diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index ddfd07d2a2c9a..d23245f977b8f 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -539,6 +539,8 @@ 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_external_texture_gl_share_context.cc +FILE: ../../../flutter/shell/platform/android/android_external_texture_gl_share_context.h FILE: ../../../flutter/shell/platform/android/android_native_window.cc FILE: ../../../flutter/shell/platform/android/android_native_window.h FILE: ../../../flutter/shell/platform/android/android_shell_holder.cc @@ -775,6 +777,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_i FILE: ../../../flutter/shell/platform/darwin/ios/framework/module.modulemap FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl.h FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl.mm +FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl_share_context.h +FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl_share_context.mm FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_context.h FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_context.mm FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_render_target.h diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 934120e0a563a..f58d5feadd686 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -28,6 +28,8 @@ shared_library("flutter_shell_native") { "android_environment_gl.h", "android_external_texture_gl.cc", "android_external_texture_gl.h", + "android_external_texture_gl_share_context.cc", + "android_external_texture_gl_share_context.h", "android_native_window.cc", "android_native_window.h", "android_shell_holder.cc", diff --git a/shell/platform/android/android_context_gl.cc b/shell/platform/android/android_context_gl.cc index d3fd715a38abc..ece127988371e 100644 --- a/shell/platform/android/android_context_gl.cc +++ b/shell/platform/android/android_context_gl.cc @@ -272,4 +272,8 @@ bool AndroidContextGL::Resize(const SkISize& size) { return true; } +EGLContext AndroidContextGL::GetShareContext() { + return context_; +} + } // namespace flutter diff --git a/shell/platform/android/android_context_gl.h b/shell/platform/android/android_context_gl.h index 50e15aba2ed4f..3c389b370ee0c 100644 --- a/shell/platform/android/android_context_gl.h +++ b/shell/platform/android/android_context_gl.h @@ -35,6 +35,8 @@ class AndroidContextGL : public fml::RefCountedThreadSafe { bool Resize(const SkISize& size); + EGLContext GetShareContext(); + private: fml::RefPtr environment_; fml::RefPtr window_; diff --git a/shell/platform/android/android_external_texture_gl_share_context.cc b/shell/platform/android/android_external_texture_gl_share_context.cc new file mode 100644 index 0000000000000..c620b5c2e6429 --- /dev/null +++ b/shell/platform/android/android_external_texture_gl_share_context.cc @@ -0,0 +1,56 @@ +// 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_share_context.h" + +#include + +#include "flutter/shell/platform/android/platform_view_android_jni.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" + +namespace flutter { + +AndroidExternalTextureShareContext::AndroidExternalTextureShareContext( + int64_t id, + int64_t shareTextureID) + : Texture(id), texture_id_(shareTextureID) {} + +AndroidExternalTextureShareContext::~AndroidExternalTextureShareContext() {} + +void AndroidExternalTextureShareContext::OnGrContextCreated() {} + +void AndroidExternalTextureShareContext::MarkNewFrameAvailable() {} + +void AndroidExternalTextureShareContext::Paint(SkCanvas& canvas, + const SkRect& bounds, + bool freeze, + GrContext* context) { + GrGLTextureInfo textureInfo = {GL_TEXTURE_EXTERNAL_OES, texture_id_, + GL_RGBA8_OES}; + + textureInfo.fTarget = GL_TEXTURE_2D; + transform.setIdentity(); + + GrBackendTexture backendTexture(1, 1, GrMipMapped::kNo, textureInfo); + sk_sp image = SkImage::MakeFromTexture( + canvas.getGrContext(), backendTexture, kTopLeft_GrSurfaceOrigin, + kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr); + if (image) { + SkAutoCanvasRestore autoRestore(&canvas, true); + canvas.translate(bounds.x(), bounds.y()); + canvas.scale(bounds.width(), bounds.height()); + if (!transform.isIdentity()) { + SkMatrix transformAroundCenter(transform); + + transformAroundCenter.preTranslate(-0.5, -0.5); + transformAroundCenter.postScale(1, -1); + transformAroundCenter.postTranslate(0.5, 0.5); + canvas.concat(transformAroundCenter); + } + canvas.drawImage(image, 0, 0); + } +} + +void AndroidExternalTextureShareContext::OnGrContextDestroyed() {} +} // namespace flutter diff --git a/shell/platform/android/android_external_texture_gl_share_context.h b/shell/platform/android/android_external_texture_gl_share_context.h new file mode 100644 index 0000000000000..f54fc087bd6ee --- /dev/null +++ b/shell/platform/android/android_external_texture_gl_share_context.h @@ -0,0 +1,43 @@ +// 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_ANDROID_EXTERNAL_TEXTURE_SHARE_CONTEXT_H_ +#define FLUTTER_SHELL_PLATFORM_ANDROID_EXTERNAL_TEXTURE_SHARE_CONTEXT_H_ + +#include +#include "flutter/flow/texture.h" +#include "flutter/fml/platform/android/jni_weak_ref.h" + +namespace flutter { + +class AndroidExternalTextureShareContext : public flutter::Texture { + public: + AndroidExternalTextureShareContext(int64_t id, int64_t shareTextureID); + + ~AndroidExternalTextureShareContext() override; + + void Paint(SkCanvas& canvas, + const SkRect& bounds, + bool freeze, + GrContext* context) override; + + void OnGrContextCreated() override; + + void OnGrContextDestroyed() override; + + void MarkNewFrameAvailable() override; + + private: + fml::jni::JavaObjectWeakGlobalRef surface_texture_; + + GLuint texture_id_ = 0; + + SkMatrix transform; + + FML_DISALLOW_COPY_AND_ASSIGN(AndroidExternalTextureShareContext); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_ANDROID_EXTERNAL_TEXTURE_GL_H_ diff --git a/shell/platform/android/android_surface.h b/shell/platform/android/android_surface.h index 43f4cf33d0d50..bdef5043cd665 100644 --- a/shell/platform/android/android_surface.h +++ b/shell/platform/android/android_surface.h @@ -7,6 +7,7 @@ #include +#include #include "flutter/fml/macros.h" #include "flutter/fml/platform/android/jni_util.h" #include "flutter/fml/platform/android/jni_weak_ref.h" @@ -36,6 +37,8 @@ class AndroidSurface { virtual bool ResourceContextClearCurrent() = 0; virtual bool SetNativeWindow(fml::RefPtr window) = 0; + + virtual EGLContext GetShareContext() = 0; }; } // namespace flutter diff --git a/shell/platform/android/android_surface_gl.cc b/shell/platform/android/android_surface_gl.cc index 737d9f293a518..4232ee7c65b01 100644 --- a/shell/platform/android/android_surface_gl.cc +++ b/shell/platform/android/android_surface_gl.cc @@ -130,4 +130,7 @@ ExternalViewEmbedder* AndroidSurfaceGL::GetExternalViewEmbedder() { return nullptr; } +EGLContext AndroidSurfaceGL::GetShareContext() { + return offscreen_context_->GetShareContext(); +} } // namespace flutter diff --git a/shell/platform/android/android_surface_gl.h b/shell/platform/android/android_surface_gl.h index d59302ad66509..d41e721f3c1b4 100644 --- a/shell/platform/android/android_surface_gl.h +++ b/shell/platform/android/android_surface_gl.h @@ -46,6 +46,9 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate, // |AndroidSurface| bool SetNativeWindow(fml::RefPtr window) override; + // |AndroidSurface| + EGLContext GetShareContext() override; + // |GPUSurfaceGLDelegate| bool GLContextMakeCurrent() override; diff --git a/shell/platform/android/android_surface_software.cc b/shell/platform/android/android_surface_software.cc index 620e15301a581..f656212a849d9 100644 --- a/shell/platform/android/android_surface_software.cc +++ b/shell/platform/android/android_surface_software.cc @@ -159,4 +159,8 @@ bool AndroidSurfaceSoftware::SetNativeWindow( return true; } +EGLContext AndroidSurfaceSoftware::GetShareContext() { + return 0; +} + } // namespace flutter diff --git a/shell/platform/android/android_surface_software.h b/shell/platform/android/android_surface_software.h index 30888091fe0d5..4af224d6be6eb 100644 --- a/shell/platform/android/android_surface_software.h +++ b/shell/platform/android/android_surface_software.h @@ -41,6 +41,9 @@ class AndroidSurfaceSoftware final : public AndroidSurface, // |AndroidSurface| bool SetNativeWindow(fml::RefPtr window) override; + // |AndroidSurface| + EGLContext GetShareContext() override; + // |GPUSurfaceSoftwareDelegate| sk_sp AcquireBackingStore(const SkISize& size) override; diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index fbd63888c19d1..ce0953ef6c1d4 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -14,6 +14,7 @@ import android.support.annotation.UiThread; import android.view.Surface; import android.view.SurfaceHolder; +import android.opengl.EGLContext; import java.nio.ByteBuffer; import java.util.HashSet; @@ -555,6 +556,23 @@ public void registerTexture(long textureId, @NonNull SurfaceTexture surfaceTextu private native void nativeRegisterTexture(long nativePlatformViewId, long textureId, @NonNull SurfaceTexture surfaceTexture); + + @UiThread + public void registerShareTexture(long texIndex, long shareTextureId) { + ensureAttachedToNative(); + nativeRegisterShareTexture(nativePlatformViewId, texIndex, shareTextureId); + } + + private native void nativeRegisterShareTexture(long nativePlatformViewId, long texIndex, long shareTextureId); + + @UiThread + public EGLContext getShareContext(long sdkInt) { + ensureAttachedToNative(); + return nativeGetShareContext(nativePlatformViewId,sdkInt); + } + + private native EGLContext nativeGetShareContext(long nativePlatformViewId,long sdkInt); + /** * Call this method to inform Flutter that a texture previously registered with * {@link #registerTexture(long, SurfaceTexture)} has a new frame available. diff --git a/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java b/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java index bac9132df255f..842432413f1a0 100644 --- a/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java +++ b/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java @@ -12,6 +12,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.Surface; +import android.opengl.EGLContext; import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicLong; @@ -120,6 +121,24 @@ public SurfaceTextureEntry createSurfaceTexture() { return entry; } + @Override + public TextureRegistry.ShareTextureEntry createShareTexture(long shareTextureID) { + final ShareTextureRegistryEntry entry = new ShareTextureRegistryEntry(nextTextureId.getAndIncrement(),shareTextureID); + Log.v(TAG, "New ShareTexture ID: " + entry.id()); + registerShareTexture(entry.id(),shareTextureID); + return entry; + } + + @Override + public void onShareFrameAvaliable(int textureIndex) { + markTextureFrameAvailable(textureIndex); + } + + @Override + public EGLContext getShareContext(long sdkInt) { + return flutterJNI.getShareContext(sdkInt); + } + final class SurfaceTextureRegistryEntry implements TextureRegistry.SurfaceTextureEntry { private final long id; @NonNull @@ -178,7 +197,33 @@ public void release() { released = true; } } - //------ END TextureRegistry IMPLEMENTATION ---- + + final class ShareTextureRegistryEntry implements TextureRegistry.ShareTextureEntry { + private final long id; + private final long textureID; + private boolean released; + ShareTextureRegistryEntry(long id, long shareTextureID) { + this.id = id; + this.textureID = shareTextureID; + } + + @Override + public long id() { + return id; + } + + @Override + public void release() { + if (released) { + return; + } + released = true; + unregisterTexture(id); + } + } + +//------ END TextureRegistry IMPLEMENTATION ---- + // TODO(mattcarroll): describe the native behavior that this invokes public void surfaceCreated(@NonNull Surface surface) { @@ -241,6 +286,10 @@ private void registerTexture(long textureId, @NonNull SurfaceTexture surfaceText flutterJNI.registerTexture(textureId, surfaceTexture); } + private void registerShareTexture(long textureId, long shareTextureID) { + flutterJNI.registerShareTexture(textureId, shareTextureID); + } + // TODO(mattcarroll): describe the native behavior that this invokes private void markTextureFrameAvailable(long textureId) { flutterJNI.markTextureFrameAvailable(textureId); diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index f10a72414fafa..237561d8ba5ad 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -36,6 +36,7 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.opengl.EGLContext; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -802,6 +803,23 @@ public TextureRegistry.SurfaceTextureEntry createSurfaceTexture() { return entry; } + @Override + public void onShareFrameAvaliable(int textureIndex) { + mNativeView.getFlutterJNI().markTextureFrameAvailable(textureIndex); + } + + @Override + public TextureRegistry.ShareTextureEntry createShareTexture(long shareTextureID) { + final ShareTextureRegistryEntry entry = new ShareTextureRegistryEntry(nextTextureId.getAndIncrement(),shareTextureID); + mNativeView.getFlutterJNI().registerShareTexture(entry.id(),shareTextureID); + return entry; + } + + @Override + public EGLContext getShareContext(long sdkInt) { + return mNativeView.getFlutterJNI().getShareContext(sdkInt); + } + final class SurfaceTextureRegistryEntry implements TextureRegistry.SurfaceTextureEntry { private final long id; private final SurfaceTexture surfaceTexture; @@ -865,4 +883,28 @@ public void release() { mNativeView.getFlutterJNI().unregisterTexture(id); } } + + final class ShareTextureRegistryEntry implements TextureRegistry.ShareTextureEntry { + private final long id; + private final long textureID; + private boolean released; + ShareTextureRegistryEntry(long id, long shareTextureID) { + this.id = id; + this.textureID = shareTextureID; + } + + @Override + public long id() { + return id; + } + + @Override + public void release() { + if (released) { + return; + } + released = true; + mNativeView.getFlutterJNI().unregisterTexture(id); + } + } } diff --git a/shell/platform/android/io/flutter/view/TextureRegistry.java b/shell/platform/android/io/flutter/view/TextureRegistry.java index ed3134bb035dd..46887b6093554 100644 --- a/shell/platform/android/io/flutter/view/TextureRegistry.java +++ b/shell/platform/android/io/flutter/view/TextureRegistry.java @@ -5,6 +5,7 @@ package io.flutter.view; import android.graphics.SurfaceTexture; +import android.opengl.EGLContext; /** * Registry of backend textures used with a single {@link FlutterView} instance. @@ -39,4 +40,42 @@ interface SurfaceTextureEntry { */ void release(); } + + /** + * Informs the the Flutter Engine that the external texture has been updated, and to start a new rendering pipeline. + */ + void onShareFrameAvaliable(int textureIndex); + + /** + * The OpenGL context created in the Flutter Engine, which is safe to user for sharing + * Param: Android SDK version code + */ + EGLContext getShareContext(long sdkInt); + + /** + * Create a ShareTextureEntry, and registers a External Texture in Flutter Engine + * The paramater is a OpenGL Texture ID + * Generally, this is used for users who process image frame with OpenGL(such as filter with GPUImage), and display the image frame using Flutter external texture + * Unlike SurfaceTexture, this can directly send the processed textures from OpenGL to flutter rendering pipeline. + * Avoid the performance consumption of data writing to SurfaceTexture + * Requirement: The OpenGL Texture should created in the EGLContext which is created using getShareContext(sdkInt) as a ShareContext + * @return A ShareTextureEntry. + */ + ShareTextureEntry createShareTexture(long shareTextureID); + + /** + * A registry entry for a managed ShareTexture. + */ + interface ShareTextureEntry { + + /** + * @return The identity of this ShareTexture. + */ + long id(); + + /** + * Deregisters and releases this ShareTexture. + */ + void release(); + } } diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 449a7e4571fba..d17387ebe32ce 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -11,6 +11,7 @@ #include "flutter/shell/common/shell_io_manager.h" #include "flutter/shell/gpu/gpu_surface_gl_delegate.h" #include "flutter/shell/platform/android/android_external_texture_gl.h" +#include "flutter/shell/platform/android/android_external_texture_gl_share_context.h" #include "flutter/shell/platform/android/android_surface_gl.h" #include "flutter/shell/platform/android/platform_message_response_android.h" #include "flutter/shell/platform/android/platform_view_android_jni.h" @@ -376,6 +377,17 @@ void PlatformViewAndroid::RegisterExternalTexture( std::make_shared(texture_id, surface_texture)); } +void PlatformViewAndroid::RegisterExternalShareTexture( + int64_t texture_id, + int64_t share_texture_id) { + RegisterTexture(std::make_shared( + texture_id, share_texture_id)); +} + +EGLContext PlatformViewAndroid::GetShareContext() { + return android_surface_->GetShareContext(); +} + // |PlatformView| std::unique_ptr PlatformViewAndroid::CreateVSyncWaiter() { return std::make_unique(task_runners_); diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index 74c0bbe6c26e7..7cf1a709b527b 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -10,6 +10,7 @@ #include #include +#include #include "flutter/fml/memory/weak_ptr.h" #include "flutter/fml/platform/android/jni_weak_ref.h" #include "flutter/fml/platform/android/scoped_java_ref.h" @@ -73,6 +74,11 @@ class PlatformViewAndroid final : public PlatformView { int64_t texture_id, const fml::jni::JavaObjectWeakGlobalRef& surface_texture); + void RegisterExternalShareTexture(int64_t texture_id, + int64_t share_texture_id); + + EGLContext GetShareContext(); + private: const fml::jni::JavaObjectWeakGlobalRef java_object_; const std::unique_ptr android_surface_; diff --git a/shell/platform/android/platform_view_android_jni.cc b/shell/platform/android/platform_view_android_jni.cc index f2d17dd13fbe1..6abe8a7da8995 100644 --- a/shell/platform/android/platform_view_android_jni.cc +++ b/shell/platform/android/platform_view_android_jni.cc @@ -8,6 +8,8 @@ #include +#include +#include #include "flutter/assets/directory_asset_bundle.h" #include "flutter/common/settings.h" #include "flutter/fml/file.h" @@ -444,6 +446,52 @@ static void RegisterTexture(JNIEnv* env, ); } +static void RegisterShareTexture(JNIEnv* env, + jobject jcaller, + jlong shell_holder, + jlong texture_id, + jlong share_texture_id) { + ANDROID_SHELL_HOLDER->GetPlatformView()->RegisterExternalShareTexture( + static_cast(texture_id), // + static_cast(share_texture_id) // + ); +} + +static jobject GetShareContext(JNIEnv* env, + jobject jcaller, + jlong shell_holder, + jlong sdk_int) { + EGLContext cxt = ANDROID_SHELL_HOLDER->GetPlatformView()->GetShareContext(); + + jclass eglcontextClassLocal = env->FindClass("android/opengl/EGLContext"); + jmethodID eglcontextConstructor; + jobject eglContext; + if (sdk_int >= 21) { + // 5.0and above + eglcontextConstructor = + env->GetMethodID(eglcontextClassLocal, "", "(J)V"); + if ((EGLContext)cxt == EGL_NO_CONTEXT) { + return env->NewObject(eglcontextClassLocal, eglcontextConstructor, + reinterpret_cast(EGL_NO_CONTEXT)); + } + eglContext = env->NewObject(eglcontextClassLocal, eglcontextConstructor, + reinterpret_cast(jlong(cxt))); + } else { + eglcontextConstructor = + env->GetMethodID(eglcontextClassLocal, "", "(I)V"); + int contextAddress = (int)(size_t)cxt; + if ((EGLContext)cxt == EGL_NO_CONTEXT) { + contextAddress = (int)(size_t)EGL_NO_CONTEXT; + return env->NewObject(eglcontextClassLocal, eglcontextConstructor, + reinterpret_cast(jint(contextAddress))); + } + eglContext = env->NewObject(eglcontextClassLocal, eglcontextConstructor, + reinterpret_cast(jint(contextAddress))); + } + + return eglContext; +} + static void MarkTextureFrameAvailable(JNIEnv* env, jobject jcaller, jlong shell_holder, @@ -592,7 +640,16 @@ bool RegisterApi(JNIEnv* env) { .signature = "(JJ)V", .fnPtr = reinterpret_cast(&UnregisterTexture), }, - + { + .name = "nativeRegisterShareTexture", + .signature = "(JJJ)V", + .fnPtr = reinterpret_cast(&RegisterShareTexture), + }, + { + .name = "nativeGetShareContext", + .signature = "(JJ)Landroid/opengl/EGLContext;", + .fnPtr = reinterpret_cast(&GetShareContext), + }, // Methods for Dart callback functionality. { .name = "nativeLookupCallbackInformation", diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index 6e00a098ee4ed..fe2fd44512e53 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -81,6 +81,8 @@ shared_library("create_flutter_framework_dylib") { "framework/Source/vsync_waiter_ios.mm", "ios_external_texture_gl.h", "ios_external_texture_gl.mm", + "ios_external_texture_gl_share_context.h", + "ios_external_texture_gl_share_context.mm", "ios_gl_context.h", "ios_gl_context.mm", "ios_gl_render_target.h", diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h b/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h index e7cd01337deb9..1f8ad9b87d801 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h @@ -8,11 +8,21 @@ #import #import +#import #include "FlutterMacros.h" NS_ASSUME_NONNULL_BEGIN FLUTTER_EXPORT +@protocol FlutterShareTexture +/* + *copy OpenGL Texture directly + *Returned Texture format should be GL_RGBA + *Returned Texture target should be GL_TEXTURE_2D + */ +- (GLuint)copyShareTexture; +@end + @protocol FlutterTexture - (CVPixelBufferRef _Nullable)copyPixelBuffer; @end @@ -20,8 +30,10 @@ FLUTTER_EXPORT FLUTTER_EXPORT @protocol FlutterTextureRegistry - (int64_t)registerTexture:(NSObject*)texture; +- (int64_t)registerShareTexture:(NSObject*)texture; - (void)textureFrameAvailable:(int64_t)textureId; - (void)unregisterTexture:(int64_t)textureId; +- (EAGLSharegroup*)getShareGroup; @end NS_ASSUME_NONNULL_END diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index ad7cfc263ee5d..884eaefec3822 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -554,6 +554,12 @@ - (int64_t)registerTexture:(NSObject*)texture { return textureId; } +- (int64_t)registerShareTexture:(NSObject*)texture { + int64_t textureId = _nextTextureId++; + self.iosPlatformView->RegisterExternalShareTexture(textureId, texture); + return textureId; +} + - (void)unregisterTexture:(int64_t)textureId { _shell->GetPlatformView()->UnregisterTexture(textureId); } @@ -562,6 +568,10 @@ - (void)textureFrameAvailable:(int64_t)textureId { _shell->GetPlatformView()->MarkTextureFrameAvailable(textureId); } +- (EAGLSharegroup*)getShareGroup { + return self.iosPlatformView->GetGLShareGroup(); +} + - (NSString*)lookupKeyForAsset:(NSString*)asset { return [FlutterDartProject lookupKeyForAsset:asset]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 3cea602f86bad..e2b1401937c70 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1118,6 +1118,10 @@ - (int64_t)registerTexture:(NSObject*)texture { return [_engine.get() registerTexture:texture]; } +- (int64_t)registerShareTexture:(NSObject*)texture { + return [_engine.get() registerShareTexture:texture]; +} + - (void)unregisterTexture:(int64_t)textureId { [_engine.get() unregisterTexture:textureId]; } @@ -1126,6 +1130,10 @@ - (void)textureFrameAvailable:(int64_t)textureId { [_engine.get() textureFrameAvailable:textureId]; } +- (id)getShareGroup { + return [_engine.get() getShareGroup]; +} + - (NSString*)lookupKeyForAsset:(NSString*)asset { return [FlutterDartProject lookupKeyForAsset:asset]; } diff --git a/shell/platform/darwin/ios/ios_external_texture_gl_share_context.h b/shell/platform/darwin/ios/ios_external_texture_gl_share_context.h new file mode 100644 index 0000000000000..e7e5e1cb4c16e --- /dev/null +++ b/shell/platform/darwin/ios/ios_external_texture_gl_share_context.h @@ -0,0 +1,37 @@ +// 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_IOS_EXTERNAL_TEXTURE_SHARE_CONTEXT_H_ +#define FLUTTER_SHELL_PLATFORM_IOS_EXTERNAL_TEXTURE_SHARE_CONTEXT_H_ + +#include "flutter/flow/texture.h" +#include "flutter/fml/platform/darwin/cf_utils.h" +#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h" + +namespace flutter { + +class IOSExternalTextureShareContext : public flutter::Texture { + public: + IOSExternalTextureShareContext(int64_t textureId, NSObject* externalTexture); + + ~IOSExternalTextureShareContext() override; + + // Called from GPU thread. + void Paint(SkCanvas& canvas, const SkRect& bounds, bool freeze, GrContext* context) override; + + void OnGrContextCreated() override; + + void OnGrContextDestroyed() override; + + void MarkNewFrameAvailable() override; + + private: + NSObject* external_texture_; + + FML_DISALLOW_COPY_AND_ASSIGN(IOSExternalTextureShareContext); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_IOS_EXTERNAL_TEXTURE_SHARE_CONTEXT_H_ diff --git a/shell/platform/darwin/ios/ios_external_texture_gl_share_context.mm b/shell/platform/darwin/ios/ios_external_texture_gl_share_context.mm new file mode 100644 index 0000000000000..c88b64f3920b1 --- /dev/null +++ b/shell/platform/darwin/ios/ios_external_texture_gl_share_context.mm @@ -0,0 +1,56 @@ +// 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/darwin/ios/ios_external_texture_gl_share_context.h" + +#import +#import +#import + +#include "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" + +namespace flutter { + +IOSExternalTextureShareContext::IOSExternalTextureShareContext( + int64_t textureId, + NSObject* externalTexture) + : Texture(textureId), external_texture_(externalTexture) { + FML_DCHECK(external_texture_); +} + +IOSExternalTextureShareContext::~IOSExternalTextureShareContext() = default; + +void IOSExternalTextureShareContext::Paint(SkCanvas& canvas, + const SkRect& bounds, + bool freeze, + GrContext* context) { + GLuint texture_id = [external_texture_ copyShareTexture]; + if (texture_id == 0) { + return; + } + GrGLTextureInfo textureInfo; + textureInfo.fFormat = GL_RGBA8_OES; + textureInfo.fID = texture_id; + textureInfo.fTarget = GL_TEXTURE_2D; + + GrBackendTexture backendTexture(bounds.width(), bounds.height(), GrMipMapped::kNo, textureInfo); + printf("paint test back\n"); + sk_sp image = + SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin, + kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr); + FML_DCHECK(image) << "Failed to create SkImage from Texture."; + if (image) { + canvas.drawImage(image, bounds.x(), bounds.y()); + } +} + +void IOSExternalTextureShareContext::OnGrContextCreated() {} + +void IOSExternalTextureShareContext::OnGrContextDestroyed() {} + +void IOSExternalTextureShareContext::MarkNewFrameAvailable() {} + +} // namespace flutter diff --git a/shell/platform/darwin/ios/ios_gl_context.h b/shell/platform/darwin/ios/ios_gl_context.h index 232645d9c8592..4697950b66872 100644 --- a/shell/platform/darwin/ios/ios_gl_context.h +++ b/shell/platform/darwin/ios/ios_gl_context.h @@ -32,6 +32,8 @@ class IOSGLContext { sk_sp ColorSpace() const { return color_space_; } + EAGLSharegroup* GetGLShareGroup(); + private: fml::scoped_nsobject context_; fml::scoped_nsobject resource_context_; diff --git a/shell/platform/darwin/ios/ios_gl_context.mm b/shell/platform/darwin/ios/ios_gl_context.mm index 52fb85f8f19a9..c965300db3b01 100644 --- a/shell/platform/darwin/ios/ios_gl_context.mm +++ b/shell/platform/darwin/ios/ios_gl_context.mm @@ -60,4 +60,9 @@ return [EAGLContext setCurrentContext:resource_context_.get()]; } +EAGLSharegroup* IOSGLContext::GetGLShareGroup() { + EAGLSharegroup* shareGroup = context_.get().sharegroup; + return shareGroup; +} + } // namespace flutter diff --git a/shell/platform/darwin/ios/ios_surface.h b/shell/platform/darwin/ios/ios_surface.h index 49f40f9eec76a..34f1a13fa5bc5 100644 --- a/shell/platform/darwin/ios/ios_surface.h +++ b/shell/platform/darwin/ios/ios_surface.h @@ -39,6 +39,8 @@ class IOSSurface { virtual std::unique_ptr CreateGPUSurface( GrContext* gr_context = nullptr) = 0; + virtual EAGLSharegroup* GetGLShareGroup() = 0; + protected: FlutterPlatformViewsController* GetPlatformViewsController(); diff --git a/shell/platform/darwin/ios/ios_surface_gl.h b/shell/platform/darwin/ios/ios_surface_gl.h index 964cc7adb692e..50d1b09213c99 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.h +++ b/shell/platform/darwin/ios/ios_surface_gl.h @@ -50,6 +50,8 @@ class IOSSurfaceGL final : public IOSSurface, bool UseOffscreenSurface() const override; + EAGLSharegroup* GetGLShareGroup() override; + // |GPUSurfaceGLDelegate| ExternalViewEmbedder* GetExternalViewEmbedder() override; diff --git a/shell/platform/darwin/ios/ios_surface_gl.mm b/shell/platform/darwin/ios/ios_surface_gl.mm index 9e838e200df34..543423aad0741 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.mm +++ b/shell/platform/darwin/ios/ios_surface_gl.mm @@ -73,6 +73,10 @@ return IsValid() && render_target_->PresentRenderBuffer(); } +EAGLSharegroup* IOSSurfaceGL::GetGLShareGroup() { + return context_.get()->GetGLShareGroup(); +} + // |ExternalViewEmbedder| sk_sp IOSSurfaceGL::GetRootSurface() { // On iOS, the root surface is created from the on-screen render target. Only the surfaces for the diff --git a/shell/platform/darwin/ios/ios_surface_software.h b/shell/platform/darwin/ios/ios_surface_software.h index d2ff61efdc4bf..4bbf755ae1233 100644 --- a/shell/platform/darwin/ios/ios_surface_software.h +++ b/shell/platform/darwin/ios/ios_surface_software.h @@ -36,6 +36,9 @@ class IOSSurfaceSoftware final : public IOSSurface, // |IOSSurface| std::unique_ptr CreateGPUSurface(GrContext* gr_context = nullptr) override; + // |IOSSurface| + EAGLSharegroup* GetGLShareGroup() override; + // |GPUSurfaceSoftwareDelegate| sk_sp AcquireBackingStore(const SkISize& size) override; diff --git a/shell/platform/darwin/ios/ios_surface_software.mm b/shell/platform/darwin/ios/ios_surface_software.mm index 4566bbf3f3624..e312425e19026 100644 --- a/shell/platform/darwin/ios/ios_surface_software.mm +++ b/shell/platform/darwin/ios/ios_surface_software.mm @@ -38,6 +38,10 @@ // Android oddities. } +EAGLSharegroup* IOSSurfaceSoftware::GetGLShareGroup() { + return nullptr; +} + std::unique_ptr IOSSurfaceSoftware::CreateGPUSurface(GrContext* gr_context) { if (!IsValid()) { return nullptr; diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index 38fc2a9f30b28..1462ef5c82132 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -37,6 +37,8 @@ class PlatformViewIOS final : public PlatformView { void RegisterExternalTexture(int64_t id, NSObject* texture); + void RegisterExternalShareTexture(int64_t id, NSObject* texture); + fml::scoped_nsprotocol GetTextInputPlugin() const; void SetTextInputPlugin(fml::scoped_nsprotocol plugin); @@ -44,6 +46,8 @@ class PlatformViewIOS final : public PlatformView { // |PlatformView| void SetSemanticsEnabled(bool enabled) override; + EAGLSharegroup* GetGLShareGroup(); + private: fml::WeakPtr owner_controller_; std::unique_ptr ios_surface_; diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index c80ae377c03a1..bc671ca65191c 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -16,6 +16,7 @@ #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" #include "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" #include "flutter/shell/platform/darwin/ios/ios_external_texture_gl.h" +#include "flutter/shell/platform/darwin/ios/ios_external_texture_gl_share_context.h" namespace flutter { @@ -71,6 +72,17 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), RegisterTexture(std::make_shared(texture_id, texture)); } +void PlatformViewIOS::RegisterExternalShareTexture(int64_t texture_id, + NSObject* texture) { + RegisterTexture(std::make_shared(texture_id, texture)); +} + +EAGLSharegroup* PlatformViewIOS::GetGLShareGroup() { + if (ios_surface_.get() == NULL) + return NULL; + return ios_surface_->GetGLShareGroup(); +} + // |PlatformView| std::unique_ptr PlatformViewIOS::CreateRenderingSurface() { if (!ios_surface_) {