| Flutter Windows Embedder |

flutter_windows_texture_registrar_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 "flutter/fml/synchronization/waitable_event.h"
6 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
7 #include "flutter/shell/platform/windows/flutter_windows_engine.h"
8 #include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h"
9 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
10 #include "flutter/shell/platform/windows/testing/mock_gl_functions.h"
11 #include "gtest/gtest.h"
12
13 namespace flutter {
14 namespace testing {
15
16 using Microsoft::WRL::ComPtr;
17
18 namespace {
19 // Returns an engine instance configured with dummy project path values.
20 std::unique_ptr<FlutterWindowsEngine> GetTestEngine() {
21 FlutterDesktopEngineProperties properties = {};
22 properties.assets_path = L"C:\\foo\\flutter_assets";
23 properties.icu_data_path = L"C:\\foo\\icudtl.dat";
24 properties.aot_library_path = L"C:\\foo\\aot.so";
25 FlutterProjectBundle project(properties);
26 auto engine = std::make_unique<FlutterWindowsEngine>(project);
27
28 EngineModifier modifier(engine.get());
29 modifier.embedder_api().RegisterExternalTexture =
30 MOCK_ENGINE_PROC(RegisterExternalTexture,
31 ([](auto engine, auto texture_id) { return kSuccess; }));
32
33 return engine;
34 }
35
36 // Creates a ID3D11Texture2D with the specified size.
37 ComPtr<ID3D11Texture2D> CreateD3dTexture(FlutterWindowsEngine* engine,
38 UINT width,
39 UINT height) {
40 ComPtr<ID3D11Device> d3d_device;
41 ComPtr<ID3D11Texture2D> d3d_texture;
42 if (engine->surface_manager()->GetDevice(d3d_device.GetAddressOf())) {
43 D3D11_TEXTURE2D_DESC texture_description = {};
44 texture_description.MipLevels = 1;
45 texture_description.SampleDesc.Count = 1;
46 texture_description.BindFlags = D3D11_BIND_RENDER_TARGET;
47 texture_description.Usage = D3D11_USAGE_DEFAULT;
48 texture_description.CPUAccessFlags = 0;
49 texture_description.ArraySize = 1;
50 texture_description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
51 texture_description.Height = width;
52 texture_description.Width = height;
53 texture_description.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
54
55 d3d_device->CreateTexture2D(&texture_description, nullptr,
56 d3d_texture.GetAddressOf());
57 }
58 return d3d_texture;
59 }
60
61 } // namespace
62
63 TEST(FlutterWindowsTextureRegistrarTest, CreateDestroy) {
64 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
65 std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
66 FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
67
68 EXPECT_TRUE(true);
69 }
70
71 TEST(FlutterWindowsTextureRegistrarTest, RegisterUnregisterTexture) {
72 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
73 EngineModifier modifier(engine.get());
74 std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
75
76 FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
77
78 FlutterDesktopTextureInfo texture_info = {};
79 texture_info.type = kFlutterDesktopPixelBufferTexture;
80 texture_info.pixel_buffer_config.callback =
81 [](size_t width, size_t height,
82 void* user_data) -> const FlutterDesktopPixelBuffer* {
83 return nullptr;
84 };
85
86 int64_t registered_texture_id = 0;
87 bool register_called = false;
88 modifier.embedder_api().RegisterExternalTexture = MOCK_ENGINE_PROC(
89 RegisterExternalTexture, ([&register_called, &registered_texture_id](
90 auto engine, auto texture_id) {
91 register_called = true;
92 registered_texture_id = texture_id;
93 return kSuccess;
94 }));
95
96 bool unregister_called = false;
97 modifier.embedder_api().UnregisterExternalTexture = MOCK_ENGINE_PROC(
98 UnregisterExternalTexture, ([&unregister_called, &registered_texture_id](
99 auto engine, auto texture_id) {
100 unregister_called = true;
101 EXPECT_EQ(registered_texture_id, texture_id);
102 return kSuccess;
103 }));
104
105 bool mark_frame_available_called = false;
106 modifier.embedder_api().MarkExternalTextureFrameAvailable =
107 MOCK_ENGINE_PROC(MarkExternalTextureFrameAvailable,
108 ([&mark_frame_available_called, &registered_texture_id](
109 auto engine, auto texture_id) {
110 mark_frame_available_called = true;
111 EXPECT_EQ(registered_texture_id, texture_id);
112 return kSuccess;
113 }));
114
115 modifier.embedder_api().PostRenderThreadTask =
116 MOCK_ENGINE_PROC(PostRenderThreadTask,
117 [](auto engine, auto callback, void* callback_data) {
118 callback(callback_data);
119 return kSuccess;
120 });
121
122 auto texture_id = registrar.RegisterTexture(&texture_info);
123 EXPECT_TRUE(register_called);
124 EXPECT_NE(texture_id, -1);
125 EXPECT_EQ(texture_id, registered_texture_id);
126
127 EXPECT_TRUE(registrar.MarkTextureFrameAvailable(texture_id));
128 EXPECT_TRUE(mark_frame_available_called);
129
130 fml::AutoResetWaitableEvent latch;
131 registrar.UnregisterTexture(texture_id, [&]() { latch.Signal(); });
132 latch.Wait();
133 ASSERT_TRUE(unregister_called);
134 }
135
136 TEST(FlutterWindowsTextureRegistrarTest, RegisterUnknownTextureType) {
137 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
138 std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
139
140 FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
141
142 FlutterDesktopTextureInfo texture_info = {};
143 texture_info.type = static_cast<FlutterDesktopTextureType>(1234);
144
145 auto texture_id = registrar.RegisterTexture(&texture_info);
146
147 EXPECT_EQ(texture_id, -1);
148 }
149
150 TEST(FlutterWindowsTextureRegistrarTest, PopulatePixelBufferTexture) {
151 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
152 std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
153 FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
154
155 bool release_callback_called = false;
156 size_t width = 100;
157 size_t height = 100;
158 std::unique_ptr<uint8_t[]> pixels =
159 std::make_unique<uint8_t[]>(width * height * 4);
160 FlutterDesktopPixelBuffer pixel_buffer = {};
161 pixel_buffer.width = width;
162 pixel_buffer.height = height;
163 pixel_buffer.buffer = pixels.get();
164 pixel_buffer.release_context = &release_callback_called;
165 pixel_buffer.release_callback = [](void* release_context) {
166 bool* called = reinterpret_cast<bool*>(release_context);
167 *called = true;
168 };
169
170 FlutterDesktopTextureInfo texture_info = {};
171 texture_info.type = kFlutterDesktopPixelBufferTexture;
172 texture_info.pixel_buffer_config.user_data = &pixel_buffer;
173 texture_info.pixel_buffer_config.callback =
174 [](size_t width, size_t height,
175 void* user_data) -> const FlutterDesktopPixelBuffer* {
176 return reinterpret_cast<const FlutterDesktopPixelBuffer*>(user_data);
177 };
178
179 FlutterOpenGLTexture flutter_texture = {};
180 auto texture_id = registrar.RegisterTexture(&texture_info);
181 EXPECT_NE(texture_id, -1);
182
183 auto result =
184 registrar.PopulateTexture(texture_id, 640, 480, &flutter_texture);
185 EXPECT_TRUE(result);
186 EXPECT_EQ(flutter_texture.width, width);
187 EXPECT_EQ(flutter_texture.height, height);
188 EXPECT_EQ(flutter_texture.target, GL_TEXTURE_2D);
189 EXPECT_TRUE(release_callback_called);
190 }
191
192 TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTextureWithHandle) {
193 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
194 std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
195 FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
196
197 UINT width = 100;
198 UINT height = 100;
199 auto d3d_texture = CreateD3dTexture(engine.get(), width, height);
200 EXPECT_TRUE(d3d_texture);
201
202 ComPtr<IDXGIResource> shared_resource;
203 EXPECT_TRUE(SUCCEEDED(d3d_texture.As(&shared_resource)));
204
205 HANDLE shared_handle;
206 EXPECT_TRUE(SUCCEEDED(shared_resource->GetSharedHandle(&shared_handle)));
207
208 bool release_callback_called = false;
209 FlutterDesktopGpuSurfaceDescriptor surface_descriptor = {};
210 surface_descriptor.struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor);
211 surface_descriptor.handle = shared_handle;
212 surface_descriptor.width = surface_descriptor.visible_width = width;
213 surface_descriptor.height = surface_descriptor.visible_height = height;
214 surface_descriptor.release_context = &release_callback_called;
215 surface_descriptor.release_callback = [](void* release_context) {
216 bool* called = reinterpret_cast<bool*>(release_context);
217 *called = true;
218 };
219
220 FlutterDesktopTextureInfo texture_info = {};
221 texture_info.type = kFlutterDesktopGpuSurfaceTexture;
222 texture_info.gpu_surface_config.struct_size =
223 sizeof(FlutterDesktopGpuSurfaceTextureConfig);
224 texture_info.gpu_surface_config.type =
225 kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle;
226 texture_info.gpu_surface_config.user_data = &surface_descriptor;
227 texture_info.gpu_surface_config.callback =
228 [](size_t width, size_t height,
229 void* user_data) -> const FlutterDesktopGpuSurfaceDescriptor* {
230 return reinterpret_cast<const FlutterDesktopGpuSurfaceDescriptor*>(
231 user_data);
232 };
233
234 FlutterOpenGLTexture flutter_texture = {};
235 auto texture_id = registrar.RegisterTexture(&texture_info);
236 EXPECT_NE(texture_id, -1);
237
238 auto result =
239 registrar.PopulateTexture(texture_id, 640, 480, &flutter_texture);
240 EXPECT_TRUE(result);
241 EXPECT_EQ(flutter_texture.width, width);
242 EXPECT_EQ(flutter_texture.height, height);
243 EXPECT_EQ(flutter_texture.target, GL_TEXTURE_2D);
244 EXPECT_TRUE(release_callback_called);
245 }
246
247 TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTexture) {
248 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
249 std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
250 FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
251
252 UINT width = 100;
253 UINT height = 100;
254 auto d3d_texture = CreateD3dTexture(engine.get(), width, height);
255 EXPECT_TRUE(d3d_texture);
256
257 bool release_callback_called = false;
258 FlutterDesktopGpuSurfaceDescriptor surface_descriptor = {};
259 surface_descriptor.struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor);
260 surface_descriptor.handle = d3d_texture.Get();
261 surface_descriptor.width = surface_descriptor.visible_width = width;
262 surface_descriptor.height = surface_descriptor.visible_height = height;
263 surface_descriptor.release_context = &release_callback_called;
264 surface_descriptor.release_callback = [](void* release_context) {
265 bool* called = reinterpret_cast<bool*>(release_context);
266 *called = true;
267 };
268
269 FlutterDesktopTextureInfo texture_info = {};
270 texture_info.type = kFlutterDesktopGpuSurfaceTexture;
271 texture_info.gpu_surface_config.struct_size =
272 sizeof(FlutterDesktopGpuSurfaceTextureConfig);
273 texture_info.gpu_surface_config.type =
274 kFlutterDesktopGpuSurfaceTypeD3d11Texture2D;
275 texture_info.gpu_surface_config.user_data = &surface_descriptor;
276 texture_info.gpu_surface_config.callback =
277 [](size_t width, size_t height,
278 void* user_data) -> const FlutterDesktopGpuSurfaceDescriptor* {
279 return reinterpret_cast<const FlutterDesktopGpuSurfaceDescriptor*>(
280 user_data);
281 };
282
283 FlutterOpenGLTexture flutter_texture = {};
284 auto texture_id = registrar.RegisterTexture(&texture_info);
285 EXPECT_NE(texture_id, -1);
286
287 auto result =
288 registrar.PopulateTexture(texture_id, 640, 480, &flutter_texture);
289 EXPECT_TRUE(result);
290 EXPECT_EQ(flutter_texture.width, width);
291 EXPECT_EQ(flutter_texture.height, height);
292 EXPECT_EQ(flutter_texture.target, GL_TEXTURE_2D);
293 EXPECT_TRUE(release_callback_called);
294 }
295
296 TEST(FlutterWindowsTextureRegistrarTest, PopulateInvalidTexture) {
297 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
298 std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
299
300 FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
301
302 auto result = registrar.PopulateTexture(1, 640, 480, nullptr);
303 EXPECT_FALSE(result);
304 }
305
306 TEST(FlutterWindowsTextureRegistrarTest,
307 UnregisterTextureWithEngineDownInvokesCallback) {
308 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
309 std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
310
311 FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
312
313 fml::AutoResetWaitableEvent latch;
314 registrar.UnregisterTexture(1234, [&]() { latch.Signal(); });
315 latch.Wait();
316 }
317
318 } // namespace testing
319 } // namespace flutter
FlutterDesktopEngineProperties::aot_library_path
const wchar_t * aot_library_path
Definition: flutter_windows.h:51
flutter_windows_texture_registrar.h
FlutterDesktopEngineProperties
Definition: flutter_windows.h:36
kFlutterDesktopGpuSurfaceTexture
@ kFlutterDesktopGpuSurfaceTexture
Definition: flutter_texture_registrar.h:28
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:47
flutter::FlutterWindowsTextureRegistrar::MarkTextureFrameAvailable
bool MarkTextureFrameAvailable(int64_t texture_id)
Definition: flutter_windows_texture_registrar.cc:104
FlutterDesktopPixelBuffer
Definition: flutter_texture_registrar.h:56
flutter::FlutterWindowsTextureRegistrar::PopulateTexture
bool PopulateTexture(int64_t texture_id, size_t width, size_t height, FlutterOpenGLTexture *texture)
Definition: flutter_windows_texture_registrar.cc:112
FlutterDesktopPixelBufferTextureConfig::user_data
void * user_data
Definition: flutter_texture_registrar.h:134
FlutterDesktopGpuSurfaceDescriptor::visible_width
size_t visible_width
Definition: flutter_texture_registrar.h:93
FlutterDesktopEngineProperties::icu_data_path
const wchar_t * icu_data_path
Definition: flutter_windows.h:45
FlutterDesktopGpuSurfaceTextureConfig::user_data
void * user_data
Definition: flutter_texture_registrar.h:148
FlutterDesktopPixelBufferTextureConfig::callback
FlutterDesktopPixelBufferTextureCallback callback
Definition: flutter_texture_registrar.h:132
FlutterDesktopTextureType
FlutterDesktopTextureType
Definition: flutter_texture_registrar.h:24
FlutterDesktopGpuSurfaceDescriptor::release_callback
void(* release_callback)(void *release_context)
Definition: flutter_texture_registrar.h:100
FlutterDesktopTextureInfo::type
FlutterDesktopTextureType type
Definition: flutter_texture_registrar.h:152
flutter::FlutterWindowsTextureRegistrar
Definition: flutter_windows_texture_registrar.h:23
FlutterDesktopGpuSurfaceDescriptor::visible_height
size_t visible_height
Definition: flutter_texture_registrar.h:96
FlutterDesktopGpuSurfaceDescriptor::release_context
void * release_context
Definition: flutter_texture_registrar.h:102
FlutterDesktopGpuSurfaceTextureConfig::struct_size
size_t struct_size
Definition: flutter_texture_registrar.h:141
FlutterDesktopTextureInfo::pixel_buffer_config
FlutterDesktopPixelBufferTextureConfig pixel_buffer_config
Definition: flutter_texture_registrar.h:154
FlutterDesktopGpuSurfaceDescriptor::height
size_t height
Definition: flutter_texture_registrar.h:90
FlutterDesktopGpuSurfaceTextureConfig::type
FlutterDesktopGpuSurfaceType type
Definition: flutter_texture_registrar.h:144
FlutterDesktopTextureInfo
Definition: flutter_texture_registrar.h:151
FlutterDesktopGpuSurfaceTextureConfig::callback
FlutterDesktopGpuSurfaceTextureCallback callback
Definition: flutter_texture_registrar.h:146
FlutterDesktopPixelBuffer::release_context
void * release_context
Definition: flutter_texture_registrar.h:66
flutter
Definition: accessibility_bridge_windows.cc:11
FlutterDesktopGpuSurfaceDescriptor
Definition: flutter_texture_registrar.h:70
kFlutterDesktopGpuSurfaceTypeD3d11Texture2D
@ kFlutterDesktopGpuSurfaceTypeD3d11Texture2D
Definition: flutter_texture_registrar.h:40
FlutterDesktopTextureInfo::gpu_surface_config
FlutterDesktopGpuSurfaceTextureConfig gpu_surface_config
Definition: flutter_texture_registrar.h:155
FlutterDesktopPixelBuffer::buffer
const uint8_t * buffer
Definition: flutter_texture_registrar.h:58
kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle
@ kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle
Definition: flutter_texture_registrar.h:38
flutter_windows_engine.h
FlutterDesktopGpuSurfaceDescriptor::handle
void * handle
Definition: flutter_texture_registrar.h:86
FlutterDesktopGpuSurfaceTextureConfig
Definition: flutter_texture_registrar.h:138
FlutterDesktopPixelBuffer::width
size_t width
Definition: flutter_texture_registrar.h:60
flutter::testing::TEST
TEST(AccessibilityBridgeWindows, GetParent)
Definition: accessibility_bridge_windows_unittests.cc:233
FlutterDesktopPixelBuffer::release_callback
void(* release_callback)(void *release_context)
Definition: flutter_texture_registrar.h:64
FlutterDesktopGpuSurfaceDescriptor::struct_size
size_t struct_size
Definition: flutter_texture_registrar.h:73
FlutterDesktopEngineProperties::assets_path
const wchar_t * assets_path
Definition: flutter_windows.h:40
FlutterDesktopGpuSurfaceDescriptor::width
size_t width
Definition: flutter_texture_registrar.h:88
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24
kFlutterDesktopPixelBufferTexture
@ kFlutterDesktopPixelBufferTexture
Definition: flutter_texture_registrar.h:26
FlutterDesktopPixelBuffer::height
size_t height
Definition: flutter_texture_registrar.h:62
flutter::FlutterWindowsTextureRegistrar::UnregisterTexture
void UnregisterTexture(int64_t texture_id, fml::closure callback=nullptr)
Definition: flutter_windows_texture_registrar.cc:80
flutter::FlutterWindowsTextureRegistrar::RegisterTexture
int64_t RegisterTexture(const FlutterDesktopTextureInfo *texture_info)
Definition: flutter_windows_texture_registrar.cc:26
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:46