Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[macos] Enable macOS platform views only for Metal #30853

Merged
merged 4 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppD
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterDartProject.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterPlatformViews.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterPluginMacOS.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h
Expand Down Expand Up @@ -1288,6 +1289,9 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenG
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMac.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMac.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewControllerTest.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.mm
Expand Down Expand Up @@ -1316,6 +1320,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/KeyCodeMap.m
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/KeyCodeMap_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/MacOSGLContextSwitch.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/MacOSGLContextSwitch.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/TestFlutterPlatformView.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/TestFlutterPlatformView.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/fixtures/flutter_desktop_test.dart
FILE: ../../../flutter/shell/platform/darwin/macos/framework/module.modulemap
FILE: ../../../flutter/shell/platform/embedder/assets/EmbedderInfo.plist
Expand Down
6 changes: 6 additions & 0 deletions shell/platform/darwin/macos/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ _flutter_framework_headers = [
"framework/Headers/FlutterDartProject.h",
"framework/Headers/FlutterEngine.h",
"framework/Headers/FlutterMacOS.h",
"framework/Headers/FlutterPlatformViews.h",
"framework/Headers/FlutterPluginMacOS.h",
"framework/Headers/FlutterPluginRegistrarMacOS.h",
"framework/Headers/FlutterViewController.h",
Expand Down Expand Up @@ -95,6 +96,8 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterOpenGLRenderer.mm",
"framework/Source/FlutterPlatformNodeDelegateMac.h",
"framework/Source/FlutterPlatformNodeDelegateMac.mm",
"framework/Source/FlutterPlatformViewController.h",
"framework/Source/FlutterPlatformViewController.mm",
"framework/Source/FlutterRenderer.h",
"framework/Source/FlutterRenderingBackend.h",
"framework/Source/FlutterRenderingBackend.mm",
Expand Down Expand Up @@ -186,11 +189,14 @@ executable("flutter_desktop_darwin_unittests") {
"framework/Source/FlutterMetalSurfaceManagerTest.mm",
"framework/Source/FlutterOpenGLRendererTest.mm",
"framework/Source/FlutterPlatformNodeDelegateMacTest.mm",
"framework/Source/FlutterPlatformViewControllerTest.mm",
"framework/Source/FlutterTextInputPluginTest.mm",
"framework/Source/FlutterTextInputSemanticsObjectTest.mm",
"framework/Source/FlutterViewControllerTest.mm",
"framework/Source/FlutterViewControllerTestUtils.h",
"framework/Source/FlutterViewControllerTestUtils.mm",
"framework/Source/TestFlutterPlatformView.h",
"framework/Source/TestFlutterPlatformView.mm",
]

cflags_objcc = flutter_cflags_objcc_arc
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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_FLUTTERPLATFORMVIEWS_H_
#define FLUTTER_FLUTTERPLATFORMVIEWS_H_

#import <AppKit/AppKit.h>

#import "FlutterCodecs.h"
#import "FlutterMacros.h"

@protocol FlutterPlatformViewFactory <NSObject>

/**
* Create a Platform View which is an `NSView`.
*
* A MacOS plugin should implement this method and return an `NSView`, which can be embedded in a
* Flutter App.
*
* The implementation of this method should create a new `NSView`.
*
* @param viewId A unique identifier for this view.
* @param args Parameters for creating the view sent from the Dart side of the
* Flutter app. If `createArgsCodec` is not implemented, or if no creation arguments were sent from
* the Dart code, this will be null. Otherwise this will be the value sent from the Dart code as
* decoded by `createArgsCodec`.
*/
- (nonnull NSView*)createWithviewIdentifier:(int64_t)viewId arguments:(nullable id)args;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

view is incorrectly capitalized. This should be fixed ASAP as it is a breaking change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing this at: #30996, I will make a follow up PR for the other issues raised.


/**
* Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`.
*
* Only implement this if `createWithFrame` needs an arguments parameter.
*/
@optional
- (nullable NSObject<FlutterMessageCodec>*)createArgsCodec;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ideally shouldn't have "create" in the name; that's not standard naming for a getter. There's no reason this needs to create something every time.

@end

#endif // FLUTTER_FLUTTERPLATFORMVIEWS_H_
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#import "FlutterBinaryMessenger.h"
#import "FlutterChannels.h"
#import "FlutterMacros.h"
#import "FlutterPlatformViews.h"
#import "FlutterPluginMacOS.h"
#import "FlutterTexture.h"

Expand Down Expand Up @@ -48,6 +49,18 @@ FLUTTER_DARWIN_EXPORT
- (void)addMethodCallDelegate:(nonnull id<FlutterPlugin>)delegate
channel:(nonnull FlutterMethodChannel*)channel;

/**
* Registers a `FlutterPlatformViewFactory` for creation of platform views.
*
* Plugins expose `NSView` for embedding in Flutter apps by registering a view factory.
*
* @param factory The view factory that will be registered.
* @param factoryId A unique identifier for the factory, the Dart code of the Flutter app can use
* this identifier to request creation of a `NSView` by the registered factory.
*/
- (void)registerViewFactory:(nonnull NSObject<FlutterPlatformViewFactory>*)factory
withId:(nonnull NSString*)factoryId;

@end

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#import "FlutterEngine.h"
#import "FlutterMacros.h"
#import "FlutterPlatformViews.h"
#import "FlutterPluginRegistrarMacOS.h"

/**
Expand Down
66 changes: 53 additions & 13 deletions shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
#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/FlutterOpenGLRenderer.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
#include "flutter/shell/platform/embedder/embedder.h"
#import "flutter/shell/platform/embedder/embedder.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change violates the style guide


/**
* Constructs and returns a FlutterLocale struct corresponding to |locale|, which must outlive
Expand Down Expand Up @@ -95,6 +96,11 @@ - (void)postMainThreadTask:(FlutterTask)task targetTimeInNanoseconds:(uint64_t)t
*/
- (void)loadAOTData:(NSString*)assetsDir;

/**
* Creates a platform view channel and sets up the method handler.
*/
- (void)setupPlatformViewChannel;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The verb is "set up", so this should be setUpPlatformViewChannel


@end

#pragma mark -
Expand Down Expand Up @@ -145,6 +151,11 @@ - (void)addMethodCallDelegate:(nonnull id<FlutterPlugin>)delegate
}];
}

