diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 31bb08f46357a..514487a85d21a 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -723,6 +723,7 @@ FILE: ../../../flutter/shell/platform/darwin/common/framework/Headers/FlutterBin FILE: ../../../flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h FILE: ../../../flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h FILE: ../../../flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h +FILE: ../../../flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/FlutterChannels.mm FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/FlutterChannelsTest.m FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/FlutterCodecs.mm @@ -740,7 +741,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterHeadle FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Info.plist FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -818,6 +818,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartP FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputModel.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputModel.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.h diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h b/shell/platform/darwin/common/framework/Headers/FlutterTexture.h similarity index 100% rename from shell/platform/darwin/ios/framework/Headers/FlutterTexture.h rename to shell/platform/darwin/common/framework/Headers/FlutterTexture.h diff --git a/shell/platform/darwin/common/framework_shared.gni b/shell/platform/darwin/common/framework_shared.gni index 7b2b3cb2a16b5..8a679c4d6fa25 100644 --- a/shell/platform/darwin/common/framework_shared.gni +++ b/shell/platform/darwin/common/framework_shared.gni @@ -8,5 +8,6 @@ framework_shared_headers = "framework/Headers/FlutterBinaryMessenger.h", "framework/Headers/FlutterChannels.h", "framework/Headers/FlutterCodecs.h", + "framework/Headers/FlutterTexture.h", ], "abspath") diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index 6e00a098ee4ed..13ee3acd6c040 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -30,7 +30,6 @@ _flutter_framework_headers = [ "framework/Headers/FlutterPlatformViews.h", "framework/Headers/FlutterPlugin.h", "framework/Headers/FlutterPluginAppLifeCycleDelegate.h", - "framework/Headers/FlutterTexture.h", "framework/Headers/FlutterViewController.h", ] diff --git a/shell/platform/darwin/ios/ios_external_texture_gl.h b/shell/platform/darwin/ios/ios_external_texture_gl.h index dd627b8118d09..30c138af76584 100644 --- a/shell/platform/darwin/ios/ios_external_texture_gl.h +++ b/shell/platform/darwin/ios/ios_external_texture_gl.h @@ -8,7 +8,7 @@ #include "flutter/flow/texture.h" #include "flutter/fml/platform/darwin/cf_utils.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" -#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h" +#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h" namespace flutter { diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index 566d08052f072..b93379d89a83d 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -12,7 +12,7 @@ #include "flutter/fml/memory/weak_ptr.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/common/platform_view.h" -#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterTexture.h" +#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h" #include "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h" diff --git a/shell/platform/darwin/macos/BUILD.gn b/shell/platform/darwin/macos/BUILD.gn index c02bd28695762..4cb1fa32b559f 100644 --- a/shell/platform/darwin/macos/BUILD.gn +++ b/shell/platform/darwin/macos/BUILD.gn @@ -52,6 +52,8 @@ shared_library("create_flutter_framework_dylib") { "framework/Source/FlutterDartProject_Internal.h", "framework/Source/FlutterEngine.mm", "framework/Source/FlutterEngine_Internal.h", + "framework/Source/FlutterExternalTextureGL.h", + "framework/Source/FlutterExternalTextureGL.mm", "framework/Source/FlutterTextInputModel.h", "framework/Source/FlutterTextInputModel.mm", "framework/Source/FlutterTextInputPlugin.h", @@ -75,7 +77,10 @@ shared_library("create_flutter_framework_dylib") { cflags_objcc = [ "-fobjc-arc" ] - libs = [ "Cocoa.framework" ] + libs = [ + "Cocoa.framework", + "CoreVideo.framework", + ] } action("copy_dylib_and_update_framework_install_name") { diff --git a/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h b/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h index d0a4658872e8c..4f4583878ff15 100644 --- a/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h +++ b/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h @@ -11,6 +11,7 @@ #include "FlutterDartProject.h" #include "FlutterMacros.h" #include "FlutterPluginRegistrarMacOS.h" +#include "FlutterTexture.h" // TODO: Merge this file with the iOS FlutterEngine.h. @@ -20,7 +21,7 @@ * Coordinates a single instance of execution of a Flutter engine. */ FLUTTER_EXPORT -@interface FlutterEngine : NSObject +@interface FlutterEngine : NSObject /** * Initializes an engine with the given viewController. diff --git a/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h b/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h index b75a2b835444d..5fc794b92995d 100644 --- a/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h +++ b/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h @@ -11,4 +11,5 @@ #import "FlutterMacros.h" #import "FlutterPluginMacOS.h" #import "FlutterPluginRegistrarMacOS.h" +#import "FlutterTexture.h" #import "FlutterViewController.h" diff --git a/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h b/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h index b8c4409976bf3..bd760823a3863 100644 --- a/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h +++ b/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h @@ -9,6 +9,7 @@ #import "FlutterBinaryMessenger.h" #import "FlutterChannels.h" #import "FlutterMacros.h" +#import "FlutterTexture.h" // TODO: Merge this file and FlutterPluginMacOS.h with the iOS FlutterPlugin.h, sharing all but // the platform-specific methods. @@ -28,6 +29,12 @@ FLUTTER_EXPORT */ @property(nonnull, readonly) id messenger; +/** + * Returns a `FlutterTextureRegistry` for registering textures + * provided by the plugin. + */ +@property(nonnull, readonly) id textures; + /** * The view displaying Flutter content. May return |nil|, for instance in a headless environment. * diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index 8d5ec197a8c18..42044b9c13542 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -8,6 +8,7 @@ #include #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" #import "flutter/shell/platform/embedder/embedder.h" @@ -46,6 +47,12 @@ - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message; */ - (void)shutDownEngine; +/** + * Forwards texture copy request to the corresponding texture via |textureID|. + */ +- (BOOL)populateTextureWithIdentifier:(int64_t)textureID + openGLTexture:(FlutterOpenGLTexture*)openGLTexture; + @end #pragma mark - @@ -78,6 +85,10 @@ - (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine return _flutterEngine.binaryMessenger; } +- (id)textures { + return _flutterEngine; +} + - (NSView*)view { return _flutterEngine.viewController.view; } @@ -119,6 +130,14 @@ static void OnPlatformMessage(const FlutterPlatformMessage* message, FlutterEngi [engine engineCallbackOnPlatformMessage:message]; } +static bool OnAcquireExternalTexture(FlutterEngine* engine, + int64_t texture_identifier, + size_t width, + size_t height, + FlutterOpenGLTexture* open_gl_texture) { + return [engine populateTextureWithIdentifier:texture_identifier openGLTexture:open_gl_texture]; +} + #pragma mark - @implementation FlutterEngine { @@ -136,6 +155,9 @@ @implementation FlutterEngine { // Whether the engine can continue running after the view controller is removed. BOOL _allowHeadlessExecution; + + // A mapping of textureID to internal FlutterExternalTextureGL adapter. + NSMutableDictionary* _textures; } - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project { @@ -150,6 +172,7 @@ - (instancetype)initWithName:(NSString*)labelPrefix _project = project ?: [[FlutterDartProject alloc] init]; _messageHandlers = [[NSMutableDictionary alloc] init]; + _textures = [[NSMutableDictionary alloc] init]; _allowHeadlessExecution = allowHeadlessExecution; return self; @@ -177,6 +200,7 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint { .open_gl.present = (BoolCallback)OnPresent, .open_gl.fbo_callback = (UIntCallback)OnFBO, .open_gl.make_resource_current = (BoolCallback)OnMakeResourceCurrent, + .open_gl.gl_external_texture_frame_callback = (TextureFrameCallback)OnAcquireExternalTexture, }; // TODO(stuartmorgan): Move internal channel registration from FlutterViewController to here. @@ -398,4 +422,29 @@ - (void)setMessageHandlerOnChannel:(nonnull NSString*)channel return [[FlutterEngineRegistrar alloc] initWithPlugin:pluginName flutterEngine:self]; } +#pragma mark - FlutterTextureRegistrar + +- (BOOL)populateTextureWithIdentifier:(int64_t)textureID + openGLTexture:(FlutterOpenGLTexture*)openGLTexture { + return [_textures[@(textureID)] populateTexture:openGLTexture]; +} + +- (int64_t)registerTexture:(id)texture { + FlutterExternalTextureGL* FlutterTexture = + [[FlutterExternalTextureGL alloc] initWithFlutterTexture:texture]; + int64_t textureID = [FlutterTexture textureID]; + FlutterEngineRegisterExternalTexture(_engine, textureID); + _textures[@(textureID)] = FlutterTexture; + return textureID; +} + +- (void)textureFrameAvailable:(int64_t)textureID { + FlutterEngineMarkExternalTextureFrameAvailable(_engine, textureID); +} + +- (void)unregisterTexture:(int64_t)textureID { + FlutterEngineUnregisterExternalTexture(_engine, textureID); + [_textures removeObjectForKey:@(textureID)]; +} + @end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h b/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h new file mode 100644 index 0000000000000..5fad0ab1924ca --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h @@ -0,0 +1,34 @@ +// 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. + +#import + +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h" +#import "flutter/shell/platform/embedder/embedder.h" + +/** + * Used to bridge FlutterTexture object and handle the texture copy request the + * Flutter engine. + */ +@interface FlutterExternalTextureGL : NSObject + +/** + * Initializes a texture adapter with |texture| return a instance. + */ +- (nonnull instancetype)initWithFlutterTexture:(nonnull id)texture; + +/** + * Accepts texture buffer copy request from the Flutter engine. + * When the user side marks the textureID as available, the Flutter engine will + * callback to this method and ask for populate the |openGLTexture| object, + * such as the texture type and the format of the pixel buffer and the texture object. + */ +- (BOOL)populateTexture:(nonnull FlutterOpenGLTexture*)openGLTexture; + +/** + * Returns the ID for the FlutterTexture instance. + */ +- (int64_t)textureID; + +@end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm b/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm new file mode 100644 index 0000000000000..0314280e9f12d --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm @@ -0,0 +1,85 @@ +// 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. + +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h" + +#import +#import +#import + +static void OnCVOpenGLTextureRelease(CVOpenGLTextureRef cvOpenGLTexture) { + CVOpenGLTextureRelease(cvOpenGLTexture); +} + +@implementation FlutterExternalTextureGL { + /** + * OpenGL texture cache. + */ + CVOpenGLTextureCacheRef _openGLTextureCache; + /** + * User side texture object, used to copy pixel buffer. + */ + id _texture; +} + +- (instancetype)initWithFlutterTexture:(id)texture { + self = [super init]; + if (self) { + _texture = texture; + } + return self; +} + +- (int64_t)textureID { + return reinterpret_cast(self); +} + +- (BOOL)populateTexture:(FlutterOpenGLTexture*)openGLTexture { + // Copy the pixel buffer from the FlutterTexture instance implemented on the user side. + CVPixelBufferRef pixelBuffer = [_texture copyPixelBuffer]; + + if (!pixelBuffer) { + return NO; + } + + // Create the opengl texture cache if necessary. + if (!_openGLTextureCache) { + CGLContextObj context = [NSOpenGLContext currentContext].CGLContextObj; + CGLPixelFormatObj format = CGLGetPixelFormat(context); + if (CVOpenGLTextureCacheCreate(kCFAllocatorDefault, NULL, context, format, NULL, + &_openGLTextureCache) != kCVReturnSuccess) { + NSLog(@"Could not create texture cache."); + CVPixelBufferRelease(pixelBuffer); + return NO; + } + } + + // Try to clear the cache of OpenGL textures to save memory. + CVOpenGLTextureCacheFlush(_openGLTextureCache, 0); + + CVOpenGLTextureRef cvOpenGLTexture = NULL; + if (CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _openGLTextureCache, + pixelBuffer, NULL, + &cvOpenGLTexture) != kCVReturnSuccess) { + CVPixelBufferRelease(pixelBuffer); + return NO; + } + + openGLTexture->target = static_cast(CVOpenGLTextureGetTarget(cvOpenGLTexture)); + openGLTexture->name = static_cast(CVOpenGLTextureGetName(cvOpenGLTexture)); + openGLTexture->format = static_cast(GL_RGBA8); + openGLTexture->destruction_callback = (VoidCallback)OnCVOpenGLTextureRelease; + openGLTexture->user_data = cvOpenGLTexture; + openGLTexture->width = CVPixelBufferGetWidth(pixelBuffer); + openGLTexture->height = CVPixelBufferGetHeight(pixelBuffer); + + CVPixelBufferRelease(pixelBuffer); + return YES; +} + +- (void)dealloc { + CVOpenGLTextureCacheRelease(_openGLTextureCache); +} + +@end diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 72da210079e73..0a62ea71453b2 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -807,8 +807,16 @@ FlutterEngineResult FlutterEngineRun(size_t version, GrGLTextureInfo gr_texture_info = {texture.target, texture.name, texture.format}; - GrBackendTexture gr_backend_texture(size.width(), size.height(), - GrMipMapped::kNo, gr_texture_info); + size_t width = size.width(); + size_t height = size.height(); + + if (texture.width != 0 && texture.height != 0) { + width = texture.width; + height = texture.height; + } + + GrBackendTexture gr_backend_texture(width, height, GrMipMapped::kNo, + gr_texture_info); SkImage::TextureReleaseProc release_proc = texture.destruction_callback; auto image = SkImage::MakeFromTexture( context, // context diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 674e24ca6ca24..280e69f497dfa 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -219,7 +219,8 @@ typedef enum { } FlutterOpenGLTargetType; typedef struct { - /// Target texture of the active texture unit (example GL_TEXTURE_2D). + /// Target texture of the active texture unit (example GL_TEXTURE_2D or + /// GL_TEXTURE_RECTANGLE). uint32_t target; /// The name of the texture. uint32_t name; @@ -230,6 +231,14 @@ typedef struct { /// Callback invoked (on an engine managed thread) that asks the embedder to /// collect the texture. VoidCallback destruction_callback; + /// Optional parameters for texture height/width, default is 0, non-zero means + /// the texture has the specified width/height. Usually, when the texture type + /// is GL_TEXTURE_RECTANGLE, we need to specify the texture width/height to + /// tell the embedder to scale when rendering. + /// Width of the texture. + size_t width; + /// Height of the texture. + size_t height; } FlutterOpenGLTexture; typedef struct { diff --git a/shell/platform/embedder/embedder_external_texture_gl.cc b/shell/platform/embedder/embedder_external_texture_gl.cc index e170654bbd9cf..d3aedf7a46719 100644 --- a/shell/platform/embedder/embedder_external_texture_gl.cc +++ b/shell/platform/embedder/embedder_external_texture_gl.cc @@ -31,7 +31,11 @@ void EmbedderExternalTextureGL::Paint(SkCanvas& canvas, } if (last_image_) { - canvas.drawImage(last_image_, bounds.x(), bounds.y()); + if (bounds != SkRect::Make(last_image_->bounds())) { + canvas.drawImageRect(last_image_, bounds, nullptr); + } else { + canvas.drawImage(last_image_, bounds.x(), bounds.y()); + } } }