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"
27 using ::testing::AnyNumber;
28 using ::testing::Return;
30 void MockGetIntegerv(GLenum name,
int* value) {
31 if (name == GL_NUM_EXTENSIONS) {
38 const unsigned char* MockGetString(GLenum name) {
41 case GL_SHADING_LANGUAGE_VERSION:
42 return reinterpret_cast<const unsigned char*
>(
"3.0");
44 return reinterpret_cast<const unsigned char*
>(
"");
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");
52 return reinterpret_cast<const unsigned char*
>(
"");
56 GLenum MockGetError() {
60 void MockGetIntegervWithMSAA(GLenum name,
int* value) {
61 if (name == GL_NUM_EXTENSIONS) {
68 const unsigned char* MockGetStringiWithMSAA(GLenum name,
int index) {
69 static constexpr
const char* extensions[] = {
70 "GL_ANGLE_framebuffer_blit",
"GL_EXT_multisampled_render_to_texture"};
71 if (name == GL_EXTENSIONS && index < 2) {
72 return reinterpret_cast<const unsigned char*
>(extensions[index]);
74 return reinterpret_cast<const unsigned char*
>(
"");
79 const impeller::ProcTableGLES::Resolver kMockResolver = [](
const char* name) {
80 std::string function_name{name};
82 if (function_name ==
"glGetString") {
83 return reinterpret_cast<void*
>(&MockGetString);
84 }
else if (function_name ==
"glGetStringi") {
85 return reinterpret_cast<void*
>(&MockGetStringi);
86 }
else if (function_name ==
"glGetIntegerv") {
87 return reinterpret_cast<void*
>(&MockGetIntegerv);
88 }
else if (function_name ==
"glGetError") {
89 return reinterpret_cast<void*
>(&MockGetError);
91 return reinterpret_cast<void*
>(&DoNothing);
95 const impeller::ProcTableGLES::Resolver kMockResolverWithMSAA =
96 [](
const char* name) {
97 std::string_view function_name{name};
99 if (function_name ==
"glGetStringi") {
100 return reinterpret_cast<void*
>(&MockGetStringiWithMSAA);
101 }
else if (function_name ==
"glGetIntegerv") {
102 return reinterpret_cast<void*
>(&MockGetIntegervWithMSAA);
104 return kMockResolver(name);
107 void MockGetIntegervWithOffscreenMSAA(GLenum name,
int* value) {
108 if (name == GL_NUM_EXTENSIONS) {
110 }
else if (name == GL_MAX_SAMPLES) {
117 const unsigned char* MockGetStringWithOffscreenMSAA(GLenum name) {
120 return reinterpret_cast<const unsigned char*
>(
"OpenGL ES 3.0");
121 case GL_SHADING_LANGUAGE_VERSION:
122 return reinterpret_cast<const unsigned char*
>(
"OpenGL ES GLSL ES 3.0");
124 return reinterpret_cast<const unsigned char*
>(
"");
128 const impeller::ProcTableGLES::Resolver kMockResolverWithOffscreenMSAA =
129 [](
const char* name) ->
void* {
130 std::string_view function_name{name};
132 if (function_name ==
"glGetString") {
133 return reinterpret_cast<void*
>(&MockGetStringWithOffscreenMSAA);
134 }
else if (function_name ==
"glGetIntegerv") {
135 return reinterpret_cast<void*
>(&MockGetIntegervWithOffscreenMSAA);
137 return kMockResolver(name);
140 class CompositorOpenGLTest :
public WindowsTest {
142 CompositorOpenGLTest() =
default;
143 virtual ~CompositorOpenGLTest() =
default;
146 FlutterWindowsEngine* engine() {
return engine_.get(); }
147 FlutterWindowsView* view() {
return view_.get(); }
148 egl::MockManager* egl_manager() {
return egl_manager_; }
149 egl::MockContext* render_context() {
return render_context_.get(); }
150 egl::MockWindowSurface* surface() {
return surface_; }
152 void UseHeadlessEngine() {
153 auto egl_manager = std::make_unique<egl::MockManager>();
154 render_context_ = std::make_unique<egl::MockContext>();
155 egl_manager_ = egl_manager.get();
157 EXPECT_CALL(*egl_manager_, render_context)
159 .WillRepeatedly(Return(render_context_.get()));
161 FlutterWindowsEngineBuilder builder{GetContext()};
163 engine_ = builder.Build();
164 EngineModifier modifier{engine_.get()};
165 modifier.SetEGLManager(std::move(egl_manager));
168 void UseEngineWithView(
bool add_surface =
true) {
171 auto window = std::make_unique<MockWindowBindingHandler>();
172 EXPECT_CALL(*window.get(), SetView).Times(1);
173 EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(
nullptr));
175 view_ = std::make_unique<FlutterWindowsView>(
kImplicitViewId, engine_.get(),
176 std::move(window),
false,
180 auto surface = std::make_unique<egl::MockWindowSurface>();
181 surface_ = surface.get();
183 EXPECT_CALL(*surface_, Destroy).Times(AnyNumber());
185 ViewModifier modifier{view_.get()};
186 modifier.SetSurface(std::move(surface));
191 std::unique_ptr<FlutterWindowsEngine> engine_;
192 std::unique_ptr<FlutterWindowsView> view_;
193 std::unique_ptr<egl::MockContext> render_context_;
194 egl::MockWindowSurface* surface_;
195 egl::MockManager* egl_manager_;
197 FML_DISALLOW_COPY_AND_ASSIGN(CompositorOpenGLTest);
202 TEST_F(CompositorOpenGLTest, CreateBackingStore) {
208 FlutterBackingStoreConfig config = {};
209 FlutterBackingStore backing_store = {};
211 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
212 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
213 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
216 TEST_F(CompositorOpenGLTest, CreateBackingStoreImpellerNoMSAA) {
219 static int framebuffer_texture2d_calls = 0;
220 static int framebuffer_texture2d_multisample_calls = 0;
221 framebuffer_texture2d_calls = 0;
222 framebuffer_texture2d_multisample_calls = 0;
224 const impeller::ProcTableGLES::Resolver resolver =
225 [](
const char* name) ->
void* {
226 std::string_view function_name{name};
227 if (function_name ==
"glFramebufferTexture2D") {
228 return reinterpret_cast<void*
>(
229 +[](GLenum, GLenum, GLenum, GLuint, GLint) {
230 framebuffer_texture2d_calls++;
232 }
else if (function_name ==
"glFramebufferTexture2DMultisampleEXT") {
233 return reinterpret_cast<void*
>(
234 +[](GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) {
235 framebuffer_texture2d_multisample_calls++;
238 return kMockResolver(name);
243 FlutterBackingStoreConfig config = {};
244 FlutterBackingStore backing_store = {};
246 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
247 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
248 EXPECT_EQ(framebuffer_texture2d_calls, 1);
249 EXPECT_EQ(framebuffer_texture2d_multisample_calls, 0);
250 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
253 TEST_F(CompositorOpenGLTest, CreateBackingStoreImpellerMSAA) {
256 static int framebuffer_texture2d_calls = 0;
257 static int framebuffer_texture2d_multisample_calls = 0;
258 framebuffer_texture2d_calls = 0;
259 framebuffer_texture2d_multisample_calls = 0;
261 const impeller::ProcTableGLES::Resolver resolver =
262 [](
const char* name) ->
void* {
263 std::string_view function_name{name};
264 if (function_name ==
"glFramebufferTexture2D") {
265 return reinterpret_cast<void*
>(
266 +[](GLenum, GLenum, GLenum, GLuint, GLint) {
267 framebuffer_texture2d_calls++;
269 }
else if (function_name ==
"glFramebufferTexture2DMultisampleEXT") {
270 return reinterpret_cast<void*
>(
271 +[](GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) {
272 framebuffer_texture2d_multisample_calls++;
275 return kMockResolverWithMSAA(name);
280 FlutterBackingStoreConfig config = {};
281 FlutterBackingStore backing_store = {};
283 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
284 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
285 EXPECT_EQ(framebuffer_texture2d_calls, 0);
286 EXPECT_EQ(framebuffer_texture2d_multisample_calls, 1);
287 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
293 TEST_F(CompositorOpenGLTest, CreateBackingStoreImpellerOffscreenMSAA) {
296 static int framebuffer_texture2d_calls = 0;
297 static int framebuffer_texture2d_multisample_calls = 0;
298 static int renderbuffer_storage_multisample_calls = 0;
299 static int renderbuffer_storage_multisample_samples = 0;
300 static int framebuffer_renderbuffer_calls = 0;
301 static int delete_renderbuffers_calls = 0;
302 static int delete_textures_calls = 0;
304 framebuffer_texture2d_calls = 0;
305 framebuffer_texture2d_multisample_calls = 0;
306 renderbuffer_storage_multisample_calls = 0;
307 renderbuffer_storage_multisample_samples = 0;
308 framebuffer_renderbuffer_calls = 0;
309 delete_renderbuffers_calls = 0;
310 delete_textures_calls = 0;
312 const impeller::ProcTableGLES::Resolver resolver =
313 [](
const char* name) ->
void* {
314 std::string_view function_name{name};
315 if (function_name ==
"glFramebufferTexture2D") {
316 return reinterpret_cast<void*
>(
317 +[](GLenum, GLenum, GLenum, GLuint, GLint) {
318 framebuffer_texture2d_calls++;
320 }
else if (function_name ==
"glFramebufferTexture2DMultisampleEXT") {
321 return reinterpret_cast<void*
>(
322 +[](GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) {
323 framebuffer_texture2d_multisample_calls++;
325 }
else if (function_name ==
"glGenRenderbuffers") {
326 return reinterpret_cast<void*
>(+[](GLsizei n, GLuint* renderbuffers) {
327 static GLuint next_id = 1;
328 for (GLsizei i = 0; i < n; i++) {
329 renderbuffers[i] = next_id++;
332 }
else if (function_name ==
"glRenderbufferStorageMultisample") {
333 return reinterpret_cast<void*
>(+[](GLenum target, GLsizei samples,
334 GLenum internalformat, GLsizei width,
336 renderbuffer_storage_multisample_calls++;
337 renderbuffer_storage_multisample_samples = samples;
339 }
else if (function_name ==
"glFramebufferRenderbuffer") {
340 return reinterpret_cast<void*
>(+[](GLenum, GLenum, GLenum, GLuint) {
341 framebuffer_renderbuffer_calls++;
343 }
else if (function_name ==
"glDeleteRenderbuffers") {
344 return reinterpret_cast<void*
>(
345 +[](GLsizei n,
const GLuint* renderbuffers) {
346 delete_renderbuffers_calls += n;
348 }
else if (function_name ==
"glDeleteTextures") {
349 return reinterpret_cast<void*
>(+[](GLsizei n,
const GLuint* textures) {
350 delete_textures_calls += n;
353 return kMockResolverWithOffscreenMSAA(name);
358 FlutterBackingStoreConfig config = {};
359 FlutterBackingStore backing_store = {};
361 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
362 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
363 EXPECT_EQ(framebuffer_texture2d_calls, 0);
364 EXPECT_EQ(framebuffer_texture2d_multisample_calls, 0);
365 EXPECT_EQ(renderbuffer_storage_multisample_calls, 2);
366 EXPECT_EQ(renderbuffer_storage_multisample_samples, 4);
367 EXPECT_EQ(framebuffer_renderbuffer_calls, 3);
369 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
370 EXPECT_EQ(delete_renderbuffers_calls, 2);
371 EXPECT_EQ(delete_textures_calls, 0);
374 TEST_F(CompositorOpenGLTest, InitializationFailure) {
380 FlutterBackingStoreConfig config = {};
381 FlutterBackingStore backing_store = {};
383 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
false));
384 EXPECT_FALSE(compositor.CreateBackingStore(config, &backing_store));
387 TEST_F(CompositorOpenGLTest, InitializationRequiresBlit) {
390 const impeller::ProcTableGLES::Resolver resolver = [](
const char* name) {
391 std::string function_name{name};
393 if (function_name ==
"glBlitFramebuffer" ||
394 function_name ==
"glBlitFramebufferANGLE") {
395 return (
void*)
nullptr;
398 return kMockResolver(name);
404 FlutterBackingStoreConfig config = {};
405 FlutterBackingStore backing_store = {};
407 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
408 ASSERT_FALSE(compositor.CreateBackingStore(config, &backing_store));
417 FlutterBackingStoreConfig config = {};
418 FlutterBackingStore backing_store = {};
420 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
421 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
423 FlutterLayer layer = {};
424 layer.type = kFlutterLayerContentTypeBackingStore;
425 layer.backing_store = &backing_store;
426 const FlutterLayer* layer_ptr = &layer;
428 EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(
true));
429 EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(
true));
430 EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(
true));
431 EXPECT_TRUE(compositor.Present(view(), &layer_ptr, 1));
433 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
436 TEST_F(CompositorOpenGLTest, PresentEmpty) {
444 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
445 EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(
true));
446 EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(
true));
447 EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(
true));
448 EXPECT_TRUE(compositor.Present(view(),
nullptr, 0));
451 TEST_F(CompositorOpenGLTest, NoSurfaceIgnored) {
452 UseEngineWithView(
false);
457 FlutterBackingStoreConfig config = {};
458 FlutterBackingStore backing_store = {};
460 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
461 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
463 FlutterLayer layer = {};
464 layer.type = kFlutterLayerContentTypeBackingStore;
465 layer.backing_store = &backing_store;
466 const FlutterLayer* layer_ptr = &layer;
468 EXPECT_FALSE(compositor.Present(view(), &layer_ptr, 1));
470 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
473 TEST_F(CompositorOpenGLTest, PresentUsingANGLEBlitExtension) {
476 bool resolved_ANGLE_blit =
false;
477 const impeller::ProcTableGLES::Resolver resolver =
478 [&resolved_ANGLE_blit](
const char* name) {
479 std::string function_name{name};
481 if (function_name ==
"glBlitFramebuffer") {
482 return (
void*)
nullptr;
483 }
else if (function_name ==
"glBlitFramebufferANGLE") {
484 resolved_ANGLE_blit =
true;
485 return reinterpret_cast<void*
>(&DoNothing);
488 return kMockResolver(name);
494 FlutterBackingStoreConfig config = {};
495 FlutterBackingStore backing_store = {};
497 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(
true));
498 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
500 FlutterLayer layer = {};
501 layer.type = kFlutterLayerContentTypeBackingStore;
502 layer.backing_store = &backing_store;
503 const FlutterLayer* layer_ptr = &layer;
505 EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(
true));
506 EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(
true));
507 EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(
true));
508 EXPECT_TRUE(compositor.Present(view(), &layer_ptr, 1));
509 EXPECT_TRUE(resolved_ANGLE_blit);
511 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
constexpr FlutterViewId kImplicitViewId