- (void)registerViewFactory:(nonnull NSObject<FlutterPlatformViewFactory>*)factory
withId:(nonnull NSString*)factoryId {
[[_flutterEngine platformViewController] registerViewFactory:factory withId:factoryId];
}

@end

// Callbacks provided to the engine. See the called methods for documentation.
Expand Down Expand Up @@ -186,6 +197,14 @@ @implementation FlutterEngine {

// FlutterCompositor is copied and used in embedder.cc.
FlutterCompositor _compositor;

// Method channel for platform view functions. These functions include creating, disposing and
// mutating a platform view.
FlutterMethodChannel* _platformViewsChannel;

// Used to support creation and deletion of platform views and registering platform view
// factories. Lifecycle is tied to the engine.
FlutterPlatformViewController* _platformViewController;
}

- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project {
Expand Down Expand Up @@ -219,6 +238,9 @@ - (instancetype)initWithName:(NSString*)labelPrefix
name:NSCurrentLocaleDidChangeNotification
object:nil];

_platformViewController = [[FlutterPlatformViewController alloc] init];
[self setupPlatformViewChannel];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should never call methods on self in init.


return self;
}

Expand Down Expand Up @@ -383,8 +405,8 @@ - (FlutterCompositor*)createFlutterCompositor {

if ([FlutterRenderingBackend renderUsingMetal]) {
FlutterMetalRenderer* metalRenderer = reinterpret_cast<FlutterMetalRenderer*>(_renderer);
_macOSCompositor =
std::make_unique<flutter::FlutterMetalCompositor>(_viewController, metalRenderer.device);
_macOSCompositor = std::make_unique<flutter::FlutterMetalCompositor>(
_viewController, _platformViewController, metalRenderer.device);
_macOSCompositor->SetPresentCallback([weakSelf](bool has_flutter_content) {
if (has_flutter_content) {
FlutterMetalRenderer* metalRenderer =
Expand Down Expand Up @@ -541,6 +563,10 @@ - (void)dispatchSemanticsAction:(FlutterSemanticsAction)action
_embedderAPI.DispatchSemanticsAction(_engine, target, action, data.GetMapping(), data.GetSize());
}

- (FlutterPlatformViewController*)platformViewController {
return _platformViewController;
}

#pragma mark - Private methods

- (void)sendUserLocales {
Expand Down Expand Up @@ -630,6 +656,18 @@ - (void)shutDownEngine {
_engine = nullptr;
}

- (void)setupPlatformViewChannel {
_platformViewsChannel =
[FlutterMethodChannel methodChannelWithName:@"flutter/platform_views"
binaryMessenger:self.binaryMessenger
codec:[FlutterStandardMethodCodec sharedInstance]];

__weak FlutterEngine* weakSelf = self;
[_platformViewsChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
[[weakSelf platformViewController] handleMethodCall:call result:result];
}];
}

#pragma mark - FlutterBinaryMessenger

- (void)sendOnChannel:(nonnull NSString*)channel message:(nullable NSData*)message {
Expand Down Expand Up @@ -781,20 +819,22 @@ - (void)updateSemanticsCustomActions:(const FlutterSemanticsCustomAction*)action

#pragma mark - Task runner integration

- (void)postMainThreadTask:(FlutterTask)task targetTimeInNanoseconds:(uint64_t)targetTime {
const auto engine_time = _embedderAPI.GetCurrentTime();
- (void)runTaskOnEmbedder:(FlutterTask)task {
if (_engine) {
auto result = _embedderAPI.RunTask(_engine, &task);
if (result != kSuccess) {
NSLog(@"Could not post a task to the Flutter engine.");
}
}
}

__weak FlutterEngine* weak_self = self;
- (void)postMainThreadTask:(FlutterTask)task targetTimeInNanoseconds:(uint64_t)targetTime {
__weak FlutterEngine* weakSelf = self;
auto worker = ^{
FlutterEngine* strong_self = weak_self;
if (strong_self && strong_self->_engine) {
auto result = _embedderAPI.RunTask(strong_self->_engine, &task);
if (result != kSuccess) {
NSLog(@"Could not post a task to the Flutter engine.");
}
}
[weakSelf runTaskOnEmbedder:task];
};

const auto engine_time = _embedderAPI.GetCurrentTime();
if (targetTime <= engine_time) {
dispatch_async(dispatch_get_main_queue(), worker);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ @interface FlutterEngine (Test)
ASSERT_TRUE(latch_called);
}

TEST(FlutterEngine, Compositor) {
// TODO: Enable after https://github.com/flutter/flutter/issues/96668 is fixed.
TEST(FlutterEngine, DISABLED_Compositor) {
NSString* fixtures = @(flutter::testing::GetFixturesPath());
FlutterDartProject* project = [[FlutterDartProject alloc]
initWithAssetsPath:fixtures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "flutter/shell/platform/common/accessibility_bridge.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.h"

@interface FlutterEngine ()
Expand Down Expand Up @@ -70,6 +71,8 @@
*/
- (BOOL)unregisterTextureWithID:(int64_t)textureID;

- (nonnull FlutterPlatformViewController*)platformViewController;

// Accessibility API.

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@

#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(FlutterViewController* view_controller,
id<MTLDevice> mtl_device);
explicit FlutterMetalCompositor(
FlutterViewController* view_controller,
FlutterPlatformViewController* platform_views_controller,
id<MTLDevice> mtl_device);

virtual ~FlutterMetalCompositor() = default;

Expand Down Expand Up @@ -42,7 +45,12 @@ class FlutterMetalCompositor : public FlutterCompositor {
bool Present(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.
void PresentPlatformView(const FlutterLayer* layer, size_t layer_index);

const id<MTLDevice> mtl_device_;
const FlutterPlatformViewController* platform_views_controller_;

FML_DISALLOW_COPY_AND_ASSIGN(FlutterMetalCompositor);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@

namespace flutter {

FlutterMetalCompositor::FlutterMetalCompositor(FlutterViewController* view_controller,
id<MTLDevice> mtl_device)
: FlutterCompositor(view_controller), mtl_device_(mtl_device) {}
FlutterMetalCompositor::FlutterMetalCompositor(
FlutterViewController* view_controller,
FlutterPlatformViewController* platform_views_controller,
id<MTLDevice> mtl_device)
: FlutterCompositor(view_controller),
mtl_device_(mtl_device),
platform_views_controller_(platform_views_controller) {}

bool FlutterMetalCompositor::CreateBackingStore(const FlutterBackingStoreConfig* config,
FlutterBackingStore* backing_store_out) {
Expand Down Expand Up @@ -77,7 +81,6 @@
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);
Expand All @@ -94,13 +97,32 @@
break;
}
case kFlutterLayerContentTypePlatformView:
// Add functionality in follow up PR.
FML_LOG(WARNING) << "Presenting PlatformViews not yet supported";
PresentPlatformView(layer, i);
break;
};
}

return EndFrame(has_flutter_content);
}

void FlutterMetalCompositor::PresentPlatformView(const FlutterLayer* layer, size_t layer_position) {
// TODO (https://github.com/flutter/flutter/issues/96668)
iskakaushik marked this conversation as resolved.
Show resolved Hide resolved
// 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) {
[view_controller_.flutterView addSubview:platform_view];
}
platform_view.layer.zPosition = layer_position;
}

} // namespace flutter
Loading