diff --git a/engine/src/flutter/shell/platform/embedder/embedder.h b/engine/src/flutter/shell/platform/embedder/embedder.h index 6f5b50ec17fbd..9249f082d30af 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.h +++ b/engine/src/flutter/shell/platform/embedder/embedder.h @@ -405,7 +405,6 @@ typedef struct { } FlutterTransformation; typedef void (*VoidCallback)(void* /* user data */); -typedef bool (*BoolCallback)(void* /* user data */); typedef enum { /// Specifies an OpenGL texture target type. Textures are specified using @@ -513,13 +512,6 @@ typedef struct { uint32_t name; /// The texture format (example GL_RGBA8). uint32_t format; - /// The pixel data buffer. - const uint8_t* buffer; - /// The size of pixel buffer. - size_t buffer_size; - /// Callback invoked that the gpu surface texture start binding. - BoolCallback bind_callback; - /// User data to be returned on the invocation of the destruction callback. void* user_data; /// Callback invoked (on an engine managed thread) that asks the embedder to @@ -613,6 +605,7 @@ typedef struct { uint32_t format; } FlutterOpenGLSurface; +typedef bool (*BoolCallback)(void* /* user data */); typedef FlutterTransformation (*TransformationCallback)(void* /* user data */); typedef uint32_t (*UIntCallback)(void* /* user data */); typedef bool (*SoftwareSurfacePresentCallback)(void* /* user data */, 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 e8d2ad8bd12a3..e7373063766f9 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 @@ -129,107 +129,136 @@ sk_sp EmbedderExternalTextureGL::ResolveTextureSkia( return DlImage::Make(std::move(image)); } -sk_sp EmbedderExternalTextureGL::ResolveTextureImpeller( - int64_t texture_id, - impeller::AiksContext* aiks_context, - const SkISize& size) { - std::unique_ptr texture = - external_texture_callback_(texture_id, size.width(), size.height()); +bool EmbedderExternalTextureGL::IsExternalTextureChanged( + FlutterOpenGLTexture* texture) { + if (static_cast(texture->width) != desc_.size.width || + static_cast(texture->height) != desc_.size.height) { + return true; + } - if (!texture) { - return nullptr; + if (!texture_image_) { + return true; } - if (texture->bind_callback != nullptr) { - return ResolveTextureImpellerSurface(aiks_context, std::move(texture)); - } else { - return ResolveTextureImpellerPixelbuffer(aiks_context, std::move(texture)); + auto handle = texture_image_->GetGLHandle(); + if (!handle.has_value()) { + return true; + } + + if (handle.value() != texture->name) { + return true; } + + return false; } -sk_sp EmbedderExternalTextureGL::ResolveTextureImpellerPixelbuffer( +std::shared_ptr +EmbedderExternalTextureGL::CreateImpellerTexture( impeller::AiksContext* aiks_context, - std::unique_ptr texture) { + FlutterOpenGLTexture* texture) { impeller::TextureDescriptor desc; desc.size = impeller::ISize(texture->width, texture->height); - desc.type = impeller::TextureType::kTexture2D; desc.storage_mode = impeller::StorageMode::kDevicePrivate; desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt; + if (texture->target == GL_TEXTURE_EXTERNAL_OES) { + desc.type = impeller::TextureType::kTextureExternalOES; + } else { + desc.type = impeller::TextureType::kTexture2D; + } + impeller::ContextGLES& context = impeller::ContextGLES::Cast(*aiks_context->GetContext()); - std::shared_ptr image = - std::make_shared(context.GetReactor(), desc); + impeller::HandleGLES handle = context.GetReactor()->CreateHandle( + impeller::HandleType::kTexture, texture->name); - image->MarkContentsInitialized(); - if (!image->SetContents(texture->buffer, texture->buffer_size)) { - if (texture->destruction_callback) { - texture->destruction_callback(texture->user_data); - } - return nullptr; - } + std::shared_ptr texture_image = + impeller::TextureGLES::WrapTexture(context.GetReactor(), desc, handle); - if (!image) { - // In case Skia rejects the image, call the release proc so that - // embedders can perform collection of intermediates. + if (!texture_image) { if (texture->destruction_callback) { texture->destruction_callback(texture->user_data); } - FML_LOG(ERROR) << "Could not create external texture"; + FML_LOG(ERROR) << "Could not create external texture with name: " + << texture->name << ", size: " << texture->width << "x" + << texture->height; return nullptr; } + texture_image->SetCoordinateSystem( + impeller::TextureCoordinateSystem::kUploadFromHost); + if (texture->destruction_callback) { - texture->destruction_callback(texture->user_data); + if (!context.GetReactor()->RegisterCleanupCallback( + handle, + [callback = texture->destruction_callback, + user_data = texture->user_data]() { callback(user_data); })) { + FML_LOG(ERROR) << "Could not register destruction callback for texture: " + << texture->name; + texture_image.reset(); + return nullptr; + } } - return impeller::DlImageImpeller::Make(image); + desc_ = desc; + return texture_image; } -sk_sp EmbedderExternalTextureGL::ResolveTextureImpellerSurface( - impeller::AiksContext* aiks_context, - std::unique_ptr texture) { - impeller::TextureDescriptor desc; - desc.size = impeller::ISize(texture->width, texture->height); - desc.storage_mode = impeller::StorageMode::kDevicePrivate; - desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt; - desc.type = impeller::TextureType::kTextureExternalOES; - impeller::ContextGLES& context = - impeller::ContextGLES::Cast(*aiks_context->GetContext()); - std::shared_ptr image = - std::make_shared(context.GetReactor(), desc); - image->MarkContentsInitialized(); - image->SetCoordinateSystem( - impeller::TextureCoordinateSystem::kUploadFromHost); - if (!image->Bind()) { +bool EmbedderExternalTextureGL::ValidateTextureParameters( + FlutterOpenGLTexture* texture, + const SkISize& size) { + if (size.width() <= 0 || size.height() <= 0) { + FML_LOG(ERROR) << "Invalid texture size: " << size.width() << "x" + << size.height(); if (texture->destruction_callback) { texture->destruction_callback(texture->user_data); } - FML_LOG(ERROR) << "Could not bind texture"; - return nullptr; + return false; } - if (!image) { - // In case Skia rejects the image, call the release proc so that - // embedders can perform collection of intermediates. + if (texture->name == 0) { + FML_LOG(ERROR) << "Invalid texture name (0)"; if (texture->destruction_callback) { texture->destruction_callback(texture->user_data); } - FML_LOG(ERROR) << "Could not create external texture"; + return false; + } + + return true; +} + +sk_sp EmbedderExternalTextureGL::ResolveTextureImpeller( + int64_t texture_id, + impeller::AiksContext* aiks_context, + const SkISize& size) { + std::unique_ptr texture = + external_texture_callback_(texture_id, size.width(), size.height()); + + if (!texture) { + FML_LOG(ERROR) << "External texture callback returned null for texture_id: " + << texture_id; return nullptr; } - if (!texture->bind_callback(texture->user_data)) { - if (texture->destruction_callback) { - texture->destruction_callback(texture->user_data); - } + if (!ValidateTextureParameters(texture.get(), size)) { return nullptr; } - if (texture->destruction_callback) { - texture->destruction_callback(texture->user_data); + if (!texture_image_) { + texture_image_ = CreateImpellerTexture(aiks_context, texture.get()); + } else { + if (IsExternalTextureChanged(texture.get())) { + texture_image_.reset(); + texture_image_ = CreateImpellerTexture(aiks_context, texture.get()); + } + } + + if (texture_image_ == nullptr) { + FML_LOG(ERROR) << "Failed to create Impeller texture for texture_id: " + << texture_id; + return nullptr; } - return impeller::DlImageImpeller::Make(image); + return impeller::DlImageImpeller::Make(texture_image_); } // |flutter::Texture| diff --git a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.h b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.h index 6ecb6843208d1..2d50c55755d32 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.h +++ b/engine/src/flutter/shell/platform/embedder/embedder_external_texture_gl.h @@ -8,6 +8,7 @@ #include "flutter/common/graphics/texture.h" #include "flutter/fml/macros.h" #include "flutter/shell/platform/embedder/embedder.h" +#include "impeller/renderer/backend/gles/texture_gles.h" #include "third_party/skia/include/core/SkSize.h" namespace flutter { @@ -25,7 +26,8 @@ class EmbedderExternalTextureGL : public flutter::Texture { private: const ExternalTextureCallback& external_texture_callback_; sk_sp last_image_; - + std::shared_ptr texture_image_ = nullptr; + impeller::TextureDescriptor desc_; sk_sp ResolveTexture(int64_t texture_id, GrDirectContext* context, impeller::AiksContext* aiks_context, @@ -39,13 +41,14 @@ class EmbedderExternalTextureGL : public flutter::Texture { impeller::AiksContext* aiks_context, const SkISize& size); - sk_sp ResolveTextureImpellerPixelbuffer( - impeller::AiksContext* aiks_context, - std::unique_ptr texture); + bool ValidateTextureParameters(FlutterOpenGLTexture* texture, + const SkISize& size); + + bool IsExternalTextureChanged(FlutterOpenGLTexture* texture); - sk_sp ResolveTextureImpellerSurface( + std::shared_ptr CreateImpellerTexture( impeller::AiksContext* aiks_context, - std::unique_ptr texture); + FlutterOpenGLTexture* texture); // |flutter::Texture| void Paint(PaintContext& context,