Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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
20#include "gmock/gmock.h"
21#include "gtest/gtest.h"
22
23namespace flutter {
24namespace testing {
25
26namespace {
27using ::testing::AnyNumber;
28using ::testing::Return;
29
30void MockGetIntegerv(GLenum name, int* value) {
31 if (name == GL_NUM_EXTENSIONS) {
32 *value = 1;
33 } else {
34 *value = 0;
35 }
36}
37
38const 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
48const 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
56GLenum MockGetError() {
57 return GL_NO_ERROR;
58}
59
60void DoNothing() {}
61
62const 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
78class 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
140TEST_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
154TEST_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
168TEST_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
181TEST_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
205TEST_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 = {};
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
230TEST_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
245TEST_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 = {};
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
267TEST_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 = {};
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
std::function< void *(const char *function_name)> Resolver
int32_t value
@ kFlutterLayerContentTypeBackingStore
Definition embedder.h:2132
GLFWwindow * window
Definition main.cc:60
FlutterEngine engine
Definition main.cc:84
VkSurfaceKHR surface
Definition main.cc:65
FlView * view
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
EGLSurface surface_
TEST_F(DisplayListTest, Defaults)
constexpr int64_t kImplicitViewId
DEF_SWITCHES_START aot vmservice shared library name
Definition switch_defs.h:27
FlutterLayerContentType type
Definition embedder.h:2164
const FlutterBackingStore * backing_store
Definition embedder.h:2168