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

WIP: Smooth window resizing on macOS #21252

Closed
wants to merge 2 commits into from
Closed
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
3 changes: 3 additions & 0 deletions shell/platform/darwin/macos/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ source_set("flutter_framework_source") {
sources += _flutter_framework_headers

deps = [
"//flutter/fml:fml",
"//flutter/shell/platform/darwin/common:framework_shared",
"//flutter/shell/platform/embedder:embedder_as_internal_library",
]
Expand All @@ -80,6 +81,8 @@ source_set("flutter_framework_source") {
libs = [
"Cocoa.framework",
"CoreVideo.framework",
"IOSurface.framework",
"QuartzCore.framework",
]
}

Expand Down
34 changes: 25 additions & 9 deletions shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ static bool OnPresent(FlutterEngine* engine) {
return [engine engineCallbackOnPresent];
}

static uint32_t OnFBO(FlutterEngine* engine) {
// There is currently no case where a different FBO is used, so no need to forward.
return 0;
static uint32_t OnFBO(FlutterEngine* engine, const FlutterFrameInfo* info) {
return [engine.viewController.flutterView getFrameBufferIdForWidth:info->size.width
height:info->size.height];
}

static bool OnMakeResourceCurrent(FlutterEngine* engine) {
Expand Down Expand Up @@ -229,7 +229,8 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
.open_gl.make_current = (BoolCallback)OnMakeCurrent,
.open_gl.clear_current = (BoolCallback)OnClearCurrent,
.open_gl.present = (BoolCallback)OnPresent,
.open_gl.fbo_callback = (UIntCallback)OnFBO,
.open_gl.fbo_with_frame_info_callback = (UIntFrameInfoCallback)OnFBO,
.open_gl.fbo_reset_after_present = true,
.open_gl.make_resource_current = (BoolCallback)OnMakeResourceCurrent,
.open_gl.gl_external_texture_frame_callback = (TextureFrameCallback)OnAcquireExternalTexture,
};
Expand Down Expand Up @@ -262,7 +263,6 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
const FlutterCustomTaskRunners custom_task_runners = {
.struct_size = sizeof(FlutterCustomTaskRunners),
.platform_task_runner = &cocoa_task_runner_description,
.render_task_runner = &cocoa_task_runner_description,
};
flutterArguments.custom_task_runners = &custom_task_runners;

Expand All @@ -280,7 +280,8 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
}

[self sendUserLocales];
[self updateWindowMetrics];

[self.viewController.flutterView start];
return YES;
}

Expand All @@ -291,7 +292,9 @@ - (void)setViewController:(FlutterViewController*)controller {
[self shutDownEngine];
_resourceContext = nil;
}
[self updateWindowMetrics];
if (_engine) {
[self.viewController.flutterView start];
}
}

- (id<FlutterBinaryMessenger>)binaryMessenger {
Expand All @@ -309,14 +312,15 @@ - (BOOL)running {
- (NSOpenGLContext*)resourceContext {
if (!_resourceContext) {
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, NSOpenGLPFADoubleBuffer, 0,
NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, 0,
};
NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
_resourceContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
}
return _resourceContext;
}

// Must be driven by FlutterView (i.e. [FlutterView start])
- (void)updateWindowMetrics {
if (!_engine) {
return;
Expand All @@ -334,6 +338,18 @@ - (void)updateWindowMetrics {
FlutterEngineSendWindowMetricsEvent(_engine, &event);
}

- (void)scheduleOnRasterTread:(dispatch_block_t)block {
void* copy = Block_copy((__bridge void*)block);
FlutterEnginePostRenderThreadTask(
_engine,
[](void* callback) {
dispatch_block_t block = (__bridge dispatch_block_t)callback;
block();
Block_release(block);
},
copy);
}

- (void)sendPointerEvent:(const FlutterPointerEvent&)event {
FlutterEngineSendPointerEvent(_engine, &event, 1);
}
Expand Down Expand Up @@ -380,7 +396,7 @@ - (bool)engineCallbackOnPresent {
if (!_mainOpenGLContext) {
return false;
}
[_mainOpenGLContext flushBuffer];
[self.viewController.flutterView present];
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
*/
- (void)updateWindowMetrics;

/**
* Schedules the block on raster thread.
*/
- (void)scheduleOnRasterTread:(nonnull dispatch_block_t)block;

/**
* Dispatches the given pointer event data to engine.
*/
Expand Down
21 changes: 13 additions & 8 deletions shell/platform/darwin/macos/framework/Source/FlutterView.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,40 @@

#import <Cocoa/Cocoa.h>

/**
* Listener for view resizing.
*/
@protocol FlutterViewReshapeListener <NSObject>
@protocol FlutterViewDelegate <NSObject>
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we call this FlutterSurfaceDelegate and move present and getFrameBufferIdForWidth to this?

/**
* Called when the view's backing store changes size.
*/
- (void)viewDidReshape:(nonnull NSView*)view;

- (void)scheduleOnRasterTread:(nonnull dispatch_block_t)block;
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: "RasterThread". Also, given that the embedder method is called FlutterEnginePostRenderThreadTask, maybe we can call this: scheduleOnRenderThread?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure about this. Apart from FlutterEnginePostRenderThreadTask, the thread is referred to as raster thread in most places in the code.


@end

/**
* View capable of acting as a rendering target and input source for the Flutter
* engine.
*/
@interface FlutterView : NSOpenGLView
@interface FlutterView : NSView

@property(readwrite, nonatomic, nonnull) NSOpenGLContext* openGLContext;

- (nullable instancetype)initWithFrame:(NSRect)frame
shareContext:(nonnull NSOpenGLContext*)shareContext
reshapeListener:(nonnull id<FlutterViewReshapeListener>)reshapeListener
delegate:(nonnull id<FlutterViewDelegate>)delegate
NS_DESIGNATED_INITIALIZER;

- (nullable instancetype)initWithShareContext:(nonnull NSOpenGLContext*)shareContext
reshapeListener:
(nonnull id<FlutterViewReshapeListener>)reshapeListener;
delegate:(nonnull id<FlutterViewDelegate>)delegate;

- (nullable instancetype)initWithFrame:(NSRect)frameRect
pixelFormat:(nullable NSOpenGLPixelFormat*)format NS_UNAVAILABLE;
- (nonnull instancetype)initWithFrame:(NSRect)frameRect NS_UNAVAILABLE;
- (nullable instancetype)initWithCoder:(nonnull NSCoder*)coder NS_UNAVAILABLE;
- (nonnull instancetype)init NS_UNAVAILABLE;

- (void)start;
- (void)present;
- (int)getFrameBufferIdForWidth:(int)width height:(int)height;

@end
Loading