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

Fix code style issues in MacOS embedder #22270

Merged
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
4 changes: 2 additions & 2 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1067,8 +1067,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/MacOSSwitchableGLContext.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/MacOSSwitchableGLContext.mm
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/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: 2 additions & 4 deletions shell/platform/darwin/macos/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,13 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterView.mm",
"framework/Source/FlutterViewController.mm",
"framework/Source/FlutterViewController_Internal.h",
"framework/Source/MacOSSwitchableGLContext.h",
"framework/Source/MacOSSwitchableGLContext.mm",
"framework/Source/MacOSGLContextSwitch.h",
"framework/Source/MacOSGLContextSwitch.mm",
]

sources += _flutter_framework_headers

deps = [
"//flutter/flow:flow",
"//flutter/fml:fml",
"//flutter/shell/platform/common/cpp:common_cpp_switches",
"//flutter/shell/platform/darwin/common:framework_shared",
"//flutter/shell/platform/embedder:embedder_as_internal_library",
Expand Down
13 changes: 11 additions & 2 deletions shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ - (bool)engineCallbackOnClearCurrent;
*/
- (bool)engineCallbackOnPresent;

/**
* Called by the engine when framebuffer object ID is requested.
*/
- (uint32_t)engineCallbackOnFBO:(const FlutterFrameInfo*)info;

/**
* Makes the resource context the current context.
*/
Expand Down Expand Up @@ -155,8 +160,7 @@ static bool OnPresent(FlutterEngine* engine) {
}

static uint32_t OnFBO(FlutterEngine* engine, const FlutterFrameInfo* info) {
CGSize size = CGSizeMake(info->size.width, info->size.height);
return [engine.viewController.flutterView getFrameBufferIdForSize:size];
return [engine engineCallbackOnFBO:info];
}

static bool OnMakeResourceCurrent(FlutterEngine* engine) {
Expand Down Expand Up @@ -473,6 +477,11 @@ - (bool)engineCallbackOnMakeCurrent {
return true;
}

- (uint32_t)engineCallbackOnFBO:(const FlutterFrameInfo*)info {
CGSize size = CGSizeMake(info->size.width, info->size.height);
return [_viewController.flutterView frameBufferIDForSize:size];
}

- (bool)engineCallbackOnClearCurrent {
[NSOpenGLContext clearCurrentContext];
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,59 +1,78 @@
// 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 <Cocoa/Cocoa.h>

@class FlutterResizeSynchronizer;

/**
* Implemented by FlutterView.
*/
@protocol FlutterResizeSynchronizerDelegate

// Invoked on raster thread; Delegate should flush the OpenGL context
- (void)resizeSynchronizerFlush:(FlutterResizeSynchronizer*)synchronizer;
/**
* Invoked on raster thread; Delegate should flush the OpenGL context.
*/
- (void)resizeSynchronizerFlush:(nonnull FlutterResizeSynchronizer*)synchronizer;

// Invoked on platform thread; Delegate should flip the surfaces
- (void)resizeSynchronizerCommit:(FlutterResizeSynchronizer*)synchronizer;
/**
* Invoked on platform thread; Delegate should flip the surfaces.
*/
- (void)resizeSynchronizerCommit:(nonnull FlutterResizeSynchronizer*)synchronizer;

@end

// Encapsulates the logic for blocking platform thread during window resize as
// well as synchronizing the raster and platform thread during commit (presenting frame)
//
// Flow during window resize
//
// 1. Platform thread calls [synchronizer beginResize:notify:]
// This will hold the platform thread until we're ready to display contents.
// 2. Raster thread calls [synchronizer shouldEnsureSurfaceForSize:] with target size
// This will return false for any size other than target size
// 3. Raster thread calls [synchronizer requestCommit]
// Any commit calls before shouldEnsureSurfaceForSize: is called with the right
// size are simply ignored; There's no point rasterizing and displaying frames
// with wrong size.
// Both delegate methods (flush/commit) will be invoked before beginResize returns
//
// Flow during regular operation (no resizing)
//
// 1. Raster thread calls [synchronizer requestCommit]
// This will invoke [delegate flush:] on raster thread and
// [delegate commit:] on platform thread. The requestCommit call will be blocked
// until this is done. This is necessary to ensure that rasterizer won't start
// rasterizing next frame before we flipped the surface, which must be performed
// on platform thread
/**
* Encapsulates the logic for blocking platform thread during window resize as
* well as synchronizing the raster and platform thread during commit (presenting frame).
*
* Flow during window resize
*
* 1. Platform thread calls [synchronizer beginResize:notify:]
* This will hold the platform thread until we're ready to display contents.
* 2. Raster thread calls [synchronizer shouldEnsureSurfaceForSize:] with target size
* This will return false for any size other than target size
* 3. Raster thread calls [synchronizer requestCommit]
* Any commit calls before shouldEnsureSurfaceForSize: is called with the right
* size are simply ignored; There's no point rasterizing and displaying frames
* with wrong size.
* Both delegate methods (flush/commit) will be invoked before beginResize returns
*
* Flow during regular operation (no resizing)
*
* 1. Raster thread calls [synchronizer requestCommit]
* This will invoke [delegate flush:] on raster thread and
* [delegate commit:] on platform thread. The requestCommit call will be blocked
* until this is done. This is necessary to ensure that rasterizer won't start
* rasterizing next frame before we flipped the surface, which must be performed
* on platform thread
*/
@interface FlutterResizeSynchronizer : NSObject

- (instancetype)initWithDelegate:(id<FlutterResizeSynchronizerDelegate>)delegate;
- (nullable instancetype)initWithDelegate:(nonnull id<FlutterResizeSynchronizerDelegate>)delegate;

// Blocks the platform thread until
// - shouldEnsureSurfaceForSize is called with proper size and
// - requestCommit is called
// All requestCommit calls before `shouldEnsureSurfaceForSize` is called with
// expected size are ignored;
// The notify block is invoked immediately after synchronizer mutex is acquired
- (void)beginResize:(CGSize)size notify:(dispatch_block_t)notify;
/**
* Blocks the platform thread until
* - shouldEnsureSurfaceForSize is called with proper size and
* - requestCommit is called
* All requestCommit calls before `shouldEnsureSurfaceForSize` is called with
* expected size are ignored;
* The notify block is invoked immediately after synchronizer mutex is acquired.
*/
- (void)beginResize:(CGSize)size notify:(nonnull dispatch_block_t)notify;

// Returns whether the view should ensure surfaces with given size;
// This will be false during resizing for any size other than size specified
// during beginResize
- (bool)shouldEnsureSurfaceForSize:(CGSize)size;
/**
* Returns whether the view should ensure surfaces with given size;
* This will be false during resizing for any size other than size specified
* during beginResize.
*/
- (BOOL)shouldEnsureSurfaceForSize:(CGSize)size;

// Called from rasterizer thread, will block until delegate resizeSynchronizerCommit:
// method is called (on platform thread)
/**
* Called from rasterizer thread, will block until delegate resizeSynchronizerCommit:
* method is called (on platform thread).
*/
- (void)requestCommit;

@end
Original file line number Diff line number Diff line change
@@ -1,103 +1,117 @@
// 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/FlutterResizeSynchronizer.h"

#import <mutex>
#include <mutex>

@interface FlutterResizeSynchronizer () {
uint32_t cookie; // counter to detect stale callbacks
// Counter to detect stale callbacks.
uint32_t _cookie;

std::mutex _mutex;

// Used to block [beginResize:].
std::condition_variable _condBlockBeginResize;
// Used to block [requestCommit].
std::condition_variable _condBlockRequestCommit;

// If NO, requestCommit calls are ignored until shouldEnsureSurfaceForSize is called with
// proper size.
BOOL _acceptingCommit;

// Waiting for resize to finish.
BOOL _waiting;

std::mutex mutex;
std::condition_variable condBlockBeginResize; // used to block [beginResize:]
std::condition_variable condBlockRequestCommit; // used to block [requestCommit]
// RequestCommit was called and [delegate commit:] must be performed on platform thread.
BOOL _pendingCommit;

bool acceptingCommit; // if false, requestCommit calls are ignored until
// shouldEnsureSurfaceForSize is called with proper size
bool waiting; // waiting for resize to finish
bool pendingCommit; // requestCommit was called and [delegate commit:] must be performed on
// platform thread
CGSize newSize; // target size for resizing
// Target size for resizing.
CGSize _newSize;

__weak id<FlutterResizeSynchronizerDelegate> delegate;
__weak id<FlutterResizeSynchronizerDelegate> _delegate;
}
@end

@implementation FlutterResizeSynchronizer

- (instancetype)initWithDelegate:(id<FlutterResizeSynchronizerDelegate>)delegate_ {
- (instancetype)initWithDelegate:(id<FlutterResizeSynchronizerDelegate>)delegate {
if (self = [super init]) {
acceptingCommit = true;
delegate = delegate_;
_acceptingCommit = YES;
_delegate = delegate;
}
return self;
}

- (void)beginResize:(CGSize)size notify:(dispatch_block_t)notify {
std::unique_lock<std::mutex> lock(mutex);
if (!delegate) {
std::unique_lock<std::mutex> lock(_mutex);
if (!_delegate) {
return;
}

++cookie;
++_cookie;

// from now on, ignore all incoming commits until the block below gets
// scheduled on raster thread
acceptingCommit = false;
_acceptingCommit = NO;

// let pending commits finish to unblock the raster thread
pendingCommit = false;
condBlockBeginResize.notify_all();
_pendingCommit = NO;
_condBlockBeginResize.notify_all();

// let the engine send resize notification
notify();

newSize = size;
_newSize = size;

waiting = true;
_waiting = YES;

condBlockRequestCommit.wait(lock, [&] { return pendingCommit; });
_condBlockRequestCommit.wait(lock, [&] { return _pendingCommit; });

[delegate resizeSynchronizerFlush:self];
[delegate resizeSynchronizerCommit:self];
pendingCommit = false;
condBlockBeginResize.notify_all();
[_delegate resizeSynchronizerFlush:self];
[_delegate resizeSynchronizerCommit:self];
_pendingCommit = NO;
_condBlockBeginResize.notify_all();

waiting = false;
_waiting = NO;
}

- (bool)shouldEnsureSurfaceForSize:(CGSize)size {
std::unique_lock<std::mutex> lock(mutex);
if (!acceptingCommit) {
if (CGSizeEqualToSize(newSize, size)) {
acceptingCommit = true;
- (BOOL)shouldEnsureSurfaceForSize:(CGSize)size {
std::unique_lock<std::mutex> lock(_mutex);
if (!_acceptingCommit) {
if (CGSizeEqualToSize(_newSize, size)) {
_acceptingCommit = YES;
}
}
return acceptingCommit;
return _acceptingCommit;
}

- (void)requestCommit {
std::unique_lock<std::mutex> lock(mutex);
if (!acceptingCommit) {
std::unique_lock<std::mutex> lock(_mutex);
if (!_acceptingCommit) {
return;
}

pendingCommit = true;
if (waiting) { // BeginResize is in progress, interrupt it and schedule commit call
condBlockRequestCommit.notify_all();
condBlockBeginResize.wait(lock, [&]() { return !pendingCommit; });
_pendingCommit = YES;
if (_waiting) { // BeginResize is in progress, interrupt it and schedule commit call
_condBlockRequestCommit.notify_all();
_condBlockBeginResize.wait(lock, [&]() { return !_pendingCommit; });
} else {
// No resize, schedule commit on platform thread and wait until either done
// or interrupted by incoming BeginResize
[delegate resizeSynchronizerFlush:self];
dispatch_async(dispatch_get_main_queue(), [self, cookie_ = cookie] {
std::unique_lock<std::mutex> lock(mutex);
if (cookie_ == cookie) {
if (delegate) {
[delegate resizeSynchronizerCommit:self];
[_delegate resizeSynchronizerFlush:self];
dispatch_async(dispatch_get_main_queue(), [self, cookie = _cookie] {
std::unique_lock<std::mutex> lock(_mutex);
if (cookie == _cookie) {
if (_delegate) {
[_delegate resizeSynchronizerCommit:self];
}
pendingCommit = false;
condBlockBeginResize.notify_all();
_pendingCommit = NO;
_condBlockBeginResize.notify_all();
}
});
condBlockBeginResize.wait(lock, [&]() { return !pendingCommit; });
_condBlockBeginResize.wait(lock, [&]() { return !_pendingCommit; });
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
// 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 <Cocoa/Cocoa.h>

// Manages the IOSurfaces for FlutterView
@interface FlutterSurfaceManager : NSObject

- (instancetype)initWithLayer:(CALayer*)layer openGLContext:(NSOpenGLContext*)opengLContext;
- (nullable instancetype)initWithLayer:(nonnull CALayer*)containingLayer
openGLContext:(nonnull NSOpenGLContext*)opengLContext;

- (void)ensureSurfaceSize:(CGSize)size;
- (void)swapBuffers;
Expand Down
Loading