| Flutter Windows Embedder |

compositor_opengl_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <memory>
6 #include <vector>
7
8 #include "flutter/impeller/renderer/backend/gles/gles.h"
9 #include "flutter/shell/platform/windows/compositor_opengl.h"
10 #include "flutter/shell/platform/windows/egl/manager.h"
11 #include "flutter/shell/platform/windows/flutter_windows_view.h"
12 #include "flutter/shell/platform/windows/testing/egl/mock_context.h"
13 #include "flutter/shell/platform/windows/testing/egl/mock_manager.h"
14 #include "flutter/shell/platform/windows/testing/egl/mock_window_surface.h"
15 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
16 #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
17 #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
18 #include "flutter/shell/platform/windows/testing/view_modifier.h"
19 #include "flutter/shell/platform/windows/testing/windows_test.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22
23 namespace flutter {
24 namespace testing {
25
26 namespace {
27 using ::testing::AnyNumber;
28 using ::testing::Return;
29
30 void MockGetIntegerv(GLenum name, int* value) {
31 if (name == GL_NUM_EXTENSIONS) {
32 *value = 1;
33 } else {
34 *value = 0;
35 }
36 }
37
38 const unsigned char* MockGetString(GLenum name) {
39 switch (name) {
40 case GL_VERSION:
41 case GL_SHADING_LANGUAGE_VERSION:
42 return reinterpret_cast<const unsigned char*>("3.0");
43 default:
44 return reinterpret_cast<const unsigned char*>("");
45 }
46 }
47
48 const unsigned char* MockGetStringi(GLenum name, int index) {
49 if (name == GL_EXTENSIONS) {
50 return reinterpret_cast<const unsigned char*>("GL_ANGLE_framebuffer_blit");
51 } else {
52 return reinterpret_cast<const unsigned char*>("");
53 }
54 }
55
56 GLenum MockGetError() {
57 return GL_NO_ERROR;
58 }
59
60 void DoNothing() {}
61
62 const impeller::ProcTableGLES::Resolver kMockResolver = [](const char* name) {
63 std::string function_name{name};
64
65 if (function_name == "glGetString") {
66 return reinterpret_cast<void*>(&MockGetString);
67 } else if (function_name == "glGetStringi") {
68 return reinterpret_cast<void*>(&MockGetStringi);
69 } else if (function_name == "glGetIntegerv") {
70 return reinterpret_cast<void*>(&MockGetIntegerv);
71 } else if (function_name == "glGetError") {
72 return reinterpret_cast<void*>(&MockGetError);
73 } else {
74 return reinterpret_cast<void*>(&DoNothing);
75 }
76 };
77
78 class CompositorOpenGLTest : public WindowsTest {
79 public:
80 CompositorOpenGLTest() = default;
81 virtual ~CompositorOpenGLTest() = default;
82
83 protected:
84 FlutterWindowsEngine* engine() { return engine_.get(); }
85 FlutterWindowsView* view() { return view_.get(); }
86 egl::MockManager* egl_manager() { return egl_manager_; }
87 egl::MockContext* render_context() { return render_context_.get(); }
88 egl::MockWindowSurface* surface() { return surface_; }
89
90 void UseHeadlessEngine() {
91 auto egl_manager = std::make_unique<egl::MockManager>();
92 render_context_ = std::make_unique<egl::MockContext>();
93 egl_manager_ = egl_manager.get();
94
95 EXPECT_CALL(*egl_manager_, render_context)
96 .Times(AnyNumber())
97 .WillRepeatedly(Return(render_context_.get()));
98
99 FlutterWindowsEngineBuilder builder{GetContext()};
100
101 engine_ = builder.Build();
102 EngineModifier modifier{engine_.get()};
103 modifier.SetEGLManager(std::move(egl_manager));
104 }
105
106 void UseEngineWithView(bool add_surface = true) {
107 UseHeadlessEngine();
108
109 auto window = std::make_unique<MockWindowBindingHandler>();
110 EXPECT_CALL(*window.get(), SetView).Times(1);
111 EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(nullptr));
112
113 view_ = std::make_unique<FlutterWindowsView>(kImplicitViewId, engine_.get(),
114 std::move(window));
115
116 if (add_surface) {
117 auto surface = std::make_unique<egl::MockWindowSurface>();
118 surface_ = surface.get();
119
120 EXPECT_CALL(*surface_, Destroy).Times(AnyNumber());
121
122 ViewModifier modifier{view_.get()};
123 modifier.SetSurface(std::move(surface));
124 }
125 }
126
127 private:
128 std::unique_ptr<FlutterWindowsEngine> engine_;
129 std::unique_ptr<FlutterWindowsView> view_;
130 std::unique_ptr<egl::MockContext> render_context_;
131 egl::MockWindowSurface* surface_;
132 egl::MockManager* egl_manager_;
133
134 FML_DISALLOW_COPY_AND_ASSIGN(CompositorOpenGLTest);
135 };
136
137 } // namespace
138
139 TEST_F(CompositorOpenGLTest, CreateBackingStore) {
140 UseHeadlessEngine();
141
142 auto compositor =
143 CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
144
145 FlutterBackingStoreConfig config = {};
146 FlutterBackingStore backing_store = {};
147
148 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
149 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
150 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
151 }
152
153 TEST_F(CompositorOpenGLTest, CreateBackingStoreImpeller) {
154 UseHeadlessEngine();
155
156 auto compositor =
157 CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/true};
158
159 FlutterBackingStoreConfig config = {};
160 FlutterBackingStore backing_store = {};
161
162 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
163 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
164 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
165 }
166
167 TEST_F(CompositorOpenGLTest, InitializationFailure) {
168 UseHeadlessEngine();
169
170 auto compositor =
171 CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
172
173 FlutterBackingStoreConfig config = {};
174 FlutterBackingStore backing_store = {};
175
176 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(false));
177 EXPECT_FALSE(compositor.CreateBackingStore(config, &backing_store));
178 }
179
180 TEST_F(CompositorOpenGLTest, InitializationRequiresBlit) {
181 UseHeadlessEngine();
182
183 const impeller::ProcTableGLES::Resolver resolver = [](const char* name) {
184 std::string function_name{name};
185
186 if (function_name == "glBlitFramebuffer" ||
187 function_name == "glBlitFramebufferANGLE") {
188 return (void*)nullptr;
189 }
190
191 return kMockResolver(name);
192 };
193
194 auto compositor =
195 CompositorOpenGL{engine(), resolver, /*enable_impeller=*/false};
196
197 FlutterBackingStoreConfig config = {};
198 FlutterBackingStore backing_store = {};
199
200 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
201 ASSERT_FALSE(compositor.CreateBackingStore(config, &backing_store));
202 }
203
204 TEST_F(CompositorOpenGLTest, Present) {
205 UseEngineWithView();
206
207 auto compositor =
208 CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
209
210 FlutterBackingStoreConfig config = {};
211 FlutterBackingStore backing_store = {};
212
213 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
214 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
215
216 FlutterLayer layer = {};
217 layer.type = kFlutterLayerContentTypeBackingStore;
218 layer.backing_store = &backing_store;
219 const FlutterLayer* layer_ptr = &layer;
220
221 EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
222 EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
223 EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
224 EXPECT_TRUE(compositor.Present(view(), &layer_ptr, 1));
225
226 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
227 }
228
229 TEST_F(CompositorOpenGLTest, PresentEmpty) {
230 UseEngineWithView();
231
232 auto compositor =
233 CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
234
235 // The context will be bound twice: first to initialize the compositor, second
236 // to clear the surface.
237 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
238 EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
239 EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
240 EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
241 EXPECT_TRUE(compositor.Present(view(), nullptr, 0));
242 }
243
244 TEST_F(CompositorOpenGLTest, NoSurfaceIgnored) {
245 UseEngineWithView(/*add_surface = */ false);
246
247 auto compositor =
248 CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
249
250 FlutterBackingStoreConfig config = {};
251 FlutterBackingStore backing_store = {};
252
253 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
254 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
255
256 FlutterLayer layer = {};
257 layer.type = kFlutterLayerContentTypeBackingStore;
258 layer.backing_store = &backing_store;
259 const FlutterLayer* layer_ptr = &layer;
260
261 EXPECT_FALSE(compositor.Present(view(), &layer_ptr, 1));
262
263 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
264 }
265
266 TEST_F(CompositorOpenGLTest, PresentUsingANGLEBlitExtension) {
267 UseEngineWithView();
268
269 bool resolved_ANGLE_blit = false;
270 const impeller::ProcTableGLES::Resolver resolver =
271 [&resolved_ANGLE_blit](const char* name) {
272 std::string function_name{name};
273
274 if (function_name == "glBlitFramebuffer") {
275 return (void*)nullptr;
276 } else if (function_name == "glBlitFramebufferANGLE") {
277 resolved_ANGLE_blit = true;
278 return reinterpret_cast<void*>(&DoNothing);
279 }
280
281 return kMockResolver(name);
282 };
283
284 auto compositor =
285 CompositorOpenGL{engine(), resolver, /*enable_impeller=*/false};
286
287 FlutterBackingStoreConfig config = {};
288 FlutterBackingStore backing_store = {};
289
290 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
291 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
292
293 FlutterLayer layer = {};
294 layer.type = kFlutterLayerContentTypeBackingStore;
295 layer.backing_store = &backing_store;
296 const FlutterLayer* layer_ptr = &layer;
297
298 EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
299 EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
300 EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
301 EXPECT_TRUE(compositor.Present(view(), &layer_ptr, 1));
302 EXPECT_TRUE(resolved_ANGLE_blit);
303
304 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
305 }
306
307 } // namespace testing
308 } // namespace flutter
flutter::CompositorOpenGL
Definition: compositor_opengl.h:19
compositor_opengl.h
flutter_windows_view.h
manager.h
flutter::testing::TEST_F
TEST_F(CompositorOpenGLTest, CreateBackingStore)
Definition: compositor_opengl_unittests.cc:139
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::kImplicitViewId
constexpr FlutterViewId kImplicitViewId
Definition: flutter_windows_engine.h:55