Merge 46ac5602889d334e3d14e27b296326fe9ad43c26 into 06df71c51446e96939c6a615b7c34ce9123806ba

This commit is contained in:
xiaowei guan 2026-02-19 11:05:00 -05:00 committed by GitHub
commit f8fa42bba2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 110 additions and 1 deletions

View File

@ -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",

View File

@ -138,13 +138,19 @@ sk_sp<DlImage> 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;
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<impeller::TextureGLES> image =
impeller::TextureGLES::WrapTexture(context.GetReactor(), desc, handle);
@ -165,6 +171,8 @@ sk_sp<DlImage> EmbedderExternalTextureGL::ResolveTextureImpeller(
FML_LOG(ERROR) << "Could not register destruction callback";
return nullptr;
}
image->SetCoordinateSystem(
impeller::TextureCoordinateSystem::kUploadFromHost);
return impeller::DlImageImpeller::Make(image);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -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() {

View File

@ -4829,6 +4829,87 @@ TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) {
ASSERT_FALSE(present_called);
}
TEST_F(EmbedderTest, RenderTextureWithImpellerOpenGL) {
auto& context = GetEmbedderContext<EmbedderTestContextGL>();
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<glGenTexturesProc>(
context.GLGetProcAddress("glGenTextures"));
static glBindTextureProc glBindTexture = reinterpret_cast<glBindTextureProc>(
context.GLGetProcAddress("glBindTexture"));
static glTexImage2DProc glTexImage2D = reinterpret_cast<glTexImage2DProc>(
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<uint8_t> buffer(800 * 600 * 4);
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);
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_RGBA8;
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_impeller.png", rendered_scene));
}
TEST_F(EmbedderTest, ImpellerOpenGLImageSnapshot) {
auto& context = GetEmbedderContext<EmbedderTestContextGL>();