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