mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix code style issues in MacOS embedder (flutter/engine#22270)
This commit is contained in:
parent
68eedd5ba3
commit
309f003ea8
@ -1068,8 +1068,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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -52,6 +52,11 @@ static FlutterLocale FlutterLocaleFromNSLocale(NSLocale* locale) {
|
||||
*/
|
||||
- (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.
|
||||
*/
|
||||
@ -146,8 +151,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) {
|
||||
@ -469,6 +473,11 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
|
||||
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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
std::condition_variable condBlockBeginResize; // used to block [beginResize:]
|
||||
std::condition_variable condBlockRequestCommit; // used to block [requestCommit]
|
||||
std::mutex _mutex;
|
||||
|
||||
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
|
||||
// Used to block [beginResize:].
|
||||
std::condition_variable _condBlockBeginResize;
|
||||
// Used to block [requestCommit].
|
||||
std::condition_variable _condBlockRequestCommit;
|
||||
|
||||
__weak id<FlutterResizeSynchronizerDelegate> delegate;
|
||||
// If NO, requestCommit calls are ignored until shouldEnsureSurfaceForSize is called with
|
||||
// proper size.
|
||||
BOOL _acceptingCommit;
|
||||
|
||||
// Waiting for resize to finish.
|
||||
BOOL _waiting;
|
||||
|
||||
// RequestCommit was called and [delegate commit:] must be performed on platform thread.
|
||||
BOOL _pendingCommit;
|
||||
|
||||
// Target size for resizing.
|
||||
CGSize _newSize;
|
||||
|
||||
__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; });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1,41 +1,45 @@
|
||||
// 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/FlutterSurfaceManager.h"
|
||||
#import "flutter/fml/logging.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/MacOSSwitchableGLContext.h"
|
||||
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/MacOSGLContextSwitch.h"
|
||||
|
||||
enum {
|
||||
kFront = 0,
|
||||
kBack = 1,
|
||||
kBufferCount,
|
||||
kFlutterSurfaceManagerFrontBuffer = 0,
|
||||
kFlutterSurfaceManagerBackBuffer = 1,
|
||||
kFlutterSurfaceManagerBufferCount,
|
||||
};
|
||||
|
||||
@interface FlutterSurfaceManager () {
|
||||
CGSize surfaceSize;
|
||||
CALayer* layer; // provided (parent layer)
|
||||
CALayer* contentLayer;
|
||||
CGSize _surfaceSize;
|
||||
CALayer* _containingLayer; // provided (parent layer)
|
||||
CALayer* _contentLayer;
|
||||
|
||||
NSOpenGLContext* openGLContext;
|
||||
uint32_t _frameBufferId[kBufferCount];
|
||||
uint32_t _backingTexture[kBufferCount];
|
||||
IOSurfaceRef _ioSurface[kBufferCount];
|
||||
NSOpenGLContext* _openGLContext;
|
||||
uint32_t _frameBufferId[kFlutterSurfaceManagerBufferCount];
|
||||
uint32_t _backingTexture[kFlutterSurfaceManagerBufferCount];
|
||||
IOSurfaceRef _ioSurface[kFlutterSurfaceManagerBufferCount];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation FlutterSurfaceManager
|
||||
|
||||
- (instancetype)initWithLayer:(CALayer*)layer_ openGLContext:(NSOpenGLContext*)opengLContext_ {
|
||||
- (instancetype)initWithLayer:(CALayer*)containingLayer
|
||||
openGLContext:(NSOpenGLContext*)openGLContext {
|
||||
if (self = [super init]) {
|
||||
layer = layer_;
|
||||
openGLContext = opengLContext_;
|
||||
_containingLayer = containingLayer;
|
||||
_openGLContext = openGLContext;
|
||||
|
||||
// Layer for content. This is separate from provided layer, because it needs to be flipped
|
||||
// vertically if we render to OpenGL texture
|
||||
contentLayer = [[CALayer alloc] init];
|
||||
[layer_ addSublayer:contentLayer];
|
||||
_contentLayer = [[CALayer alloc] init];
|
||||
[_containingLayer addSublayer:_contentLayer];
|
||||
|
||||
flutter::GLContextSwitch context_switch(
|
||||
std::make_unique<MacOSSwitchableGLContext>(opengLContext_));
|
||||
MacOSGLContextSwitch context_switch(openGLContext);
|
||||
|
||||
glGenFramebuffers(2, _frameBufferId);
|
||||
glGenTextures(2, _backingTexture);
|
||||
@ -57,15 +61,14 @@ enum {
|
||||
}
|
||||
|
||||
- (void)ensureSurfaceSize:(CGSize)size {
|
||||
if (CGSizeEqualToSize(size, surfaceSize)) {
|
||||
if (CGSizeEqualToSize(size, _surfaceSize)) {
|
||||
return;
|
||||
}
|
||||
surfaceSize = size;
|
||||
_surfaceSize = size;
|
||||
|
||||
flutter::GLContextSwitch context_switch(
|
||||
std::make_unique<MacOSSwitchableGLContext>(openGLContext));
|
||||
MacOSGLContextSwitch context_switch(_openGLContext);
|
||||
|
||||
for (int i = 0; i < kBufferCount; ++i) {
|
||||
for (int i = 0; i < kFlutterSurfaceManagerBufferCount; ++i) {
|
||||
if (_ioSurface[i]) {
|
||||
CFRelease(_ioSurface[i]);
|
||||
}
|
||||
@ -96,29 +99,33 @@ enum {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB,
|
||||
_backingTexture[i], 0);
|
||||
|
||||
FML_DCHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||
NSAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE,
|
||||
@"Framebuffer status check failed");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)swapBuffers {
|
||||
contentLayer.frame = layer.bounds;
|
||||
_contentLayer.frame = _containingLayer.bounds;
|
||||
|
||||
// The surface is an OpenGL texture, which means it has origin in bottom left corner
|
||||
// and needs to be flipped vertically
|
||||
contentLayer.transform = CATransform3DMakeScale(1, -1, 1);
|
||||
[contentLayer setContents:(__bridge id)_ioSurface[kBack]];
|
||||
_contentLayer.transform = CATransform3DMakeScale(1, -1, 1);
|
||||
[_contentLayer setContents:(__bridge id)_ioSurface[kFlutterSurfaceManagerBackBuffer]];
|
||||
|
||||
std::swap(_ioSurface[kBack], _ioSurface[kFront]);
|
||||
std::swap(_frameBufferId[kBack], _frameBufferId[kFront]);
|
||||
std::swap(_backingTexture[kBack], _backingTexture[kFront]);
|
||||
std::swap(_ioSurface[kFlutterSurfaceManagerBackBuffer],
|
||||
_ioSurface[kFlutterSurfaceManagerFrontBuffer]);
|
||||
std::swap(_frameBufferId[kFlutterSurfaceManagerBackBuffer],
|
||||
_frameBufferId[kFlutterSurfaceManagerFrontBuffer]);
|
||||
std::swap(_backingTexture[kFlutterSurfaceManagerBackBuffer],
|
||||
_backingTexture[kFlutterSurfaceManagerFrontBuffer]);
|
||||
}
|
||||
|
||||
- (uint32_t)glFrameBufferId {
|
||||
return _frameBufferId[kBack];
|
||||
return _frameBufferId[kFlutterSurfaceManagerBackBuffer];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
for (int i = 0; i < kBufferCount; ++i) {
|
||||
for (int i = 0; i < kFlutterSurfaceManagerBufferCount; ++i) {
|
||||
if (_ioSurface[i]) {
|
||||
CFRelease(_ioSurface[i]);
|
||||
}
|
||||
|
||||
@ -20,7 +20,16 @@
|
||||
*/
|
||||
@interface FlutterView : NSView
|
||||
|
||||
/**
|
||||
* The OpenGL context of backing surface.
|
||||
*/
|
||||
@property(readwrite, nonatomic, nonnull) NSOpenGLContext* openGLContext;
|
||||
|
||||
/**
|
||||
* Controls whether view resizing synchronously updates contents. This can only be enabled
|
||||
* after the engine is running and producing frames, because during synchronous view resizing the
|
||||
* platform thread is blocked until engine produces frame with requested size.
|
||||
*/
|
||||
@property(readwrite, nonatomic) BOOL synchronousResizing;
|
||||
|
||||
- (nullable instancetype)initWithFrame:(NSRect)frame
|
||||
@ -38,7 +47,15 @@
|
||||
- (nullable instancetype)initWithCoder:(nonnull NSCoder*)coder NS_UNAVAILABLE;
|
||||
- (nonnull instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Flushes the OpenGL context and flips the surfaces. Expected to be called on raster thread.
|
||||
*/
|
||||
- (void)present;
|
||||
- (int)getFrameBufferIdForSize:(CGSize)size;
|
||||
|
||||
/**
|
||||
* Ensures that framebuffer with requested size exists and returns the ID. Expected to be called on
|
||||
* raster thread.
|
||||
*/
|
||||
- (int)frameBufferIDForSize:(CGSize)size;
|
||||
|
||||
@end
|
||||
|
||||
@ -3,17 +3,18 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
|
||||
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/MacOSSwitchableGLContext.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/MacOSGLContextSwitch.h"
|
||||
|
||||
#import <OpenGL/gl.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
@interface FlutterView () <FlutterResizeSynchronizerDelegate> {
|
||||
__weak id<FlutterViewReshapeListener> _reshapeListener;
|
||||
FlutterResizeSynchronizer* resizeSynchronizer;
|
||||
FlutterSurfaceManager* surfaceManager;
|
||||
FlutterResizeSynchronizer* _resizeSynchronizer;
|
||||
FlutterSurfaceManager* _surfaceManager;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -35,9 +36,9 @@
|
||||
|
||||
[self setWantsLayer:YES];
|
||||
|
||||
resizeSynchronizer = [[FlutterResizeSynchronizer alloc] initWithDelegate:self];
|
||||
surfaceManager = [[FlutterSurfaceManager alloc] initWithLayer:self.layer
|
||||
openGLContext:self.openGLContext];
|
||||
_resizeSynchronizer = [[FlutterResizeSynchronizer alloc] initWithDelegate:self];
|
||||
_surfaceManager = [[FlutterSurfaceManager alloc] initWithLayer:self.layer
|
||||
openGLContext:self.openGLContext];
|
||||
|
||||
_reshapeListener = reshapeListener;
|
||||
}
|
||||
@ -45,8 +46,7 @@
|
||||
}
|
||||
|
||||
- (void)resizeSynchronizerFlush:(FlutterResizeSynchronizer*)synchronizer {
|
||||
flutter::GLContextSwitch context_switch(
|
||||
std::make_unique<MacOSSwitchableGLContext>(self.openGLContext));
|
||||
MacOSGLContextSwitch context_switch(self.openGLContext);
|
||||
glFlush();
|
||||
}
|
||||
|
||||
@ -54,29 +54,29 @@
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
|
||||
[surfaceManager swapBuffers];
|
||||
[_surfaceManager swapBuffers];
|
||||
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
- (int)getFrameBufferIdForSize:(CGSize)size {
|
||||
if ([resizeSynchronizer shouldEnsureSurfaceForSize:size]) {
|
||||
[surfaceManager ensureSurfaceSize:size];
|
||||
- (int)frameBufferIDForSize:(CGSize)size {
|
||||
if ([_resizeSynchronizer shouldEnsureSurfaceForSize:size]) {
|
||||
[_surfaceManager ensureSurfaceSize:size];
|
||||
}
|
||||
return [surfaceManager glFrameBufferId];
|
||||
return [_surfaceManager glFrameBufferId];
|
||||
}
|
||||
|
||||
- (void)present {
|
||||
[resizeSynchronizer requestCommit];
|
||||
[_resizeSynchronizer requestCommit];
|
||||
}
|
||||
|
||||
- (void)reshaped {
|
||||
if (self.synchronousResizing) {
|
||||
CGSize scaledSize = [self convertSizeToBacking:self.bounds.size];
|
||||
[resizeSynchronizer beginResize:scaledSize
|
||||
notify:^{
|
||||
[_reshapeListener viewDidReshape:self];
|
||||
}];
|
||||
[_resizeSynchronizer beginResize:scaledSize
|
||||
notify:^{
|
||||
[_reshapeListener viewDidReshape:self];
|
||||
}];
|
||||
} else {
|
||||
[_reshapeListener viewDidReshape:self];
|
||||
}
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
// 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>
|
||||
|
||||
/**
|
||||
* RAII wrapper that sets provided NSOpenGLContext as current and restores
|
||||
* original context on scope exit.
|
||||
*/
|
||||
class MacOSGLContextSwitch {
|
||||
public:
|
||||
explicit MacOSGLContextSwitch(NSOpenGLContext* context);
|
||||
~MacOSGLContextSwitch();
|
||||
|
||||
MacOSGLContextSwitch(const MacOSGLContextSwitch&) = delete;
|
||||
MacOSGLContextSwitch(MacOSGLContextSwitch&&) = delete;
|
||||
|
||||
private:
|
||||
NSOpenGLContext* previous_;
|
||||
};
|
||||
@ -0,0 +1,18 @@
|
||||
// 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/MacOSGLContextSwitch.h"
|
||||
|
||||
MacOSGLContextSwitch::MacOSGLContextSwitch(NSOpenGLContext* context) {
|
||||
previous_ = [NSOpenGLContext currentContext];
|
||||
[context makeCurrentContext];
|
||||
}
|
||||
|
||||
MacOSGLContextSwitch::~MacOSGLContextSwitch() {
|
||||
if (previous_) {
|
||||
[previous_ makeCurrentContext];
|
||||
} else {
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
#include "flutter/flow/gl_context_switch.h"
|
||||
#include "flutter/fml/memory/thread_checker.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
class MacOSSwitchableGLContext final : public flutter::SwitchableGLContext {
|
||||
public:
|
||||
explicit MacOSSwitchableGLContext(NSOpenGLContext* context);
|
||||
|
||||
bool SetCurrent() override;
|
||||
|
||||
bool RemoveCurrent() override;
|
||||
|
||||
private:
|
||||
NSOpenGLContext* context_;
|
||||
NSOpenGLContext* previous_context_;
|
||||
|
||||
FML_DECLARE_THREAD_CHECKER(checker);
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(MacOSSwitchableGLContext);
|
||||
};
|
||||
@ -1,19 +0,0 @@
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/MacOSSwitchableGLContext.h"
|
||||
|
||||
MacOSSwitchableGLContext::MacOSSwitchableGLContext(NSOpenGLContext* context) : context_(context) {}
|
||||
|
||||
bool MacOSSwitchableGLContext::SetCurrent() {
|
||||
FML_DCHECK_CREATION_THREAD_IS_CURRENT(checker);
|
||||
previous_context_ = [NSOpenGLContext currentContext];
|
||||
[context_ makeCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacOSSwitchableGLContext::RemoveCurrent() {
|
||||
if (previous_context_) {
|
||||
[previous_context_ makeCurrentContext];
|
||||
} else {
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user