Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[macOS] Refactor rendering infrastructure #37789

Merged
merged 34 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
376d3cd
[macos] Refactor rendering process
knopp Nov 25, 2022
a4a545b
fix comments
knopp Nov 28, 2022
2657127
Put includes and imports together
knopp Nov 30, 2022
5d9a08c
Update shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm
knopp Dec 1, 2022
c6b54b9
Update shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm
knopp Dec 1, 2022
e184cea
Update shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm
knopp Dec 1, 2022
5ef610c
Update shell/platform/darwin/macos/framework/Source/FlutterPlatformVi…
knopp Dec 1, 2022
96ef01c
Update shell/platform/darwin/macos/framework/Source/FlutterRenderer.mm
knopp Dec 1, 2022
3fa4f7b
Remove cast
knopp Dec 1, 2022
0676efe
Do not manually add platform view layer to FlutterView
knopp Dec 1, 2022
33f11b6
Remove unnecesary _Internal header files
knopp Dec 1, 2022
e8e6bc7
Make surfaceManager a readonly property
knopp Dec 1, 2022
cb55070
Add comment
knopp Dec 1, 2022
18d0ce0
Style nit: Rewrite as a noun phrase.
knopp Dec 1, 2022
c272e1f
Naming nit for consistency with removeSurfaceForSize:
knopp Dec 1, 2022
1804415
Write as ternary conditional.
knopp Dec 1, 2022
0508b36
Fix plural in comment.
knopp Dec 1, 2022
bc3147b
Offset and index are already set to 0.
knopp Dec 1, 2022
fa645a0
Remove FlutterSurfaceManager lookupSurface
knopp Dec 5, 2022
1dce078
Update shell/platform/darwin/macos/framework/Source/FlutterThreadSync…
knopp Dec 13, 2022
5971c82
Update shell/platform/darwin/macos/framework/Source/FlutterSurfaceMan…
knopp Dec 13, 2022
9902324
Update shell/platform/darwin/macos/framework/Source/FlutterSurfaceMan…
knopp Dec 13, 2022
e077a6c
Update shell/platform/darwin/macos/framework/Source/FlutterRenderer.mm
knopp Dec 13, 2022
cb7c4b7
Update shell/platform/darwin/macos/framework/Source/FlutterSurfaceMan…
knopp Dec 13, 2022
a13d260
Update shell/platform/darwin/macos/framework/Source/FlutterSurfaceMan…
knopp Dec 13, 2022
e25e502
Update shell/platform/darwin/macos/framework/Source/FlutterSurfaceMan…
knopp Dec 13, 2022
117b15c
Update shell/platform/darwin/macos/framework/Source/FlutterSurfaceMan…
knopp Dec 13, 2022
6bab84a
Update shell/platform/darwin/macos/framework/Source/FlutterSurfaceMan…
knopp Dec 13, 2022
10275f7
Update shell/platform/darwin/macos/framework/Source/FlutterSurfaceMan…
knopp Dec 13, 2022
849a273
Fix build error
knopp Dec 13, 2022
71649f3
Address nits
knopp Dec 13, 2022
77b5209
Replace EVent with fml::AutoResetWaitableEvent
knopp Dec 13, 2022
768aca8
Remove unecessary CATransaction
knopp Dec 13, 2022
f981e60
Add GetRequiredFrameSize
knopp Dec 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -2717,8 +2717,6 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngin
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTexture.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTexture.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSurfaceHolder.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterKeyPrimaryResponder.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterKeyboardManager.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterKeyboardManager.mm
Expand All @@ -2739,10 +2737,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatf
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRendererTest.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizableBackingStoreProvider.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizableBackingStoreProvider.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterSurface.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterSurface.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManagerTest.mm
Expand All @@ -2754,6 +2750,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextI
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObjectTest.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextureRegistrar.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterTextureRegistrar.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterThreadSynchronizer.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterThreadSynchronizer.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm
Expand Down
10 changes: 4 additions & 6 deletions shell/platform/darwin/macos/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterEngine_Internal.h",
"framework/Source/FlutterExternalTexture.h",
"framework/Source/FlutterExternalTexture.mm",
"framework/Source/FlutterIOSurfaceHolder.h",
"framework/Source/FlutterIOSurfaceHolder.mm",
"framework/Source/FlutterKeyPrimaryResponder.h",
"framework/Source/FlutterKeyboardManager.h",
"framework/Source/FlutterKeyboardManager.mm",
Expand All @@ -88,10 +86,8 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterPlatformViewController.mm",
"framework/Source/FlutterRenderer.h",
"framework/Source/FlutterRenderer.mm",
"framework/Source/FlutterResizableBackingStoreProvider.h",
"framework/Source/FlutterResizableBackingStoreProvider.mm",
"framework/Source/FlutterResizeSynchronizer.h",
"framework/Source/FlutterResizeSynchronizer.mm",
"framework/Source/FlutterSurface.h",
"framework/Source/FlutterSurface.mm",
"framework/Source/FlutterSurfaceManager.h",
"framework/Source/FlutterSurfaceManager.mm",
"framework/Source/FlutterTextInputPlugin.h",
Expand All @@ -100,6 +96,8 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterTextInputSemanticsObject.mm",
"framework/Source/FlutterTextureRegistrar.h",
"framework/Source/FlutterTextureRegistrar.mm",
"framework/Source/FlutterThreadSynchronizer.h",
"framework/Source/FlutterThreadSynchronizer.mm",
"framework/Source/FlutterView.h",
"framework/Source/FlutterView.mm",
"framework/Source/FlutterViewController.mm",
Expand Down
65 changes: 3 additions & 62 deletions shell/platform/darwin/macos/framework/Source/FlutterCompositor.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

