diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn index ba7d1276f54a7..bd6ae97ff8b6f 100644 --- a/shell/platform/embedder/BUILD.gn +++ b/shell/platform/embedder/BUILD.gn @@ -124,6 +124,8 @@ template("embedder_source_set") { if (impeller_supports_rendering) { sources += [ + "embedder_external_texture_gl_impeller.cc", + "embedder_external_texture_gl_impeller.h", "embedder_surface_gl_impeller.cc", "embedder_surface_gl_impeller.h", ] diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 52e49646c009a..5acf151c9bb02 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -2029,8 +2029,8 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, } return texture; }; - external_texture_resolver = - std::make_unique(external_texture_callback); + external_texture_resolver = std::make_unique( + external_texture_callback, settings.enable_impeller); } } #endif diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index d26e2215adf3a..117aa714c6f82 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -294,6 +294,7 @@ 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 @@ -361,6 +362,11 @@ typedef enum { kFlutterSoftwarePixelFormatNative32, } FlutterSoftwarePixelFormat; +typedef enum { + kFlutterGLImpellerTexturePixelBuffer, + kFlutterGLImpellerTextureGpuSurface, +} FlutterGLImpellerTextureType; + typedef struct { /// Target texture of the active texture unit (example GL_TEXTURE_2D or /// GL_TEXTURE_RECTANGLE). @@ -369,6 +375,14 @@ 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; + /// The type of the texture. + FlutterGLImpellerTextureType impeller_texture_type; /// 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 @@ -401,7 +415,6 @@ typedef struct { VoidCallback destruction_callback; } FlutterOpenGLFramebuffer; -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/shell/platform/embedder/embedder_external_texture_gl_impeller.cc b/shell/platform/embedder/embedder_external_texture_gl_impeller.cc new file mode 100755 index 0000000000000..d5c4a5a677b26 --- /dev/null +++ b/shell/platform/embedder/embedder_external_texture_gl_impeller.cc @@ -0,0 +1,160 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/embedder/embedder_external_texture_gl_impeller.h" + +#include "flutter/fml/logging.h" +#include "flutter/impeller/display_list/dl_image_impeller.h" +#include "flutter/impeller/renderer/backend/gles/context_gles.h" +#include "flutter/impeller/renderer/backend/gles/texture_gles.h" +#include "impeller/aiks/aiks_context.h" +#include "impeller/renderer/backend/gles/gles.h" +#include "include/core/SkCanvas.h" +#include "include/core/SkPaint.h" + +namespace flutter { + +EmbedderExternalTextureGLImpeller::EmbedderExternalTextureGLImpeller( + int64_t texture_identifier, + const EmbedderExternalTextureGL::ExternalTextureCallback& callback) + : Texture(texture_identifier), external_texture_callback_(callback) { + FML_DCHECK(external_texture_callback_); +} + +EmbedderExternalTextureGLImpeller::~EmbedderExternalTextureGLImpeller() = + default; + +// |flutter::Texture| +void EmbedderExternalTextureGLImpeller::Paint(PaintContext& context, + const SkRect& bounds, + bool freeze, + const DlImageSampling sampling) { + if (last_image_ == nullptr) { + last_image_ = + ResolveTexture(Id(), // + context, // + SkISize::Make(bounds.width(), bounds.height()) // + ); + } + + DlCanvas* canvas = context.canvas; + const DlPaint* paint = context.paint; + + if (last_image_) { + SkRect image_bounds = SkRect::Make(last_image_->bounds()); + if (bounds != image_bounds) { + canvas->DrawImageRect(last_image_, image_bounds, bounds, sampling, paint); + } else { + canvas->DrawImage(last_image_, {bounds.x(), bounds.y()}, sampling, paint); + } + } +} + +// |flutter::Texture| +void EmbedderExternalTextureGLImpeller::OnGrContextCreated() {} + +// |flutter::Texture| +void EmbedderExternalTextureGLImpeller::OnGrContextDestroyed() {} + +// |flutter::Texture| +void EmbedderExternalTextureGLImpeller::MarkNewFrameAvailable() { + last_image_ = nullptr; +} + +// |flutter::Texture| +void EmbedderExternalTextureGLImpeller::OnTextureUnregistered() {} + +sk_sp EmbedderExternalTextureGLImpeller::ResolveTexture( + int64_t texture_id, + PaintContext& context, + const SkISize& size) { + std::unique_ptr texture = + external_texture_callback_(texture_id, size.width(), size.height()); + if (!texture) { + return nullptr; + } + size_t width = size.width(); + size_t height = size.height(); + if (texture->width != 0 && texture->height != 0) { + width = texture->width; + height = texture->height; + } + if (texture->impeller_texture_type == + FlutterGLImpellerTextureType::kFlutterGLImpellerTexturePixelBuffer) { + return ResolvePixelBufferTexture(texture.get(), context, + SkISize::Make(width, height)); + } else { + return ResolveGpuSurfaceTexture(texture.get(), context, + SkISize::Make(width, height)); + } +} + +sk_sp EmbedderExternalTextureGLImpeller::ResolvePixelBufferTexture( + FlutterOpenGLTexture* texture, + PaintContext& context, + const SkISize& size) { + impeller::TextureDescriptor desc; + desc.type = impeller::TextureType::kTexture2D; + impeller::AiksContext* aiks_context = context.aiks_context; + const auto& gl_context = + impeller::ContextGLES::Cast(*aiks_context->GetContext()); + desc.storage_mode = impeller::StorageMode::kDevicePrivate; + desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt; + desc.size = {static_cast(size.width()), static_cast(size.height())}; + desc.mip_count = 1; + + auto textureGLES = + std::make_shared(gl_context.GetReactor(), desc); + if (!textureGLES->SetContents(texture->buffer, texture->buffer_size)) { + if (texture->destruction_callback) { + texture->destruction_callback(texture->user_data); + } + return nullptr; + } + if (texture->destruction_callback) { + texture->destruction_callback(texture->user_data); + } + return impeller::DlImageImpeller::Make(textureGLES); +} + +sk_sp EmbedderExternalTextureGLImpeller::ResolveGpuSurfaceTexture( + FlutterOpenGLTexture* texture, + PaintContext& context, + const SkISize& size) { + impeller::TextureDescriptor desc; + desc.type = impeller::TextureType::kTextureExternalOES; + impeller::AiksContext* aiks_context = context.aiks_context; + const auto& gl_context = + impeller::ContextGLES::Cast(*aiks_context->GetContext()); + desc.storage_mode = impeller::StorageMode::kDevicePrivate; + desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt; + desc.size = {static_cast(size.width()), static_cast(size.height())}; + desc.mip_count = 1; + auto textureGLES = std::make_shared( + gl_context.GetReactor(), desc, + impeller::TextureGLES::IsWrapped::kWrapped); + textureGLES->SetCoordinateSystem( + impeller::TextureCoordinateSystem::kUploadFromHost); + if (!textureGLES->Bind()) { + if (texture->destruction_callback) { + texture->destruction_callback(texture->user_data); + } + return nullptr; + } + + if (!texture->bind_callback(texture->user_data)) { + if (texture->destruction_callback) { + texture->destruction_callback(texture->user_data); + } + return nullptr; + } + + if (texture->destruction_callback) { + texture->destruction_callback(texture->user_data); + } + + return impeller::DlImageImpeller::Make(textureGLES); +} + +} // namespace flutter diff --git a/shell/platform/embedder/embedder_external_texture_gl_impeller.h b/shell/platform/embedder/embedder_external_texture_gl_impeller.h new file mode 100755 index 0000000000000..2b2e12d3bc6f6 --- /dev/null +++ b/shell/platform/embedder/embedder_external_texture_gl_impeller.h @@ -0,0 +1,62 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_IMPELLER_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_IMPELLER_H_ + +#include "flutter/common/graphics/texture.h" +#include "flutter/fml/macros.h" +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/embedder/embedder_external_texture_gl.h" +#include "third_party/skia/include/core/SkSize.h" + +namespace flutter { + +class EmbedderExternalTextureGLImpeller : public flutter::Texture { + public: + EmbedderExternalTextureGLImpeller( + int64_t texture_identifier, + const EmbedderExternalTextureGL::ExternalTextureCallback& callback); + + ~EmbedderExternalTextureGLImpeller(); + + private: + const EmbedderExternalTextureGL::ExternalTextureCallback& + external_texture_callback_; + sk_sp last_image_; + + sk_sp ResolveTexture(int64_t texture_id, + PaintContext& context, + const SkISize& size); + sk_sp ResolveGpuSurfaceTexture(FlutterOpenGLTexture* texture, + PaintContext& context, + const SkISize& size); + sk_sp ResolvePixelBufferTexture(FlutterOpenGLTexture* texture, + PaintContext& context, + const SkISize& size); + + // |flutter::Texture| + void Paint(PaintContext& context, + const SkRect& bounds, + bool freeze, + const DlImageSampling sampling) override; + + // |flutter::Texture| + void OnGrContextCreated() override; + + // |flutter::Texture| + void OnGrContextDestroyed() override; + + // |flutter::Texture| + void MarkNewFrameAvailable() override; + + // |flutter::Texture| + void OnTextureUnregistered() override; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureGLImpeller); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_TEXTURE_GL_IMPELLER_H_ diff --git a/shell/platform/embedder/embedder_external_texture_resolver.cc b/shell/platform/embedder/embedder_external_texture_resolver.cc index 4e4b41b8d4ad2..bbe83b875d5fd 100644 --- a/shell/platform/embedder/embedder_external_texture_resolver.cc +++ b/shell/platform/embedder/embedder_external_texture_resolver.cc @@ -4,6 +4,10 @@ #include "flutter/shell/platform/embedder/embedder_external_texture_resolver.h" +#if defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING) +#include "flutter/shell/platform/embedder/embedder_external_texture_gl_impeller.h" +#endif + #include #include @@ -11,8 +15,9 @@ namespace flutter { #ifdef SHELL_ENABLE_GL EmbedderExternalTextureResolver::EmbedderExternalTextureResolver( - EmbedderExternalTextureGL::ExternalTextureCallback gl_callback) - : gl_callback_(std::move(gl_callback)) {} + EmbedderExternalTextureGL::ExternalTextureCallback gl_callback, + bool enable_impeller) + : gl_callback_(std::move(gl_callback)), enable_impeller_(enable_impeller) {} #endif #ifdef SHELL_ENABLE_METAL @@ -25,6 +30,12 @@ std::unique_ptr EmbedderExternalTextureResolver::ResolveExternalTexture(int64_t texture_id) { #ifdef SHELL_ENABLE_GL if (gl_callback_) { +#ifdef IMPELLER_SUPPORTS_RENDERING + if (enable_impeller_) { + return std::make_unique(texture_id, + gl_callback_); + } +#endif return std::make_unique(texture_id, gl_callback_); } diff --git a/shell/platform/embedder/embedder_external_texture_resolver.h b/shell/platform/embedder/embedder_external_texture_resolver.h index 412301736e566..da421e2b837a1 100644 --- a/shell/platform/embedder/embedder_external_texture_resolver.h +++ b/shell/platform/embedder/embedder_external_texture_resolver.h @@ -26,7 +26,8 @@ class EmbedderExternalTextureResolver { #ifdef SHELL_ENABLE_GL explicit EmbedderExternalTextureResolver( - EmbedderExternalTextureGL::ExternalTextureCallback gl_callback); + EmbedderExternalTextureGL::ExternalTextureCallback gl_callback, + bool enable_impeller); #endif #ifdef SHELL_ENABLE_METAL @@ -46,6 +47,7 @@ class EmbedderExternalTextureResolver { #ifdef SHELL_ENABLE_METAL EmbedderExternalTextureMetal::ExternalTextureCallback metal_callback_; #endif + bool enable_impeller_ = false; FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureResolver); };