Flutter Engine
The Flutter Engine
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
23namespace flutter {
24namespace testing {
25
26namespace {
27using ::testing::AnyNumber;
28using ::testing::Return;
29
30const 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
40void MockGetIntegerv(GLenum name, int* value) {
41 *value = 0;
42}
43
44GLenum MockGetError() {
45 return GL_NO_ERROR;
46}
47
48void DoNothing() {}
49
50const 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
64class 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
113 private:
114 std::unique_ptr<FlutterWindowsEngine> engine_;
115 std::unique_ptr<FlutterWindowsView> view_;
116 std::unique_ptr<egl::MockContext> render_context_;
117 egl::MockWindowSurface* surface_;
118 egl::MockManager* egl_manager_;
119
120 FML_DISALLOW_COPY_AND_ASSIGN(CompositorOpenGLTest);
121};
122
123} // namespace
124
125TEST_F(CompositorOpenGLTest, CreateBackingStore) {
126 UseHeadlessEngine();
127
128 auto compositor = CompositorOpenGL{engine(), kMockResolver};
129
130 FlutterBackingStoreConfig config = {};
131 FlutterBackingStore backing_store = {};
132
133 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
134 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
135 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
136}
137
138TEST_F(CompositorOpenGLTest, InitializationFailure) {
139 UseHeadlessEngine();
140
141 auto compositor = CompositorOpenGL{engine(), kMockResolver};
142
143 FlutterBackingStoreConfig config = {};
144 FlutterBackingStore backing_store = {};
145
146 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(false));
147 EXPECT_FALSE(compositor.CreateBackingStore(config, &backing_store));
148}
149
150TEST_F(CompositorOpenGLTest, Present) {
151 UseEngineWithView();
152
153 auto compositor = CompositorOpenGL{engine(), kMockResolver};
154
155 FlutterBackingStoreConfig config = {};
156 FlutterBackingStore backing_store = {};
157
158 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
159 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
160
161 FlutterLayer layer = {};
163 layer.backing_store = &backing_store;
164 const FlutterLayer* layer_ptr = &layer;
165
166 EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
167 EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
168 EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
169 EXPECT_TRUE(compositor.Present(view(), &layer_ptr, 1));
170
171 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
172}
173
174TEST_F(CompositorOpenGLTest, PresentEmpty) {
175 UseEngineWithView();
176
177 auto compositor = CompositorOpenGL{engine(), kMockResolver};
178
179 // The context will be bound twice: first to initialize the compositor, second
180 // to clear the surface.
181 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
182 EXPECT_CALL(*surface(), IsValid).WillRepeatedly(Return(true));
183 EXPECT_CALL(*surface(), MakeCurrent).WillOnce(Return(true));
184 EXPECT_CALL(*surface(), SwapBuffers).WillOnce(Return(true));
185 EXPECT_TRUE(compositor.Present(view(), nullptr, 0));
186}
187
188TEST_F(CompositorOpenGLTest, NoSurfaceIgnored) {
189 UseEngineWithView(/*add_surface = */ false);
190
191 auto compositor = CompositorOpenGL{engine(), kMockResolver};
192
193 FlutterBackingStoreConfig config = {};
194 FlutterBackingStore backing_store = {};
195
196 EXPECT_CALL(*render_context(), MakeCurrent).WillOnce(Return(true));
197 ASSERT_TRUE(compositor.CreateBackingStore(config, &backing_store));
198
199 FlutterLayer layer = {};
201 layer.backing_store = &backing_store;
202 const FlutterLayer* layer_ptr = &layer;
203
204 EXPECT_FALSE(compositor.Present(view(), &layer_ptr, 1));
205
206 ASSERT_TRUE(compositor.CollectBackingStore(&backing_store));
207}
208
209} // namespace testing
210} // namespace flutter
std::function< void *(const char *function_name)> Resolver
@ kFlutterLayerContentTypeBackingStore
Definition: embedder.h:1793
GLFWwindow * window
Definition: main.cc:45
FlutterEngine engine
Definition: main.cc:68
VkSurfaceKHR surface
Definition: main.cc:49
uint8_t value
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27
EGLSurface surface_
SK_API GrDirectContext * GetContext(const SkImage *src)
const char *const function_name
TEST_F(DisplayListTest, Defaults)
constexpr int64_t kImplicitViewId
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
FlutterLayerContentType type
Definition: embedder.h:1824
const FlutterBackingStore * backing_store
Definition: embedder.h:1828
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678