From 5cfcc911db02c27c9118806bceb669909614dd58 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Tue, 15 Aug 2023 12:15:47 -0700 Subject: [PATCH] Add support for SurfaceTexture based external textures on Android under Impeller/GLES. - Refactor AndroidExternalTextureGL into SurfaceTextureExternalTexture base class. - Add SurfaceTextureExternalTextureGL for legacy GL rendering. - Add SurfaceTextureExternalTextureImpellerGL for Impeller GLES rendering. NOTE: There is still no support for SurfaceTextures under Vulkan rendering. --- ci/licenses_golden/licenses_flutter | 12 +- shell/platform/android/BUILD.gn | 6 +- .../android/android_external_texture_gl.cc | 139 ------------------ .../hardware_buffer_external_texture.h | 2 + .../renderer/SurfaceTextureWrapper.java | 4 +- .../platform/android/platform_view_android.cc | 22 ++- .../android/platform_view_android_jni_impl.cc | 2 +- .../surface_texture_external_texture.cc | 114 ++++++++++++++ ...l.h => surface_texture_external_texture.h} | 34 ++--- .../surface_texture_external_texture_gl.cc | 115 +++++++++++++++ .../surface_texture_external_texture_gl.h | 64 ++++++++ 11 files changed, 340 insertions(+), 174 deletions(-) delete mode 100644 shell/platform/android/android_external_texture_gl.cc create mode 100644 shell/platform/android/surface_texture_external_texture.cc rename shell/platform/android/{android_external_texture_gl.h => surface_texture_external_texture.h} (62%) create mode 100644 shell/platform/android/surface_texture_external_texture_gl.cc create mode 100644 shell/platform/android/surface_texture_external_texture_gl.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 86d58b4deda95..97ab61f6f88dd 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2317,8 +2317,6 @@ ORIGIN: ../../../flutter/shell/platform/android/android_egl_surface.h + ../../.. ORIGIN: ../../../flutter/shell/platform/android/android_environment_gl.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_environment_gl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_exports.lst + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/android_external_texture_gl.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/android/android_external_texture_gl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_image_generator.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_image_generator.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/android_shell_holder.cc + ../../../flutter/LICENSE @@ -2505,6 +2503,10 @@ ORIGIN: ../../../flutter/shell/platform/android/surface/android_surface_mock.cc ORIGIN: ../../../flutter/shell/platform/android/surface/android_surface_mock.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/surface/snapshot_surface_producer.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/surface/snapshot_surface_producer.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/android/surface_texture_external_texture.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/android/surface_texture_external_texture.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/android/surface_texture_external_texture_gl.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/android/surface_texture_external_texture_gl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/vsync_waiter_android.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/vsync_waiter_android.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/common/accessibility_bridge.cc + ../../../flutter/LICENSE @@ -5043,8 +5045,6 @@ FILE: ../../../flutter/shell/platform/android/android_egl_surface.h FILE: ../../../flutter/shell/platform/android/android_environment_gl.cc FILE: ../../../flutter/shell/platform/android/android_environment_gl.h FILE: ../../../flutter/shell/platform/android/android_exports.lst -FILE: ../../../flutter/shell/platform/android/android_external_texture_gl.cc -FILE: ../../../flutter/shell/platform/android/android_external_texture_gl.h FILE: ../../../flutter/shell/platform/android/android_image_generator.cc FILE: ../../../flutter/shell/platform/android/android_image_generator.h FILE: ../../../flutter/shell/platform/android/android_shell_holder.cc @@ -5243,6 +5243,10 @@ FILE: ../../../flutter/shell/platform/android/surface/android_surface_mock.cc FILE: ../../../flutter/shell/platform/android/surface/android_surface_mock.h FILE: ../../../flutter/shell/platform/android/surface/snapshot_surface_producer.cc FILE: ../../../flutter/shell/platform/android/surface/snapshot_surface_producer.h +FILE: ../../../flutter/shell/platform/android/surface_texture_external_texture.cc +FILE: ../../../flutter/shell/platform/android/surface_texture_external_texture.h +FILE: ../../../flutter/shell/platform/android/surface_texture_external_texture_gl.cc +FILE: ../../../flutter/shell/platform/android/surface_texture_external_texture_gl.h FILE: ../../../flutter/shell/platform/android/vsync_waiter_android.cc FILE: ../../../flutter/shell/platform/android/vsync_waiter_android.h FILE: ../../../flutter/shell/platform/common/accessibility_bridge.cc diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 0895c3dc02286..18562b0ae24c4 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -82,8 +82,6 @@ source_set("flutter_shell_native_src") { "android_egl_surface.h", "android_environment_gl.cc", "android_environment_gl.h", - "android_external_texture_gl.cc", - "android_external_texture_gl.h", "android_shell_holder.cc", "android_shell_holder.h", "android_surface_gl_impeller.cc", @@ -115,6 +113,10 @@ source_set("flutter_shell_native_src") { "platform_view_android.h", "platform_view_android_jni_impl.cc", "platform_view_android_jni_impl.h", + "surface_texture_external_texture.cc", + "surface_texture_external_texture.h", + "surface_texture_external_texture_gl.cc", + "surface_texture_external_texture_gl.h", "vsync_waiter_android.cc", "vsync_waiter_android.h", ] diff --git a/shell/platform/android/android_external_texture_gl.cc b/shell/platform/android/android_external_texture_gl.cc deleted file mode 100644 index 4df19aa85c60f..0000000000000 --- a/shell/platform/android/android_external_texture_gl.cc +++ /dev/null @@ -1,139 +0,0 @@ -// 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/android/android_external_texture_gl.h" - -#include - -#include - -#include "flutter/display_list/effects/dl_color_source.h" -#include "third_party/skia/include/core/SkAlphaType.h" -#include "third_party/skia/include/core/SkColorSpace.h" -#include "third_party/skia/include/core/SkColorType.h" -#include "third_party/skia/include/core/SkImage.h" -#include "third_party/skia/include/gpu/GrBackendSurface.h" -#include "third_party/skia/include/gpu/GrDirectContext.h" -#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h" -#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" -#include "third_party/skia/include/gpu/gl/GrGLTypes.h" - -namespace flutter { - -AndroidExternalTextureGL::AndroidExternalTextureGL( - int64_t id, - const fml::jni::ScopedJavaGlobalRef& surface_texture, - std::shared_ptr jni_facade) - : Texture(id), - jni_facade_(std::move(jni_facade)), - surface_texture_(surface_texture), - transform(SkMatrix::I()) {} - -AndroidExternalTextureGL::~AndroidExternalTextureGL() { - if (state_ == AttachmentState::kAttached) { - glDeleteTextures(1, &texture_name_); - } -} - -void AndroidExternalTextureGL::OnGrContextCreated() { - state_ = AttachmentState::kUninitialized; -} - -void AndroidExternalTextureGL::MarkNewFrameAvailable() { - new_frame_ready_ = true; -} - -void AndroidExternalTextureGL::Paint(PaintContext& context, - const SkRect& bounds, - bool freeze, - const DlImageSampling sampling) { - if (state_ == AttachmentState::kDetached) { - return; - } - if (state_ == AttachmentState::kUninitialized) { - glGenTextures(1, &texture_name_); - Attach(static_cast(texture_name_)); - state_ = AttachmentState::kAttached; - } - if (!freeze && new_frame_ready_) { - Update(); - new_frame_ready_ = false; - } - GrGLTextureInfo textureInfo = {GL_TEXTURE_EXTERNAL_OES, texture_name_, - GL_RGBA8_OES}; - auto backendTexture = - GrBackendTextures::MakeGL(1, 1, skgpu::Mipmapped::kNo, textureInfo); - sk_sp image = SkImages::BorrowTextureFrom( - context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin, - kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr); - if (image) { - DlAutoCanvasRestore autoRestore(context.canvas, true); - - // The incoming texture is vertically flipped, so we flip it - // back. OpenGL's coordinate system has Positive Y equivalent to up, while - // Skia's coordinate system has Negative Y equvalent to up. - context.canvas->Translate(bounds.x(), bounds.y() + bounds.height()); - context.canvas->Scale(bounds.width(), -bounds.height()); - - auto dl_image = DlImage::Make(image); - if (!transform.isIdentity()) { - DlImageColorSource source(dl_image, DlTileMode::kRepeat, - DlTileMode::kRepeat, sampling, &transform); - - DlPaint paintWithShader; - if (context.paint) { - paintWithShader = *context.paint; - } - paintWithShader.setColorSource(&source); - context.canvas->DrawRect(SkRect::MakeWH(1, 1), paintWithShader); - } else { - context.canvas->DrawImage(dl_image, {0, 0}, sampling, context.paint); - } - } -} - -void AndroidExternalTextureGL::UpdateTransform() { - jni_facade_->SurfaceTextureGetTransformMatrix( - fml::jni::ScopedJavaLocalRef(surface_texture_), transform); - - // Android's SurfaceTexture transform matrix works on texture coordinate - // lookups in the range 0.0-1.0, while Skia's Shader transform matrix works on - // the image itself, as if it were inscribed inside a clip rect. - // An Android transform that scales lookup by 0.5 (displaying 50% of the - // texture) is the same as a Skia transform by 2.0 (scaling 50% of the image - // outside of the virtual "clip rect"), so we invert the incoming matrix. - SkMatrix inverted; - if (!transform.invert(&inverted)) { - FML_LOG(FATAL) << "Invalid SurfaceTexture transformation matrix"; - } - transform = inverted; -} - -void AndroidExternalTextureGL::OnGrContextDestroyed() { - if (state_ == AttachmentState::kAttached) { - Detach(); - glDeleteTextures(1, &texture_name_); - } - state_ = AttachmentState::kDetached; -} - -void AndroidExternalTextureGL::Attach(jint textureName) { - jni_facade_->SurfaceTextureAttachToGLContext( - fml::jni::ScopedJavaLocalRef(surface_texture_), textureName); -} - -void AndroidExternalTextureGL::Update() { - jni_facade_->SurfaceTextureUpdateTexImage( - fml::jni::ScopedJavaLocalRef(surface_texture_)); - UpdateTransform(); -} - -void AndroidExternalTextureGL::Detach() { - jni_facade_->SurfaceTextureDetachFromGLContext( - fml::jni::ScopedJavaLocalRef(surface_texture_)); -} - -void AndroidExternalTextureGL::OnTextureUnregistered() {} - -} // namespace flutter diff --git a/shell/platform/android/hardware_buffer_external_texture.h b/shell/platform/android/hardware_buffer_external_texture.h index 8f879d67a939f..5f93923fb9fa1 100644 --- a/shell/platform/android/hardware_buffer_external_texture.h +++ b/shell/platform/android/hardware_buffer_external_texture.h @@ -14,6 +14,8 @@ namespace flutter { +// External texture peered to a sequence of android.hardware.HardwareBuffers. +// class HardwareBufferExternalTexture : public flutter::Texture { public: explicit HardwareBufferExternalTexture( diff --git a/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java b/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java index 655d0db865b4e..fcd6c1694c67a 100644 --- a/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java +++ b/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java @@ -81,8 +81,8 @@ public void attachToGLContext(int texName) { // This causes the texture to be in an uninitialized state. // This should *not* be an issue once platform views are always rendered as TextureLayers // since thread merging will be always disabled on Android. - // For more see: AndroidExternalTextureGL::OnGrContextCreated in - // android_external_texture_gl.cc, and + // For more see: SurfaceTextureExternalTextureGL::OnGrContextCreated in + // surface_texture_external_texture_gl.cc, and // https://github.com/flutter/flutter/issues/98155 if (attached) { surfaceTexture.detachFromGLContext(); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index bf4f962627de7..5a74c309e4ac7 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -14,14 +14,14 @@ #include "flutter/shell/platform/android/android_context_gl_impeller.h" #include "flutter/shell/platform/android/android_context_gl_skia.h" #include "flutter/shell/platform/android/android_context_vulkan_impeller.h" -#include "flutter/shell/platform/android/android_external_texture_gl.h" #include "flutter/shell/platform/android/android_surface_gl_impeller.h" #include "flutter/shell/platform/android/android_surface_gl_skia.h" #include "flutter/shell/platform/android/android_surface_software.h" #include "flutter/shell/platform/android/hardware_buffer_external_texture_gl.h" -#include "flutter/shell/platform/android/hardware_buffer_external_texture_vk.h" +#include "flutter/shell/platform/android/surface_texture_external_texture_gl.h" #if IMPELLER_ENABLE_VULKAN // b/258506856 for why this is behind an if #include "flutter/shell/platform/android/android_surface_vulkan_impeller.h" +#include "flutter/shell/platform/android/hardware_buffer_external_texture_vk.h" #endif #include "flutter/shell/platform/android/context/android_context.h" #include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h" @@ -301,10 +301,20 @@ void PlatformViewAndroid::RegisterExternalTexture( int64_t texture_id, const fml::jni::ScopedJavaGlobalRef& surface_texture) { if (android_context_->RenderingApi() == AndroidRenderingAPI::kOpenGLES) { - RegisterTexture(std::make_shared( - texture_id, surface_texture, jni_facade_)); + if (android_context_->GetImpellerContext()) { + // Impeller GLES. + RegisterTexture(std::make_shared( + std::static_pointer_cast( + android_context_->GetImpellerContext()), + texture_id, surface_texture, jni_facade_)); + } else { + // Legacy GL. + RegisterTexture(std::make_shared( + texture_id, surface_texture, jni_facade_)); + } } else { - FML_LOG(INFO) << "Attempted to use a GL texture in a non GL context."; + FML_LOG(INFO) << "Attempted to use a SurfaceTextureExternalTexture with an " + "unsupported rendering API."; } } @@ -312,7 +322,7 @@ void PlatformViewAndroid::RegisterImageTexture( int64_t texture_id, const fml::jni::ScopedJavaGlobalRef& image_texture_entry) { if (android_context_->RenderingApi() == AndroidRenderingAPI::kOpenGLES) { - if (android_context_->GetImpellerContext() != nullptr) { + if (android_context_->GetImpellerContext()) { // Impeller GLES. RegisterTexture(std::make_shared( std::static_pointer_cast( diff --git a/shell/platform/android/platform_view_android_jni_impl.cc b/shell/platform/android/platform_view_android_jni_impl.cc index bda5d082bc8c5..7b9b2e12b37cf 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -28,13 +28,13 @@ #include "flutter/lib/ui/plugins/callback_cache.h" #include "flutter/runtime/dart_service_isolate.h" #include "flutter/shell/common/run_configuration.h" -#include "flutter/shell/platform/android/android_external_texture_gl.h" #include "flutter/shell/platform/android/android_shell_holder.h" #include "flutter/shell/platform/android/apk_asset_provider.h" #include "flutter/shell/platform/android/flutter_main.h" #include "flutter/shell/platform/android/hardware_buffer_external_texture_gl.h" #include "flutter/shell/platform/android/jni/platform_view_android_jni.h" #include "flutter/shell/platform/android/platform_view_android.h" +#include "flutter/shell/platform/android/surface_texture_external_texture_gl.h" #define ANDROID_SHELL_HOLDER \ (reinterpret_cast(shell_holder)) diff --git a/shell/platform/android/surface_texture_external_texture.cc b/shell/platform/android/surface_texture_external_texture.cc new file mode 100644 index 0000000000000..aff59abdc1468 --- /dev/null +++ b/shell/platform/android/surface_texture_external_texture.cc @@ -0,0 +1,114 @@ +// 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/android/surface_texture_external_texture.h" + +#include + +#include + +#include "flutter/display_list/effects/dl_color_source.h" +#include "third_party/skia/include/core/SkAlphaType.h" +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/core/SkColorType.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" +#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h" +#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" +#include "third_party/skia/include/gpu/gl/GrGLTypes.h" + +namespace flutter { + +SurfaceTextureExternalTexture::SurfaceTextureExternalTexture( + int64_t id, + const fml::jni::ScopedJavaGlobalRef& surface_texture, + std::shared_ptr jni_facade) + : Texture(id), + jni_facade_(std::move(jni_facade)), + surface_texture_(surface_texture), + transform_(SkMatrix::I()) {} + +SurfaceTextureExternalTexture::~SurfaceTextureExternalTexture() {} + +void SurfaceTextureExternalTexture::OnGrContextCreated() { + state_ = AttachmentState::kUninitialized; +} + +void SurfaceTextureExternalTexture::MarkNewFrameAvailable() { + new_frame_ready_ = true; +} + +void SurfaceTextureExternalTexture::Paint(PaintContext& context, + const SkRect& bounds, + bool freeze, + const DlImageSampling sampling) { + if (state_ == AttachmentState::kDetached) { + return; + } + const bool should_process_frame = + (!freeze && new_frame_ready_) || dl_image_ == nullptr; + if (should_process_frame) { + ProcessFrame(context, bounds); + new_frame_ready_ = false; + } + FML_CHECK(state_ == AttachmentState::kAttached); + + if (dl_image_) { + context.canvas->DrawImageRect( + dl_image_, // image + SkRect::Make(dl_image_->bounds()), // source rect + bounds, // destination rect + sampling, // sampling + context.paint, // paint + flutter::DlCanvas::SrcRectConstraint::kStrict // enforce edges + ); + } else { + FML_LOG(ERROR) << "No DlImage available."; + } +} + +void SurfaceTextureExternalTexture::OnGrContextDestroyed() { + if (state_ == AttachmentState::kAttached) { + Detach(); + } + state_ = AttachmentState::kDetached; +} + +void SurfaceTextureExternalTexture::OnTextureUnregistered() {} + +void SurfaceTextureExternalTexture::Detach() { + jni_facade_->SurfaceTextureDetachFromGLContext( + fml::jni::ScopedJavaLocalRef(surface_texture_)); + dl_image_.reset(); +} + +void SurfaceTextureExternalTexture::Attach(int gl_tex_id) { + jni_facade_->SurfaceTextureAttachToGLContext( + fml::jni::ScopedJavaLocalRef(surface_texture_), gl_tex_id); + state_ = AttachmentState::kAttached; +} + +void SurfaceTextureExternalTexture::Update() { + jni_facade_->SurfaceTextureUpdateTexImage( + fml::jni::ScopedJavaLocalRef(surface_texture_)); + + jni_facade_->SurfaceTextureGetTransformMatrix( + fml::jni::ScopedJavaLocalRef(surface_texture_), transform_); + + // Android's SurfaceTexture transform matrix works on texture coordinate + // lookups in the range 0.0-1.0, while Skia's Shader transform matrix works on + // the image itself, as if it were inscribed inside a clip rect. + // An Android transform that scales lookup by 0.5 (displaying 50% of the + // texture) is the same as a Skia transform by 2.0 (scaling 50% of the image + // outside of the virtual "clip rect"), so we invert the incoming matrix. + SkMatrix inverted; + if (!transform_.invert(&inverted)) { + FML_LOG(FATAL) + << "Invalid (not invertable) SurfaceTexture transformation matrix"; + } + transform_ = inverted; +} + +} // namespace flutter diff --git a/shell/platform/android/android_external_texture_gl.h b/shell/platform/android/surface_texture_external_texture.h similarity index 62% rename from shell/platform/android/android_external_texture_gl.h rename to shell/platform/android/surface_texture_external_texture.h index ee2a88358ff5d..fe6bff3d93519 100644 --- a/shell/platform/android/android_external_texture_gl.h +++ b/shell/platform/android/surface_texture_external_texture.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_EXTERNAL_TEXTURE_GL_H_ -#define FLUTTER_SHELL_PLATFORM_ANDROID_EXTERNAL_TEXTURE_GL_H_ +#ifndef FLUTTER_SHELL_PLATFORM_SURFACE_TEXTURE_EXTERNAL_TEXTURE_H_ +#define FLUTTER_SHELL_PLATFORM_SURFACE_TEXTURE_EXTERNAL_TEXTURE_H_ #include @@ -12,14 +12,15 @@ namespace flutter { -class AndroidExternalTextureGL : public flutter::Texture { +// External texture peered to an android.graphics.SurfaceTexture. +class SurfaceTextureExternalTexture : public flutter::Texture { public: - AndroidExternalTextureGL( + SurfaceTextureExternalTexture( int64_t id, const fml::jni::ScopedJavaGlobalRef& surface_texture, std::shared_ptr jni_facade); - ~AndroidExternalTextureGL() override; + ~SurfaceTextureExternalTexture() override; void Paint(PaintContext& context, const SkRect& bounds, @@ -34,32 +35,25 @@ class AndroidExternalTextureGL : public flutter::Texture { void OnTextureUnregistered() override; - private: - void Attach(jint textureName); + protected: + virtual void ProcessFrame(PaintContext& context, const SkRect& bounds) = 0; + virtual void Detach(); + void Attach(int gl_tex_id); void Update(); - void Detach(); - - void UpdateTransform(); - enum class AttachmentState { kUninitialized, kAttached, kDetached }; std::shared_ptr jni_facade_; - fml::jni::ScopedJavaGlobalRef surface_texture_; - AttachmentState state_ = AttachmentState::kUninitialized; - + SkMatrix transform_; bool new_frame_ready_ = false; + sk_sp dl_image_; - GLuint texture_name_ = 0; - - SkMatrix transform; - - FML_DISALLOW_COPY_AND_ASSIGN(AndroidExternalTextureGL); + FML_DISALLOW_COPY_AND_ASSIGN(SurfaceTextureExternalTexture); }; } // namespace flutter -#endif // FLUTTER_SHELL_PLATFORM_ANDROID_EXTERNAL_TEXTURE_GL_H_ +#endif // FLUTTER_SHELL_PLATFORM_SURFACE_TEXTURE_EXTERNAL_TEXTURE_H_ diff --git a/shell/platform/android/surface_texture_external_texture_gl.cc b/shell/platform/android/surface_texture_external_texture_gl.cc new file mode 100644 index 0000000000000..8099e0edd70a6 --- /dev/null +++ b/shell/platform/android/surface_texture_external_texture_gl.cc @@ -0,0 +1,115 @@ +// 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/android/surface_texture_external_texture_gl.h" + +#include + +#include "flutter/display_list/effects/dl_color_source.h" +#include "impeller/display_list/dl_image_impeller.h" +#include "shell/platform/android/surface_texture_external_texture.h" +#include "third_party/skia/include/core/SkAlphaType.h" +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/core/SkColorType.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" +#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h" +#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" +#include "third_party/skia/include/gpu/gl/GrGLTypes.h" + +namespace flutter { + +SurfaceTextureExternalTextureGL::SurfaceTextureExternalTextureGL( + int64_t id, + const fml::jni::ScopedJavaGlobalRef& surface_texture, + std::shared_ptr jni_facade) + : SurfaceTextureExternalTexture(id, surface_texture, jni_facade) {} + +SurfaceTextureExternalTextureGL::~SurfaceTextureExternalTextureGL() { + Detach(); +} + +void SurfaceTextureExternalTextureGL::ProcessFrame(PaintContext& context, + const SkRect& bounds) { + if (state_ == AttachmentState::kUninitialized) { + // Generate the texture handle. + glGenTextures(1, &texture_name_); + Attach(texture_name_); + } + FML_CHECK(state_ == AttachmentState::kAttached); + + // Updates the texture contents and transformation matrix. + Update(); + + // Create a + GrGLTextureInfo textureInfo = {GL_TEXTURE_EXTERNAL_OES, texture_name_, + GL_RGBA8_OES}; + auto backendTexture = + GrBackendTextures::MakeGL(1, 1, skgpu::Mipmapped::kNo, textureInfo); + dl_image_ = DlImage::Make(SkImages::BorrowTextureFrom( + context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin, + kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr)); +} + +void SurfaceTextureExternalTextureGL::Detach() { + SurfaceTextureExternalTexture::Detach(); + if (texture_name_ != 0) { + glDeleteTextures(1, &texture_name_); + texture_name_ = 0; + } +} + +SurfaceTextureExternalTextureImpellerGL:: + SurfaceTextureExternalTextureImpellerGL( + const std::shared_ptr& context, + int64_t id, + const fml::jni::ScopedJavaGlobalRef& surface_texture, + std::shared_ptr jni_facade) + : SurfaceTextureExternalTexture(id, surface_texture, jni_facade), + impeller_context_(context) {} + +SurfaceTextureExternalTextureImpellerGL:: + ~SurfaceTextureExternalTextureImpellerGL() { + Detach(); +} + +void SurfaceTextureExternalTextureImpellerGL::ProcessFrame( + PaintContext& context, + const SkRect& bounds) { + if (state_ == AttachmentState::kUninitialized) { + // Generate the texture handle. + impeller::TextureDescriptor desc; + desc.type = impeller::TextureType::kTextureExternalOES; + desc.storage_mode = impeller::StorageMode::kDevicePrivate; + desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt; + desc.size = {static_cast(bounds.width()), + static_cast(bounds.height())}; + desc.mip_count = 1; + texture_ = std::make_shared( + impeller_context_->GetReactor(), desc, + impeller::TextureGLES::IsWrapped::kWrapped); + texture_->SetCoordinateSystem( + impeller::TextureCoordinateSystem::kUploadFromHost); + auto maybe_handle = texture_->GetGLHandle(); + if (!maybe_handle.has_value()) { + FML_LOG(ERROR) << "Could not get GL handle from impeller::TextureGLES!"; + return; + } + Attach(maybe_handle.value()); + } + FML_CHECK(state_ == AttachmentState::kAttached); + + // Updates the texture contents and transformation matrix. + Update(); + + dl_image_ = impeller::DlImageImpeller::Make(texture_); +} + +void SurfaceTextureExternalTextureImpellerGL::Detach() { + SurfaceTextureExternalTexture::Detach(); + texture_.reset(); +} + +} // namespace flutter diff --git a/shell/platform/android/surface_texture_external_texture_gl.h b/shell/platform/android/surface_texture_external_texture_gl.h new file mode 100644 index 0000000000000..3bfa3b8489ade --- /dev/null +++ b/shell/platform/android/surface_texture_external_texture_gl.h @@ -0,0 +1,64 @@ +// 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_SURFACE_TEXTURE_EXTERNAL_TEXTURE_GL_H_ +#define FLUTTER_SHELL_PLATFORM_SURFACE_TEXTURE_EXTERNAL_TEXTURE_GL_H_ + +#include "flutter/shell/platform/android/surface_texture_external_texture.h" + +#include "flutter/impeller/renderer/backend/gles/context_gles.h" +#include "flutter/impeller/renderer/backend/gles/gles.h" +#include "flutter/impeller/renderer/backend/gles/texture_gles.h" +#include "flutter/impeller/toolkit/egl/egl.h" +#include "flutter/impeller/toolkit/egl/image.h" +#include "flutter/impeller/toolkit/gles/texture.h" + +#include "flutter/impeller/renderer/backend/gles/context_gles.h" + +namespace flutter { + +class SurfaceTextureExternalTextureGL : public SurfaceTextureExternalTexture { + public: + SurfaceTextureExternalTextureGL( + int64_t id, + const fml::jni::ScopedJavaGlobalRef& surface_texture, + std::shared_ptr jni_facade); + + ~SurfaceTextureExternalTextureGL() override; + + private: + virtual void ProcessFrame(PaintContext& context, + const SkRect& bounds) override; + virtual void Detach() override; + + GLuint texture_name_ = 0; + + FML_DISALLOW_COPY_AND_ASSIGN(SurfaceTextureExternalTextureGL); +}; + +class SurfaceTextureExternalTextureImpellerGL + : public SurfaceTextureExternalTexture { + public: + SurfaceTextureExternalTextureImpellerGL( + const std::shared_ptr& context, + int64_t id, + const fml::jni::ScopedJavaGlobalRef& surface_texture, + std::shared_ptr jni_facade); + + ~SurfaceTextureExternalTextureImpellerGL() override; + + private: + virtual void ProcessFrame(PaintContext& context, + const SkRect& bounds) override; + virtual void Detach() override; + + const std::shared_ptr impeller_context_; + std::shared_ptr texture_; + + FML_DISALLOW_COPY_AND_ASSIGN(SurfaceTextureExternalTextureImpellerGL); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_SURFACE_TEXTURE_EXTERNAL_TEXTURE_GL_H_