From ca30228f770a3c107a6c1eb43c3cb54e29647782 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Tue, 27 Jan 2026 02:25:10 +0800 Subject: [PATCH 1/7] Fix fail to render pixel buffer issue --- .../shell/platform/embedder/embedder_external_texture_gl.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc index fe81731aff0d5..bb06cab4e9e77 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc @@ -140,11 +140,12 @@ sk_sp EmbedderExternalTextureGL::ResolveTextureImpeller( impeller::TextureDescriptor desc; desc.size = impeller::ISize(texture->width, texture->height); + desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt; impeller::ContextGLES& context = impeller::ContextGLES::Cast(*aiks_context->GetContext()); impeller::HandleGLES handle = context.GetReactor()->CreateHandle( - impeller::HandleType::kTexture, texture->target); + impeller::HandleType::kTexture, texture->name); std::shared_ptr image = impeller::TextureGLES::WrapTexture(context.GetReactor(), desc, handle); @@ -165,6 +166,8 @@ sk_sp EmbedderExternalTextureGL::ResolveTextureImpeller( FML_LOG(ERROR) << "Could not register destruction callback"; return nullptr; } + image->SetCoordinateSystem( + impeller::TextureCoordinateSystem::kUploadFromHost); return impeller::DlImageImpeller::Make(image); } From 999ef41c45c5d5c283a0d5b525e2e1c177a0bee8 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Tue, 10 Feb 2026 01:49:45 +0800 Subject: [PATCH 2/7] Add unit test --- .../platform/embedder/fixtures/main.dart | 19 +++++ .../embedder/tests/embedder_gl_unittests.cc | 74 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/engine/src/flutter/shell/platform/embedder/fixtures/main.dart b/engine/src/flutter/shell/platform/embedder/fixtures/main.dart index ea4f16371a5a9..bb9b2dababb55 100644 --- a/engine/src/flutter/shell/platform/embedder/fixtures/main.dart +++ b/engine/src/flutter/shell/platform/embedder/fixtures/main.dart @@ -1576,6 +1576,25 @@ void render_impeller_test() { PlatformDispatcher.instance.scheduleFrame(); } +@pragma('vm:entry-point') +// ignore: non_constant_identifier_names +void render_texture_impeller_test() { + PlatformDispatcher.instance.onBeginFrame = (Duration duration) { + const size = Size(800.0, 600.0); + + final builder = SceneBuilder(); + + builder.pushOffset(0.0, 0.0); + + builder.addTexture(/*textureId*/ 1, width: size.width, height: size.height); + + builder.pop(); + + PlatformDispatcher.instance.views.first.render(builder.build()); + }; + PlatformDispatcher.instance.scheduleFrame(); +} + @pragma('vm:entry-point') // ignore: non_constant_identifier_names void render_impeller_text_test() { diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc b/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc index e9711f53d871f..039d13324c79b 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc @@ -4829,6 +4829,80 @@ TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) { ASSERT_FALSE(present_called); } +TEST_F(EmbedderTest, RenderTextureWithImpellerOpenGL) { + auto& context = GetEmbedderContext(); + EmbedderConfigBuilder builder(context); + fml::AutoResetWaitableEvent latch; + bool present_called = false; + context.SetGLPresentCallback([&](FlutterPresentInfo present_info) { + present_called = true; + latch.Signal(); + }); + builder.AddCommandLineArgument("--enable-impeller"); + builder.SetDartEntrypoint("render_texture_impeller_test"); + builder.SetSurface(DlISize(800, 600)); + typedef void (*glGenTexturesProc)(GLsizei n, GLuint* textures); + typedef void (*glBindTextureProc)(GLenum n, GLuint texture); + typedef void (*glTexImage2DProc)(GLenum target, GLint level, + GLint internalformat, GLsizei width, + GLsizei height, GLint border, GLenum format, + GLenum type, const void* pixels); + static glGenTexturesProc glGenTextures = reinterpret_cast( + context.GLGetProcAddress("glGenTextures")); + static glBindTextureProc glBindTexture = reinterpret_cast( + context.GLGetProcAddress("glBindTexture")); + static glTexImage2DProc glTexImage2D = reinterpret_cast( + context.GLGetProcAddress("glTexImage2D")); + + auto rendered_scene = context.GetNextSceneImage(); + context.GetRendererConfig().open_gl.gl_external_texture_frame_callback = + [](void* user_data, int64_t texture_id, size_t width, size_t height, + FlutterOpenGLTexture* texture) -> bool { + std::vector buffer(800 * 600 * 4); + for (int i = 0; i < 800 * 600; ++i) { + buffer[i * 4 + 0] = 255; // Red channel + buffer[i * 4 + 1] = 0; // Green channel + buffer[i * 4 + 2] = 0; // Blue channel + buffer[i * 4 + 3] = 255; // Alpha channel (fully opaque) + } + + GLuint gl_texture; + glGenTextures(1, &gl_texture); + glBindTexture(GL_TEXTURE_2D, gl_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 800, 600, 0, GL_RGBA, + GL_UNSIGNED_BYTE, buffer.data()); + texture->target = GL_TEXTURE_2D; + texture->name = gl_texture; + texture->format = GL_RGBA; + texture->destruction_callback = nullptr; + texture->user_data = nullptr; + texture->width = width; + texture->height = height; + return true; + }; + + auto engine = builder.LaunchEngine(); + + ASSERT_TRUE(engine.is_valid()); + + flutter::EmbedderEngine* embedder_engine = ToEmbedderEngine(engine.get()); + + ASSERT_TRUE(embedder_engine->RegisterTexture(1)); + ASSERT_TRUE(embedder_engine->MarkTextureFrameAvailable(1)); + + // Send a window metrics events so frames may be scheduled. + FlutterWindowMetricsEvent event = {}; + event.struct_size = sizeof(event); + event.width = 800; + event.height = 600; + event.pixel_ratio = 1.0; + ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), + kSuccess); + latch.Wait(); + ASSERT_TRUE( + ImageMatchesFixture("external_texture_metal.png", rendered_scene)); +} + TEST_F(EmbedderTest, ImpellerOpenGLImageSnapshot) { auto& context = GetEmbedderContext(); From 8da1bb32339fa8d4278df801ebcc1cddd27f7092 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Tue, 10 Feb 2026 21:03:02 +0800 Subject: [PATCH 3/7] Update unit test for rendering texture 1.Make the texture red on the top half and blue on the botton half. 2.Add a new image file. --- .../src/flutter/shell/platform/embedder/BUILD.gn | 1 + .../fixtures/external_texture_impeller.png | Bin 0 -> 3272 bytes .../embedder/tests/embedder_gl_unittests.cc | 11 +++++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 engine/src/flutter/shell/platform/embedder/fixtures/external_texture_impeller.png diff --git a/engine/src/flutter/shell/platform/embedder/BUILD.gn b/engine/src/flutter/shell/platform/embedder/BUILD.gn index de073b38654f6..18564dcaca528 100644 --- a/engine/src/flutter/shell/platform/embedder/BUILD.gn +++ b/engine/src/flutter/shell/platform/embedder/BUILD.gn @@ -254,6 +254,7 @@ test_fixtures("fixtures") { "fixtures/vk_dpr_noxform.png", "fixtures/vk_gradient.png", "fixtures/gradient_metal.png", + "fixtures/external_texture_impeller.png", "fixtures/external_texture_metal.png", "fixtures/gradient_xform.png", "fixtures/scene_without_custom_compositor.png", diff --git a/engine/src/flutter/shell/platform/embedder/fixtures/external_texture_impeller.png b/engine/src/flutter/shell/platform/embedder/fixtures/external_texture_impeller.png new file mode 100644 index 0000000000000000000000000000000000000000..0a6dfb6ec54b781b253ad57d98cc2031149e12ab GIT binary patch literal 3272 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzEX7WqAsj$Z!;#VfFH%aOTNztF;Te1VHjdTZAAXkr+l>sKu6{1-oD!M<5{QNA literal 0 HcmV?d00001 diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc b/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc index 039d13324c79b..af333111264a7 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc @@ -4859,13 +4859,20 @@ TEST_F(EmbedderTest, RenderTextureWithImpellerOpenGL) { [](void* user_data, int64_t texture_id, size_t width, size_t height, FlutterOpenGLTexture* texture) -> bool { std::vector buffer(800 * 600 * 4); - for (int i = 0; i < 800 * 600; ++i) { + for (int i = 0; i < 800 * 300; ++i) { buffer[i * 4 + 0] = 255; // Red channel buffer[i * 4 + 1] = 0; // Green channel buffer[i * 4 + 2] = 0; // Blue channel buffer[i * 4 + 3] = 255; // Alpha channel (fully opaque) } + for (int i = 800 * 300; i < 800 * 600; ++i) { + buffer[i * 4 + 0] = 0; // Red channel + buffer[i * 4 + 1] = 0; // Green channel + buffer[i * 4 + 2] = 255; // Blue channel + buffer[i * 4 + 3] = 255; // Alpha channel (fully opaque) + } + GLuint gl_texture; glGenTextures(1, &gl_texture); glBindTexture(GL_TEXTURE_2D, gl_texture); @@ -4900,7 +4907,7 @@ TEST_F(EmbedderTest, RenderTextureWithImpellerOpenGL) { kSuccess); latch.Wait(); ASSERT_TRUE( - ImageMatchesFixture("external_texture_metal.png", rendered_scene)); + ImageMatchesFixture("external_texture_impeller.png", rendered_scene)); } TEST_F(EmbedderTest, ImpellerOpenGLImageSnapshot) { From 9195a8d1813177f6b91aea7561515866bd3b0219 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Tue, 10 Feb 2026 21:05:31 +0800 Subject: [PATCH 4/7] Code format --- .../shell/platform/embedder/tests/embedder_gl_unittests.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc b/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc index af333111264a7..1efe14520f8ae 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc @@ -4867,9 +4867,9 @@ TEST_F(EmbedderTest, RenderTextureWithImpellerOpenGL) { } for (int i = 800 * 300; i < 800 * 600; ++i) { - buffer[i * 4 + 0] = 0; // Red channel + buffer[i * 4 + 0] = 0; // Red channel buffer[i * 4 + 1] = 0; // Green channel - buffer[i * 4 + 2] = 255; // Blue channel + buffer[i * 4 + 2] = 255; // Blue channel buffer[i * 4 + 3] = 255; // Alpha channel (fully opaque) } From 55c900a0a966b86f3c04db4279f1d46ba3c37e4a Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Wed, 11 Feb 2026 17:00:26 +0800 Subject: [PATCH 5/7] Add format check Only support GL_RGBA8 format now. --- .../shell/platform/embedder/embedder_external_texture_gl.cc | 5 +++++ .../shell/platform/embedder/tests/embedder_gl_unittests.cc | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc index bb06cab4e9e77..047617e479abc 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.cc @@ -138,6 +138,11 @@ sk_sp EmbedderExternalTextureGL::ResolveTextureImpeller( return nullptr; } + if (texture->format != GL_RGBA8) { + FML_LOG(ERROR) << "Only support GL_RGBA8 format now"; + return nullptr; + } + impeller::TextureDescriptor desc; desc.size = impeller::ISize(texture->width, texture->height); desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt; diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc b/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc index 1efe14520f8ae..362d825985ab1 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_gl_unittests.cc @@ -4880,7 +4880,7 @@ TEST_F(EmbedderTest, RenderTextureWithImpellerOpenGL) { GL_UNSIGNED_BYTE, buffer.data()); texture->target = GL_TEXTURE_2D; texture->name = gl_texture; - texture->format = GL_RGBA; + texture->format = GL_RGBA8; texture->destruction_callback = nullptr; texture->user_data = nullptr; texture->width = width; From d77c855ad3cdb7463b85c44468acf1e8cff6c08b Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Fri, 13 Feb 2026 01:33:39 +0800 Subject: [PATCH 6/7] Trigger Build From 2df7bd4b32dfa617a96003980bc5b5168f779fee Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Fri, 13 Feb 2026 01:33:39 +0800 Subject: [PATCH 7/7] Trigger Build