#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"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h"
#include "flutter/shell/platform/embedder/embedder.h"

namespace flutter {
Expand All @@ -28,8 +28,7 @@ class FlutterCompositor {
// It must not be null, and is typically FlutterViewEngineProvider.
explicit FlutterCompositor(
id<FlutterViewProvider> view_provider,
FlutterPlatformViewController* platform_views_controller,
id<MTLDevice> mtl_device);
FlutterPlatformViewController* platform_views_controller);

~FlutterCompositor() = default;

Expand All @@ -48,57 +47,12 @@ class FlutterCompositor {
bool CreateBackingStore(const FlutterBackingStoreConfig* config,
FlutterBackingStore* backing_store_out);

// 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. 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<bool(bool has_flutter_content)>;

// 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);

// 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.
typedef enum { kStarted, kPresenting, kEnded } FrameStatus;

protected:
// Returns the view associated with the view ID.
//
// Returns nil if the ID is invalid.
FlutterView* GetView(uint64_t view_id);

// Gets and sets the FrameStatus for the current frame.
void SetFrameStatus(FrameStatus frame_status);
FrameStatus GetFrameStatus();

// Clears the previous CALayers and updates the frame status to frame started.
void StartFrame();

// Calls the present callback and ensures the frame status is updated
// to frame ended, returning whether the present was successful or not.
bool EndFrame(bool has_flutter_content);

// Creates a CALayer object which is backed by the supplied IOSurface, and
// adds it to the root CALayer for the given view.
void InsertCALayerForIOSurface(
FlutterView* view,
const IOSurfaceRef& io_surface,
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
Expand All @@ -107,25 +61,12 @@ class FlutterCompositor {
const FlutterLayer* layer,
size_t layer_position);

// A list of the active CALayer objects for the frame that need to be removed.
std::list<CALayer*> active_ca_layers_;

// Where the compositor can query FlutterViews. Must not be null.
id<FlutterViewProvider> 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<MTLDevice> 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_;

// Current frame status.
FrameStatus frame_status_ = kEnded;

FML_DISALLOW_COPY_AND_ASSIGN(FlutterCompositor);
};

Expand Down
167 changes: 40 additions & 127 deletions shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@
#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<FlutterViewProvider> view_provider,
FlutterPlatformViewController* platform_view_controller,
id<MTLDevice> mtl_device)
: view_provider_(view_provider),
platform_view_controller_(platform_view_controller),
mtl_device_(mtl_device) {
FlutterPlatformViewController* platform_view_controller)
: view_provider_(view_provider), platform_view_controller_(platform_view_controller) {
FML_CHECK(view_provider != nullptr) << "view_provider cannot be nullptr";
}

Expand All @@ -23,103 +19,67 @@
// 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);
FlutterView* view = [view_provider_ 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.
FlutterRenderBackingStore* backingStore = [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;
}

FlutterSurface* surface = [view.surfaceManager surfaceForSize:size];
memset(backing_store_out, 0, sizeof(FlutterBackingStore));
backing_store_out->struct_size = sizeof(FlutterBackingStore);
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);
}
backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore);
backing_store_out->metal.texture = surface.asFlutterMetalTexture;
return true;
}

