diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 83d3b324cae10..b9363219a93d3 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2596,6 +2596,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterChann FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponderUnittests.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositorUnittests.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm @@ -2621,9 +2622,6 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMenuP FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMenuPlugin.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMenuPluginTest.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMenuPlugin_Internal.h -FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.h -FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.mm -FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositorUnittests.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRendererTest.mm diff --git a/shell/platform/darwin/macos/BUILD.gn b/shell/platform/darwin/macos/BUILD.gn index 1802069cd207a..a7b62727ff526 100644 --- a/shell/platform/darwin/macos/BUILD.gn +++ b/shell/platform/darwin/macos/BUILD.gn @@ -82,8 +82,6 @@ source_set("flutter_framework_source") { "framework/Source/FlutterMenuPlugin.h", "framework/Source/FlutterMenuPlugin.mm", "framework/Source/FlutterMenuPlugin_Internal.h", - "framework/Source/FlutterMetalCompositor.h", - "framework/Source/FlutterMetalCompositor.mm", "framework/Source/FlutterMetalRenderer.h", "framework/Source/FlutterMetalRenderer.mm", "framework/Source/FlutterMouseCursorPlugin.h", @@ -171,6 +169,7 @@ executable("flutter_desktop_darwin_unittests") { sources = [ "framework/Source/AccessibilityBridgeMacTest.mm", "framework/Source/FlutterChannelKeyResponderUnittests.mm", + "framework/Source/FlutterCompositorUnittests.mm", "framework/Source/FlutterEmbedderExternalTextureUnittests.mm", "framework/Source/FlutterEmbedderKeyResponderUnittests.mm", "framework/Source/FlutterEngineTest.mm", @@ -178,7 +177,6 @@ executable("flutter_desktop_darwin_unittests") { "framework/Source/FlutterEngineTestUtils.mm", "framework/Source/FlutterKeyboardManagerUnittests.mm", "framework/Source/FlutterMenuPluginTest.mm", - "framework/Source/FlutterMetalCompositorUnittests.mm", "framework/Source/FlutterMetalRendererTest.mm", "framework/Source/FlutterMetalSurfaceManagerTest.mm", "framework/Source/FlutterPlatformNodeDelegateMacTest.mm", diff --git a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h index 9a7249d7dc1d6..66cf7b8939d37 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h @@ -9,6 +9,7 @@ #include #include "flutter/fml/macros.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.h" #include "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h" #include "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h" #include "flutter/shell/platform/embedder/embedder.h" @@ -25,52 +26,57 @@ class FlutterCompositor { // The view_provider is used to query FlutterViews from view IDs, // which are used for presenting and creating backing stores. // It must not be null, and is typically FlutterViewEngineProvider. - explicit FlutterCompositor(id view_provider); + explicit FlutterCompositor( + id view_provider, + FlutterPlatformViewController* platform_views_controller, + id mtl_device); - virtual ~FlutterCompositor() = default; + ~FlutterCompositor() = default; - // Creates a BackingStore and saves updates the backing_store_out - // data with the new BackingStore data. - // If the backing store is being requested for the first time - // for a given frame, this compositor does not create a new backing - // store but rather returns the backing store associated with the - // FlutterView's FlutterSurfaceManager. + // Creates a backing store and saves updates the backing_store_out data with + // the new FlutterBackingStore data. // - // Any additional state allocated for the backing store and - // saved as user_data in the backing store must be collected - // in the backing_store's destruction_callback field which will - // be called when the embedder collects the backing store. - virtual bool CreateBackingStore(const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) = 0; + // If the backing store is being requested for the first time for a given + // frame, this compositor does not create a new backing store but rather + // returns the backing store associated with the FlutterView's + // FlutterSurfaceManager. + // + // Any additional state allocated for the backing store and saved as + // user_data in the backing store must be collected in the backing_store's + // destruction_callback field which will be called when the embedder collects + // the backing store. + bool CreateBackingStore(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out); - // Releases the memory for any state used by the backing store. - virtual bool CollectBackingStore( - const FlutterBackingStore* backing_store) = 0; + // Releases the memory for any resources that were allocated for the + // specified backing store. + bool CollectBackingStore(const FlutterBackingStore* backing_store); // Presents the FlutterLayers by updating the FlutterView specified by - // `view_id` using the layer content. - // Present sets frame_started_ to false. - virtual bool Present(uint64_t view_id, - const FlutterLayer** layers, - size_t layers_count) = 0; + // `view_id` using the layer content. Sets frame_started_ to false. + bool Present(uint64_t view_id, + const FlutterLayer** layers, + size_t layers_count); + // Callback triggered at the end of the Present function. has_flutter_content + // is true when Flutter content was rendered, otherwise false. using PresentCallback = std::function; - // PresentCallback is called at the end of the Present function. + // Registers a callback to be triggered at the end of the Present function. + // If a callback was previously registered, it will be replaced. void SetPresentCallback(const PresentCallback& present_callback); - // Denotes the current status of the frame being composited. - // Started: A new frame has begun and we have cleared the old layer tree - // and are now creating backingstore(s) for the embedder to use. + // The status of the frame being composited. + // Started: A new frame has begun and we have cleared the old layer tree and + // are now creating backingstore(s) for the embedder to use. // Presenting: the embedder has finished rendering into the provided - // backingstore(s) and we are creating the layer tree for the - // system compositor to present with. - // Ended: The frame has been presented and we are no longer processing - // it. + // backingstore(s) and we are creating the layer tree for the system + // compositor to present with. + // Ended: The frame has been presented and we are no longer processing it. typedef enum { kStarted, kPresenting, kEnded } FrameStatus; protected: - // Get the view associated with the view ID. + // Returns the view associated with the view ID. // // Returns nil if the ID is invalid. FlutterView* GetView(uint64_t view_id); @@ -94,12 +100,25 @@ class FlutterCompositor { CATransform3D transform = CATransform3DIdentity); private: + // Presents the platform view layer represented by `layer`. `layer_index` is + // used to position the layer in the z-axis. If the layer does not have a + // superview, it will become subview of `default_base_view`. + void PresentPlatformView(FlutterView* default_base_view, + const FlutterLayer* layer, + size_t layer_position); + // A list of the active CALayer objects for the frame that need to be removed. std::list active_ca_layers_; // Where the compositor can query FlutterViews. Must not be null. id const view_provider_; + // The controller used to manage creation and deletion of platform views. + const FlutterPlatformViewController* platform_view_controller_; + + // The Metal device used to draw graphics. + const id mtl_device_; + // Callback set by the embedder to be called when the layer tree has been // correctly set up for this frame. PresentCallback present_callback_; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm index 70be1049d0bcd..1cb1a412af769 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm @@ -3,13 +3,139 @@ // found in the LICENSE file. #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h" + #include "flutter/fml/logging.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h" namespace flutter { -FlutterCompositor::FlutterCompositor(id view_provider) - : view_provider_(view_provider) { - FML_CHECK(view_provider != nullptr) << "FlutterViewProvider* cannot be nullptr"; +FlutterCompositor::FlutterCompositor(id view_provider, + FlutterPlatformViewController* platform_view_controller, + id mtl_device) + : view_provider_(view_provider), + platform_view_controller_(platform_view_controller), + mtl_device_(mtl_device) { + FML_CHECK(view_provider != nullptr) << "view_provider cannot be nullptr"; +} + +bool FlutterCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config, + FlutterBackingStore* backing_store_out) { + // TODO(dkwingsmt): This class only supports single-view for now. As more + // classes are gradually converted to multi-view, it should get the view ID + // from somewhere. + FlutterView* view = GetView(kFlutterDefaultViewId); + if (!view) { + return false; + } + + CGSize size = CGSizeMake(config->size.width, config->size.height); + + backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore); + backing_store_out->metal.texture.struct_size = sizeof(FlutterMetalTexture); + + if (GetFrameStatus() != FrameStatus::kStarted) { + StartFrame(); + // If the backing store is for the first layer, return the MTLTexture for the + // FlutterView. + FlutterMetalRenderBackingStore* backingStore = + reinterpret_cast([view backingStoreForSize:size]); + backing_store_out->metal.texture.texture = + (__bridge FlutterMetalTextureHandle)backingStore.texture; + } else { + FlutterIOSurfaceHolder* io_surface_holder = [[FlutterIOSurfaceHolder alloc] init]; + [io_surface_holder recreateIOSurfaceWithSize:size]; + auto texture_descriptor = + [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm + width:size.width + height:size.height + mipmapped:NO]; + texture_descriptor.usage = + MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget | MTLTextureUsageShaderWrite; + + backing_store_out->metal.texture.texture = (__bridge_retained FlutterMetalTextureHandle) + [mtl_device_ newTextureWithDescriptor:texture_descriptor + iosurface:[io_surface_holder ioSurface] + plane:0]; + + backing_store_out->metal.texture.user_data = (__bridge_retained void*)io_surface_holder; + } + + backing_store_out->type = kFlutterBackingStoreTypeMetal; + backing_store_out->metal.texture.destruction_callback = [](void* user_data) { + if (user_data != nullptr) { + CFRelease(user_data); + } + }; + + return true; +} + +bool FlutterCompositor::CollectBackingStore(const FlutterBackingStore* backing_store) { + // If we allocated this MTLTexture ourselves, user_data is not null, and we will need + // to release it manually. + if (backing_store->metal.texture.user_data != nullptr && + backing_store->metal.texture.texture != nullptr) { + CFRelease(backing_store->metal.texture.texture); + } + return true; +} + +bool FlutterCompositor::Present(uint64_t view_id, + const FlutterLayer** layers, + size_t layers_count) { + FlutterView* view = GetView(view_id); + if (!view) { + return false; + } + + SetFrameStatus(FrameStatus::kPresenting); + + bool has_flutter_content = false; + for (size_t i = 0; i < layers_count; ++i) { + const auto* layer = layers[i]; + FlutterBackingStore* backing_store = const_cast(layer->backing_store); + + switch (layer->type) { + case kFlutterLayerContentTypeBackingStore: { + if (backing_store->metal.texture.user_data) { + FlutterIOSurfaceHolder* io_surface_holder = + (__bridge FlutterIOSurfaceHolder*)backing_store->metal.texture.user_data; + IOSurfaceRef io_surface = [io_surface_holder ioSurface]; + InsertCALayerForIOSurface(view, io_surface); + } + has_flutter_content = true; + break; + } + case kFlutterLayerContentTypePlatformView: { + PresentPlatformView(view, layer, i); + break; + } + }; + } + + return EndFrame(has_flutter_content); +} + +void FlutterCompositor::PresentPlatformView(FlutterView* default_base_view, + const FlutterLayer* layer, + size_t layer_position) { + // TODO (https://github.com/flutter/flutter/issues/96668) + // once the issue is fixed, this check will pass. + FML_DCHECK([[NSThread currentThread] isMainThread]) + << "Must be on the main thread to present platform views"; + + int64_t platform_view_id = layer->platform_view->identifier; + NSView* platform_view = [platform_view_controller_ platformViewWithID:platform_view_id]; + + FML_DCHECK(platform_view) << "Platform view not found for id: " << platform_view_id; + + CGFloat scale = [[NSScreen mainScreen] backingScaleFactor]; + platform_view.frame = CGRectMake(layer->offset.x / scale, layer->offset.y / scale, + layer->size.width / scale, layer->size.height / scale); + if (platform_view.superview == nil) { + [default_base_view addSubview:platform_view]; + } + platform_view.layer.zPosition = layer_position; } void FlutterCompositor::SetPresentCallback( diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositorUnittests.mm b/shell/platform/darwin/macos/framework/Source/FlutterCompositorUnittests.mm similarity index 79% rename from shell/platform/darwin/macos/framework/Source/FlutterMetalCompositorUnittests.mm rename to shell/platform/darwin/macos/framework/Source/FlutterCompositorUnittests.mm index 4084a61395d3f..b9f9f10b7807c 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositorUnittests.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterCompositorUnittests.mm @@ -5,7 +5,7 @@ #import #import -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h" #import "flutter/testing/testing.h" @@ -62,10 +62,10 @@ - (nullable FlutterView*)getView:(uint64_t)viewId { } } // namespace -TEST(FlutterMetalCompositorTest, TestPresent) { - std::unique_ptr macos_compositor = - std::make_unique( - MockViewProvider(), /*platform_view_controller*/ nullptr, /*mtl_device*/ nullptr); +TEST(FlutterCompositorTest, TestPresent) { + std::unique_ptr macos_compositor = + std::make_unique(MockViewProvider(), /*platform_view_controller*/ nullptr, + /*mtl_device*/ nullptr); bool flag = false; macos_compositor->SetPresentCallback([f = &flag](bool has_flutter_content) { @@ -77,10 +77,10 @@ - (nullable FlutterView*)getView:(uint64_t)viewId { ASSERT_TRUE(flag); } -TEST(FlutterMetalCompositorTest, TestCreate) { - std::unique_ptr macos_compositor = - std::make_unique( - MockViewProvider(), /*platform_view_controller*/ nullptr, /*mtl_device*/ nullptr); +TEST(FlutterCompositorTest, TestCreate) { + std::unique_ptr macos_compositor = + std::make_unique(MockViewProvider(), /*platform_view_controller*/ nullptr, + /*mtl_device*/ nullptr); FlutterBackingStore backing_store; FlutterBackingStoreConfig config; @@ -96,10 +96,10 @@ - (nullable FlutterView*)getView:(uint64_t)viewId { ASSERT_EQ(texture.height, 600ul); } -TEST(FlutterMetalCompositorTest, TestCompositing) { - std::unique_ptr macos_compositor = - std::make_unique( - MockViewProvider(), /*platform_view_controller*/ nullptr, /*mtl_device*/ nullptr); +TEST(FlutterCompositorTest, TestCompositing) { + std::unique_ptr macos_compositor = + std::make_unique(MockViewProvider(), /*platform_view_controller*/ nullptr, + /*mtl_device*/ nullptr); FlutterBackingStore backing_store; FlutterBackingStoreConfig config; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index 7dd0c864841eb..88df2550d6046 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -9,9 +9,9 @@ #include #include +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMenuPlugin.h" -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMouseCursorPlugin.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.h" @@ -202,9 +202,8 @@ @implementation FlutterEngine { // Pointer to the Dart AOT snapshot and instruction data. _FlutterEngineAOTData* _aotData; - // _macOSCompositor is created when the engine is created and - // its destruction is handled by ARC when the engine is destroyed. - // This is either a FlutterGLCompositor or a FlutterMetalCompositor instance. + // _macOSCompositor is created when the engine is created and its destruction is handled by ARC + // when the engine is destroyed. std::unique_ptr _macOSCompositor; FlutterViewEngineProvider* _viewProvider; @@ -424,7 +423,7 @@ - (FlutterCompositor*)createFlutterCompositor { __weak FlutterEngine* weakSelf = self; FlutterMetalRenderer* metalRenderer = reinterpret_cast(_renderer); - _macOSCompositor = std::make_unique( + _macOSCompositor = std::make_unique( _viewProvider, _platformViewController, metalRenderer.device); _macOSCompositor->SetPresentCallback([weakSelf](bool has_flutter_content) { if (has_flutter_content) { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.h b/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.h deleted file mode 100644 index b2406baf91dea..0000000000000 --- a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.h +++ /dev/null @@ -1,66 +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. - -#ifndef FLUTTER_METAL_COMPOSITOR_H_ -#define FLUTTER_METAL_COMPOSITOR_H_ - -#include "flutter/fml/macros.h" -#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h" -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.h" - -namespace flutter { - -class FlutterMetalCompositor : public FlutterCompositor { - public: - explicit FlutterMetalCompositor( - id view_provider, - FlutterPlatformViewController* platform_views_controller, - id mtl_device); - - virtual ~FlutterMetalCompositor() = default; - - // Creates a BackingStore and sets backing_store_out to a - // FlutterBackingStore struct containing details of the new - // backing store. - // - // If the backing store is being requested for the first time - // for a given frame, this compositor does not create a new backing - // store but rather returns the backing store associated with the - // FlutterView's FlutterSurfaceManager. - // - // Any additional state allocated for the backing store and - // saved as user_data in the backing store must be collected - // in backing_store_out's destruction_callback field which will - // be called when the embedder collects the backing store. - bool CreateBackingStore(const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) override; - - // Releases and deallocates any and all resources that were allocated - // for this FlutterBackingStore object in CreateBackingStore. - bool CollectBackingStore(const FlutterBackingStore* backing_store) override; - - // Presents the FlutterLayers by updating the FlutterView specified by - // `view_id` using the layer content. - // Present sets frame_started_ to false. - bool Present(uint64_t view_id, - const FlutterLayer** layers, - size_t layers_count) override; - - private: - // Presents the platform view layer represented by `layer`. `layer_index` is - // used to position the layer in the z-axis. If the layer does not have a - // superview, it will become subview of `default_base_view`. - void PresentPlatformView(FlutterView* default_base_view, - const FlutterLayer* layer, - size_t layer_position); - - const id mtl_device_; - const FlutterPlatformViewController* platform_views_controller_; - - FML_DISALLOW_COPY_AND_ASSIGN(FlutterMetalCompositor); -}; - -} // namespace flutter - -#endif // FLUTTER_METAL_COMPOSITOR_H_ diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.mm deleted file mode 100644 index 2e8ff9b176c5b..0000000000000 --- a/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.mm +++ /dev/null @@ -1,141 +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. - -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalCompositor.h" - -#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h" - -#include "flutter/fml/logging.h" - -namespace flutter { - -FlutterMetalCompositor::FlutterMetalCompositor( - id view_provider, - FlutterPlatformViewController* platform_views_controller, - id mtl_device) - : FlutterCompositor(view_provider), - mtl_device_(mtl_device), - platform_views_controller_(platform_views_controller) {} - -bool FlutterMetalCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config, - FlutterBackingStore* backing_store_out) { - // TODO(dkwingsmt): This class only supports single-view for now. As more - // classes are gradually converted to multi-view, it should get the view ID - // from somewhere. - FlutterView* view = GetView(kFlutterDefaultViewId); - if (!view) { - return false; - } - - CGSize size = CGSizeMake(config->size.width, config->size.height); - - backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore); - backing_store_out->metal.texture.struct_size = sizeof(FlutterMetalTexture); - - if (GetFrameStatus() != FrameStatus::kStarted) { - StartFrame(); - // If the backing store is for the first layer, return the MTLTexture for the - // FlutterView. - FlutterMetalRenderBackingStore* backingStore = - reinterpret_cast([view backingStoreForSize:size]); - backing_store_out->metal.texture.texture = - (__bridge FlutterMetalTextureHandle)backingStore.texture; - } else { - FlutterIOSurfaceHolder* io_surface_holder = [[FlutterIOSurfaceHolder alloc] init]; - [io_surface_holder recreateIOSurfaceWithSize:size]; - auto texture_descriptor = - [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm - width:size.width - height:size.height - mipmapped:NO]; - texture_descriptor.usage = - MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget | MTLTextureUsageShaderWrite; - - backing_store_out->metal.texture.texture = (__bridge_retained FlutterMetalTextureHandle) - [mtl_device_ newTextureWithDescriptor:texture_descriptor - iosurface:[io_surface_holder ioSurface] - plane:0]; - - backing_store_out->metal.texture.user_data = (__bridge_retained void*)io_surface_holder; - } - - backing_store_out->type = kFlutterBackingStoreTypeMetal; - backing_store_out->metal.texture.destruction_callback = [](void* user_data) { - if (user_data != nullptr) { - CFRelease(user_data); - } - }; - - return true; -} - -bool FlutterMetalCompositor::CollectBackingStore(const FlutterBackingStore* backing_store) { - // If we allocated this MTLTexture ourselves, user_data is not null, and we will need - // to release it manually. - if (backing_store->metal.texture.user_data != nullptr && - backing_store->metal.texture.texture != nullptr) { - CFRelease(backing_store->metal.texture.texture); - } - return true; -} - -bool FlutterMetalCompositor::Present(uint64_t view_id, - const FlutterLayer** layers, - size_t layers_count) { - FlutterView* view = GetView(view_id); - if (!view) { - return false; - } - - SetFrameStatus(FrameStatus::kPresenting); - - bool has_flutter_content = false; - for (size_t i = 0; i < layers_count; ++i) { - const auto* layer = layers[i]; - FlutterBackingStore* backing_store = const_cast(layer->backing_store); - - switch (layer->type) { - case kFlutterLayerContentTypeBackingStore: { - if (backing_store->metal.texture.user_data) { - FlutterIOSurfaceHolder* io_surface_holder = - (__bridge FlutterIOSurfaceHolder*)backing_store->metal.texture.user_data; - IOSurfaceRef io_surface = [io_surface_holder ioSurface]; - InsertCALayerForIOSurface(view, io_surface); - } - has_flutter_content = true; - break; - } - case kFlutterLayerContentTypePlatformView: { - PresentPlatformView(view, layer, i); - break; - } - }; - } - - return EndFrame(has_flutter_content); -} - -void FlutterMetalCompositor::PresentPlatformView(FlutterView* default_base_view, - const FlutterLayer* layer, - size_t layer_position) { - // TODO (https://github.com/flutter/flutter/issues/96668) - // once the issue is fixed, this check will pass. - FML_DCHECK([[NSThread currentThread] isMainThread]) - << "Must be on the main thread to present platform views"; - - int64_t platform_view_id = layer->platform_view->identifier; - NSView* platform_view = [platform_views_controller_ platformViewWithID:platform_view_id]; - - FML_DCHECK(platform_view) << "Platform view not found for id: " << platform_view_id; - - CGFloat scale = [[NSScreen mainScreen] backingScaleFactor]; - platform_view.frame = CGRectMake(layer->offset.x / scale, layer->offset.y / scale, - layer->size.width / scale, layer->size.height / scale); - if (platform_view.superview == nil) { - [default_base_view addSubview:platform_view]; - } - platform_view.layer.zPosition = layer_position; -} - -} // namespace flutter