| 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 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