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"
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), false,
115  BoxConstraints());
116 
117  if (add_surface) {
118  auto surface = std::make_unique<egl::MockWindowSurface>();
119  surface_ = surface.get();
120 
121  EXPECT_CALL(*surface_, Destroy).Times(AnyNumber());
122 
123  ViewModifier modifier{view_.get()};
124  modifier.SetSurface(std::move(surface));
125  }
126  }
127 
128  private:
129  std::unique_ptr<FlutterWindowsEngine> engine_;
130  std::unique_ptr<FlutterWindowsView> view_;
131  std::unique_ptr<egl::MockContext> render_context_;
132  egl::MockWindowSurface* surface_;
133  egl::MockManager* egl_manager_;
134 
135  FML_DISALLOW_COPY_AND_ASSIGN(CompositorOpenGLTest);
136 };
137 
138 } // namespace
139 
140 TEST_F(CompositorOpenGLTest, CreateBackingStore) {
141  UseHeadlessEngine();
142 
143  auto compositor =
144  CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
145 
146  FlutterBackingStoreConfig config = {};
147  FlutterBackingStore backing_store = {};
148 
149  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
150  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
151  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
152 }
153 
154 TEST_F(CompositorOpenGLTest, CreateBackingStoreImpeller) {
155  UseHeadlessEngine();
156 
157  auto compositor =
158  CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/true};
159 
160  FlutterBackingStoreConfig config = {};
161  FlutterBackingStore backing_store = {};
162 
163  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
164  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
165  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
166 }
167 
168 TEST_F(CompositorOpenGLTest, InitializationFailure) {
169  UseHeadlessEngine();
170 
171  auto compositor =
172  CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
173 
174  FlutterBackingStoreConfig config = {};
175  FlutterBackingStore backing_store = {};
176 
177  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(false));
178  EXPECT_FALSE(compositor.CreateBackingStore(config, &backing_store));
179 }
180 
181 TEST_F(CompositorOpenGLTest, InitializationRequiresBlit) {
182  UseHeadlessEngine();
183 
184  const impeller::ProcTableGLES::Resolver resolver = [](const char* name) {
185  std::string function_name{name};
186 
187  if (function_name == "glBlitFramebuffer" ||
188  function_name == "glBlitFramebufferANGLE") {
189  return (void*)nullptr;
190  }
191 
192  return kMockResolver(name);
193  };
194 
195  auto compositor =
196  CompositorOpenGL{engine(), resolver, /*enable_impeller=*/false};
197 
198  FlutterBackingStoreConfig config = {};
199  FlutterBackingStore backing_store = {};
200 
201  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
202  ASSERT_FALSE(compositor.CreateBackingStore(config, &backing_store));
203 }
204 
205 TEST_F(CompositorOpenGLTest, Present) {
206  UseEngineWithView();
207 
208  auto compositor =
209  CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
210 
211  FlutterBackingStoreConfig config = {};
212  FlutterBackingStore backing_store = {};
213 
214  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
215  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
216 
217  FlutterLayer layer = {};
218  layer.type = kFlutterLayerContentTypeBackingStore;
219  layer.backing_store = &backing_store;
220  const FlutterLayer* layer_ptr = &layer;
221 
222  EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
223  EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
224  EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
225  EXPECT_TRUE(compositor.Present(view(), &layer_ptr, 1));
226 
227  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
228 }
229 
230 TEST_F(CompositorOpenGLTest, PresentEmpty) {
231  UseEngineWithView();
232 
233  auto compositor =
234  CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
235 
236  // The context will be bound twice: first to initialize the compositor, second
237  // to clear the surface.
238  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
239  EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
240  EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
241  EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
242  EXPECT_TRUE(compositor.Present(view(), nullptr, 0));
243 }
244 
245 TEST_F(CompositorOpenGLTest, NoSurfaceIgnored) {
246  UseEngineWithView(/*add_surface = */ false);
247 
248  auto compositor =
249  CompositorOpenGL{engine(), kMockResolver, /*enable_impeller=*/false};
250 
251  FlutterBackingStoreConfig config = {};
252  FlutterBackingStore backing_store = {};
253 
254  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
255  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
256 
257  FlutterLayer layer = {};
258  layer.type = kFlutterLayerContentTypeBackingStore;
259  layer.backing_store = &backing_store;
260  const FlutterLayer* layer_ptr = &layer;
261 
262  EXPECT_FALSE(compositor.Present(view(), &layer_ptr, 1));
263 
264  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
265 }
266 
267 TEST_F(CompositorOpenGLTest, PresentUsingANGLEBlitExtension) {
268  UseEngineWithView();
269 
270  bool resolved_ANGLE_blit = false;
271  const impeller::ProcTableGLES::Resolver resolver =
272  [&resolved_ANGLE_blit](const char* name) {
273  std::string function_name{name};
274 
275  if (function_name == "glBlitFramebuffer") {
276  return (void*)nullptr;
277  } else if (function_name == "glBlitFramebufferANGLE") {
278  resolved_ANGLE_blit = true;
279  return reinterpret_cast<void*>(&DoNothing);
280  }
281 
282  return kMockResolver(name);
283  };
284 
285  auto compositor =
286  CompositorOpenGL{engine(), resolver, /*enable_impeller=*/false};
287 
288  FlutterBackingStoreConfig config = {};
289  FlutterBackingStore backing_store = {};
290 
291  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
292  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
293 
294  FlutterLayer layer = {};
295  layer.type = kFlutterLayerContentTypeBackingStore;
296  layer.backing_store = &backing_store;
297  const FlutterLayer* layer_ptr = &layer;
298 
299  EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
300  EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
301  EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
302  EXPECT_TRUE(compositor.Present(view(), &layer_ptr, 1));
303  EXPECT_TRUE(resolved_ANGLE_blit);
304 
305  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
306 }
307 
308 } // namespace testing
309 } // namespace flutter
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
constexpr FlutterViewId kImplicitViewId