5 #include "flutter/fml/synchronization/waitable_event.h"
6 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
10 #include "flutter/shell/platform/windows/testing/egl/mock_proc_table.h"
11 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
12 #include "gtest/gtest.h"
18 using ::testing::AtLeast;
20 using Microsoft::WRL::ComPtr;
24 std::unique_ptr<FlutterWindowsEngine> GetTestEngine() {
26 properties.
assets_path = L
"C:\\foo\\flutter_assets";
30 FlutterProjectBundle project(properties);
31 auto engine = std::make_unique<FlutterWindowsEngine>(project);
33 EngineModifier modifier(engine.get());
34 modifier.embedder_api().RegisterExternalTexture =
35 MOCK_ENGINE_PROC(RegisterExternalTexture,
36 ([](
auto engine,
auto texture_id) {
return kSuccess; }));
42 ComPtr<ID3D11Texture2D> CreateD3dTexture(FlutterWindowsEngine* engine,
45 ComPtr<ID3D11Device> d3d_device;
46 ComPtr<ID3D11Texture2D> d3d_texture;
47 if (engine->egl_manager()->GetDevice(d3d_device.GetAddressOf())) {
48 D3D11_TEXTURE2D_DESC texture_description = {};
49 texture_description.MipLevels = 1;
50 texture_description.SampleDesc.Count = 1;
51 texture_description.BindFlags = D3D11_BIND_RENDER_TARGET;
52 texture_description.Usage = D3D11_USAGE_DEFAULT;
53 texture_description.CPUAccessFlags = 0;
54 texture_description.ArraySize = 1;
55 texture_description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
56 texture_description.Height = width;
57 texture_description.Width = height;
58 texture_description.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
60 d3d_device->CreateTexture2D(&texture_description,
nullptr,
61 d3d_texture.GetAddressOf());
68 TEST(FlutterWindowsTextureRegistrarTest, CreateDestroy) {
69 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
70 auto gl = std::make_shared<egl::MockProcTable>();
76 TEST(FlutterWindowsTextureRegistrarTest, RegisterUnregisterTexture) {
77 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
78 EngineModifier modifier(engine.get());
79 auto gl = std::make_shared<egl::MockProcTable>();
86 [](
size_t width,
size_t height,
91 int64_t registered_texture_id = 0;
92 bool register_called =
false;
93 modifier.embedder_api().RegisterExternalTexture = MOCK_ENGINE_PROC(
94 RegisterExternalTexture, ([®ister_called, ®istered_texture_id](
96 register_called =
true;
101 bool unregister_called =
false;
102 modifier.embedder_api().UnregisterExternalTexture = MOCK_ENGINE_PROC(
103 UnregisterExternalTexture, ([&unregister_called, ®istered_texture_id](
105 unregister_called =
true;
110 bool mark_frame_available_called =
false;
111 modifier.embedder_api().MarkExternalTextureFrameAvailable =
112 MOCK_ENGINE_PROC(MarkExternalTextureFrameAvailable,
113 ([&mark_frame_available_called, ®istered_texture_id](
115 mark_frame_available_called =
true;
120 modifier.embedder_api().PostRenderThreadTask =
121 MOCK_ENGINE_PROC(PostRenderThreadTask,
122 [](
auto engine,
auto callback,
void* callback_data) {
128 EXPECT_TRUE(register_called);
133 EXPECT_TRUE(mark_frame_available_called);
135 fml::AutoResetWaitableEvent latch;
138 ASSERT_TRUE(unregister_called);
141 TEST(FlutterWindowsTextureRegistrarTest, RegisterUnknownTextureType) {
142 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
143 auto gl = std::make_shared<egl::MockProcTable>();
155 TEST(FlutterWindowsTextureRegistrarTest, PopulatePixelBufferTexture) {
156 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
157 auto gl = std::make_shared<egl::MockProcTable>();
161 bool release_callback_called =
false;
164 std::unique_ptr<uint8_t[]> pixels =
165 std::make_unique<uint8_t[]>(width * height * 4);
167 pixel_buffer.
width = width;
168 pixel_buffer.
height = height;
169 pixel_buffer.
buffer = pixels.get();
172 bool* called =
reinterpret_cast<bool*
>(release_context);
180 [](
size_t width,
size_t height,
185 FlutterOpenGLTexture flutter_texture = {};
189 EXPECT_CALL(*gl.get(), GenTextures(1, _))
191 .WillOnce([](GLsizei n, GLuint* textures) { textures[0] = 1; });
192 EXPECT_CALL(*gl.get(), BindTexture).Times(1);
193 EXPECT_CALL(*gl.get(), TexParameteri).Times(AtLeast(1));
194 EXPECT_CALL(*gl.get(), TexImage2D).Times(1);
195 EXPECT_CALL(*gl.get(), DeleteTextures(1, _)).Times(1);
200 EXPECT_EQ(flutter_texture.width, width);
201 EXPECT_EQ(flutter_texture.height, height);
202 EXPECT_EQ(flutter_texture.target, GL_TEXTURE_2D);
203 EXPECT_TRUE(release_callback_called);
206 TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTextureWithHandle) {
207 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
208 auto gl = std::make_shared<egl::MockProcTable>();
213 auto d3d_texture = CreateD3dTexture(engine.get(), width, height);
214 EXPECT_TRUE(d3d_texture);
216 ComPtr<IDXGIResource> shared_resource;
217 EXPECT_TRUE(SUCCEEDED(d3d_texture.As(&shared_resource)));
219 HANDLE shared_handle;
220 EXPECT_TRUE(SUCCEEDED(shared_resource->GetSharedHandle(&shared_handle)));
222 bool release_callback_called =
false;
225 surface_descriptor.
handle = shared_handle;
230 bool* called =
reinterpret_cast<bool*
>(release_context);
242 [](
size_t width,
size_t height,
248 FlutterOpenGLTexture flutter_texture = {};
252 EXPECT_CALL(*gl.get(), GenTextures(1, _))
254 .WillOnce([](GLsizei n, GLuint* textures) { textures[0] = 1; });
255 EXPECT_CALL(*gl.get(), BindTexture).Times(1);
256 EXPECT_CALL(*gl.get(), TexParameteri).Times(AtLeast(1));
257 EXPECT_CALL(*gl.get(), DeleteTextures(1, _)).Times(1);
262 EXPECT_EQ(flutter_texture.width, width);
263 EXPECT_EQ(flutter_texture.height, height);
264 EXPECT_EQ(flutter_texture.target, GL_TEXTURE_2D);
265 EXPECT_TRUE(release_callback_called);
268 TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTexture) {
269 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
270 auto gl = std::make_shared<egl::MockProcTable>();
275 auto d3d_texture = CreateD3dTexture(engine.get(), width, height);
276 EXPECT_TRUE(d3d_texture);
278 bool release_callback_called =
false;
281 surface_descriptor.
handle = d3d_texture.Get();
286 bool* called =
reinterpret_cast<bool*
>(release_context);
298 [](
size_t width,
size_t height,
304 FlutterOpenGLTexture flutter_texture = {};
308 EXPECT_CALL(*gl.get(), GenTextures(1, _))
310 .WillOnce([](GLsizei n, GLuint* textures) { textures[0] = 1; });
311 EXPECT_CALL(*gl.get(), BindTexture).Times(1);
312 EXPECT_CALL(*gl.get(), TexParameteri).Times(AtLeast(1));
313 EXPECT_CALL(*gl.get(), DeleteTextures(1, _)).Times(1);
318 EXPECT_EQ(flutter_texture.width, width);
319 EXPECT_EQ(flutter_texture.height, height);
320 EXPECT_EQ(flutter_texture.target, GL_TEXTURE_2D);
321 EXPECT_TRUE(release_callback_called);
324 TEST(FlutterWindowsTextureRegistrarTest, PopulateInvalidTexture) {
325 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
326 auto gl = std::make_shared<egl::MockProcTable>();
331 EXPECT_FALSE(result);
334 TEST(FlutterWindowsTextureRegistrarTest,
335 UnregisterTextureWithEngineDownInvokesCallback) {
336 std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
337 auto gl = std::make_shared<egl::MockProcTable>();
341 fml::AutoResetWaitableEvent latch;
bool PopulateTexture(int64_t texture_id, size_t width, size_t height, FlutterOpenGLTexture *texture)
int64_t RegisterTexture(const FlutterDesktopTextureInfo *texture_info)
void UnregisterTexture(int64_t texture_id, fml::closure callback=nullptr)
bool MarkTextureFrameAvailable(int64_t texture_id)
@ kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle
@ kFlutterDesktopGpuSurfaceTypeD3d11Texture2D
FlutterDesktopTextureType
@ kFlutterDesktopGpuSurfaceTexture
@ kFlutterDesktopPixelBufferTexture
FlutterDesktopBinaryReply callback
TEST(AccessibilityBridgeWindows, GetParent)
const wchar_t * icu_data_path
const wchar_t * assets_path
FlutterDesktopImpellerSwitch impeller_switch
const wchar_t * aot_library_path
void(* release_callback)(void *release_context)
FlutterDesktopGpuSurfaceTextureCallback callback
FlutterDesktopGpuSurfaceType type
void(* release_callback)(void *release_context)
FlutterDesktopPixelBufferTextureCallback callback
FlutterDesktopGpuSurfaceTextureConfig gpu_surface_config
FlutterDesktopTextureType type
FlutterDesktopPixelBufferTextureConfig pixel_buffer_config