bool FlutterCompositor::Present(uint64_t view_id,
const FlutterLayer** layers,
size_t layers_count) {
FlutterView* view = GetView(view_id);
FlutterView* view = [view_provider_ 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<FlutterBackingStore*>(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;
NSMutableArray* surfaces = [NSMutableArray array];
for (size_t i = 0; i < layers_count; i++) {
const FlutterLayer* layer = layers[i];
if (layer->type == kFlutterLayerContentTypeBackingStore) {
FlutterSurface* surface =
[FlutterSurface fromFlutterMetalTexture:&layer->backing_store->metal.texture];

if (surface) {
FlutterSurfacePresentInfo* info = [[FlutterSurfacePresentInfo alloc] init];
info.surface = surface;
info.offset = CGPointMake(layer->offset.x, layer->offset.y);
info.zIndex = i;
[surfaces addObject:info];
}
};
}
}

return EndFrame(has_flutter_content);
[view.surfaceManager present:surfaces
notify:^{
for (size_t i = 0; i < layers_count; i++) {
const FlutterLayer* layer = layers[i];
switch (layer->type) {
case kFlutterLayerContentTypeBackingStore:
break;
case kFlutterLayerContentTypePlatformView:
PresentPlatformView(view, layer, i);
break;
}
}
[platform_view_controller_ disposePlatformViews];
}];

return true;
}

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";

Expand All @@ -128,7 +88,7 @@

FML_DCHECK(platform_view) << "Platform view not found for id: " << platform_view_id;

CGFloat scale = [[NSScreen mainScreen] backingScaleFactor];
CGFloat scale = platform_view.layer.contentsScale;
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) {
Expand All @@ -137,51 +97,4 @@
platform_view.layer.zPosition = layer_position;
}

void FlutterCompositor::SetPresentCallback(
const FlutterCompositor::PresentCallback& present_callback) {
present_callback_ = present_callback;
}

void FlutterCompositor::StartFrame() {
// First remove all CALayers from the superlayer.
for (auto layer : active_ca_layers_) {
[layer removeFromSuperlayer];
}

// Reset active layers.
active_ca_layers_.clear();
SetFrameStatus(FrameStatus::kStarted);
}

bool FlutterCompositor::EndFrame(bool has_flutter_content) {
bool status = present_callback_(has_flutter_content);
SetFrameStatus(FrameStatus::kEnded);
return status;
}

FlutterView* FlutterCompositor::GetView(uint64_t view_id) {
return [view_provider_ getView:view_id];
}

void FlutterCompositor::SetFrameStatus(FlutterCompositor::FrameStatus frame_status) {
frame_status_ = frame_status;
}

FlutterCompositor::FrameStatus FlutterCompositor::GetFrameStatus() {
return frame_status_;
}

void FlutterCompositor::InsertCALayerForIOSurface(FlutterView* view,
const IOSurfaceRef& io_surface,
CATransform3D transform) {
// FlutterCompositor manages the lifecycle of CALayers.
CALayer* content_layer = [[CALayer alloc] init];
content_layer.transform = transform;
content_layer.frame = view.layer.bounds;
[content_layer setContents:(__bridge id)io_surface];
[view.layer addSublayer:content_layer];

active_ca_layers_.push_back(content_layer);
}

} // namespace flutter
Loading