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 const unsigned char* MockGetString(GLenum name) {
31  switch (name) {
32  case GL_VERSION:
33  case GL_SHADING_LANGUAGE_VERSION:
34  return reinterpret_cast<const unsigned char*>("3.0");
35  default:
36  return reinterpret_cast<const unsigned char*>("");
37  }
38 }
39 
40 void MockGetIntegerv(GLenum name, int* value) {
41  *value = 0;
42 }
43 
44 GLenum MockGetError() {
45  return GL_NO_ERROR;
46 }
47 
48 void DoNothing() {}
49 
50 const impeller::ProcTableGLES::Resolver kMockResolver = [](const char* name) {
51  std::string function_name{name};
52 
53  if (function_name == "glGetString") {
54  return reinterpret_cast<void*>(&MockGetString);
55  } else if (function_name == "glGetIntegerv") {
56  return reinterpret_cast<void*>(&MockGetIntegerv);
57  } else if (function_name == "glGetError") {
58  return reinterpret_cast<void*>(&MockGetError);
59  } else {
60  return reinterpret_cast<void*>(&DoNothing);
61  }
62 };
63 
64 class CompositorOpenGLTest : public WindowsTest {
65  public:
66  CompositorOpenGLTest() = default;
67  virtual ~CompositorOpenGLTest() = default;
68 
69  protected:
70  FlutterWindowsEngine* engine() { return engine_.get(); }
71  FlutterWindowsView* view() { return view_.get(); }
72  egl::MockManager* egl_manager() { return egl_manager_; }
73  egl::MockContext* render_context() { return render_context_.get(); }
74  egl::MockWindowSurface* surface() { return surface_; }
75 
76  void UseHeadlessEngine() {
77  auto egl_manager = std::make_unique<egl::MockManager>();
78  render_context_ = std::make_unique<egl::MockContext>();
79  egl_manager_ = egl_manager.get();
80 
81  EXPECT_CALL(*egl_manager_, render_context)
82  .Times(AnyNumber())
83  .WillRepeatedly(Return(render_context_.get()));
84 
85  FlutterWindowsEngineBuilder builder{GetContext()};
86 
87  engine_ = builder.Build();
88  EngineModifier modifier{engine_.get()};
89  modifier.SetEGLManager(std::move(egl_manager));
90  }
91 
92  void UseEngineWithView(bool add_surface = true) {
93  UseHeadlessEngine();
94 
95  auto window = std::make_unique<MockWindowBindingHandler>();
96  EXPECT_CALL(*window.get(), SetView).Times(1);
97  EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(nullptr));
98 
99  view_ = std::make_unique<FlutterWindowsView>(kImplicitViewId, engine_.get(),
100  std::move(window));
101 
102  if (add_surface) {
103  auto surface = std::make_unique<egl::MockWindowSurface>();
104  surface_ = surface.get();
105 
106  EXPECT_CALL(*surface_, Destroy).Times(AnyNumber());
107 
108  ViewModifier modifier{view_.get()};
109  modifier.SetSurface(std::move(surface));
110  }
111 
112  EngineModifier modifier{engine_.get()};
113  modifier.SetImplicitView(view_.get());
114  }
115 
116  private:
117  std::unique_ptr<FlutterWindowsEngine> engine_;
118  std::unique_ptr<FlutterWindowsView> view_;
119  std::unique_ptr<egl::MockContext> render_context_;
120  egl::MockWindowSurface* surface_;
121  egl::MockManager* egl_manager_;
122 
123  FML_DISALLOW_COPY_AND_ASSIGN(CompositorOpenGLTest);
124 };
125 
126 } // namespace
127 
128 TEST_F(CompositorOpenGLTest, CreateBackingStore) {
129  UseHeadlessEngine();
130 
131  auto compositor = CompositorOpenGL{engine(), kMockResolver};
132 
133  FlutterBackingStoreConfig config = {};
134  FlutterBackingStore backing_store = {};
135 
136  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
137  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
138  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
139 }
140 
141 TEST_F(CompositorOpenGLTest, InitializationFailure) {
142  UseHeadlessEngine();
143 
144  auto compositor = CompositorOpenGL{engine(), kMockResolver};
145 
146  FlutterBackingStoreConfig config = {};
147  FlutterBackingStore backing_store = {};
148 
149  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(false));
150  EXPECT_FALSE(compositor.CreateBackingStore(config, &backing_store));
151 }
152 
153 TEST_F(CompositorOpenGLTest, Present) {
154  UseEngineWithView();
155 
156  auto compositor = CompositorOpenGL{engine(), kMockResolver};
157 
158  FlutterBackingStoreConfig config = {};
159  FlutterBackingStore backing_store = {};
160 
161  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
162  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
163 
164  FlutterLayer layer = {};
165  layer.type = kFlutterLayerContentTypeBackingStore;
166  layer.backing_store = &backing_store;
167  const FlutterLayer* layer_ptr = &layer;
168 
169  EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
170  EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
171  EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
172  EXPECT_TRUE(compositor.Present(view()->view_id(), &layer_ptr, 1));
173 
174  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
175 }
176 
177 TEST_F(CompositorOpenGLTest, PresentEmpty) {
178  UseEngineWithView();
179 
180  auto compositor = CompositorOpenGL{engine(), kMockResolver};
181 
182  // The context will be bound twice: first to initialize the compositor, second
183  // to clear the surface.
184  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
185  EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
186  EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
187  EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
188  EXPECT_TRUE(compositor.Present(view()->view_id(), nullptr, 0));
189 }
190 
191 TEST_F(CompositorOpenGLTest, HeadlessPresentIgnored) {
192  UseHeadlessEngine();
193 
194  auto compositor = CompositorOpenGL{engine(), kMockResolver};
195 
196  FlutterBackingStoreConfig config = {};
197  FlutterBackingStore backing_store = {};
198 
199  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
200  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
201 
202  FlutterLayer layer = {};
203  layer.type = kFlutterLayerContentTypeBackingStore;
204  layer.backing_store = &backing_store;
205  const FlutterLayer* layer_ptr = &layer;
206 
207  EXPECT_FALSE(compositor.Present(kImplicitViewId, &layer_ptr, 1));
208 
209  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
210 }
211 
212 TEST_F(CompositorOpenGLTest, UnknownViewIgnored) {
213  UseEngineWithView();
214 
215  auto compositor = CompositorOpenGL{engine(), kMockResolver};
216 
217  FlutterBackingStoreConfig config = {};
218  FlutterBackingStore backing_store = {};
219 
220  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
221  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
222 
223  FlutterLayer layer = {};
224  layer.type = kFlutterLayerContentTypeBackingStore;
225  layer.backing_store = &backing_store;
226  const FlutterLayer* layer_ptr = &layer;
227 
228  FlutterViewId unknown_view_id = 123;
229  ASSERT_NE(view()->view_id(), unknown_view_id);
230  ASSERT_EQ(engine()->view(unknown_view_id), nullptr);
231 
232  EXPECT_FALSE(compositor.Present(unknown_view_id, &layer_ptr, 1));
233 
234  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
235 }
236 
237 TEST_F(CompositorOpenGLTest, NoSurfaceIgnored) {
238  UseEngineWithView(/*add_surface = */ false);
239 
240  auto compositor = CompositorOpenGL{engine(), kMockResolver};
241 
242  FlutterBackingStoreConfig config = {};
243  FlutterBackingStore backing_store = {};
244 
245  EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
246  ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
247 
248  FlutterLayer layer = {};
249  layer.type = kFlutterLayerContentTypeBackingStore;
250  layer.backing_store = &backing_store;
251  const FlutterLayer* layer_ptr = &layer;
252 
253  EXPECT_FALSE(compositor.Present(view()->view_id(), &layer_ptr, 1));
254 
255  ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
256 }
257 
258 } // namespace testing
259 } // namespace flutter
flutter::kImplicitViewId
constexpr FlutterViewId kImplicitViewId
Definition: flutter_windows_engine.h:54
flutter_windows_view.h
compositor_opengl.h
flutter::FlutterViewId
int64_t FlutterViewId
Definition: flutter_view.h:13
flutter
Definition: accessibility_bridge_windows.cc:11
manager.h
flutter::CompositorOpenGL
Definition: compositor_opengl.h:18
flutter::testing::TEST_F
TEST_F(CompositorOpenGLTest, CreateBackingStore)
Definition: compositor_opengl_unittests.cc:128