Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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
30 changes: 29 additions & 1 deletion shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ @interface FlutterMetalLayer () {
BOOL _displayLinkForcedMaxRate;
}

- (void)onDisplayLink:(CADisplayLink*)link;
- (void)presentTexture:(FlutterTexture*)texture;
- (void)returnTexture:(FlutterTexture*)texture;

Expand Down Expand Up @@ -163,6 +164,26 @@ - (void)flutterPrepareForPresent:(nonnull id<MTLCommandBuffer>)commandBuffer {

@end

@interface FlutterMetalLayerDisplayLinkProxy : NSObject {
__weak FlutterMetalLayer* _layer;
}

@end

@implementation FlutterMetalLayerDisplayLinkProxy
- (instancetype)initWithLayer:(FlutterMetalLayer*)layer {
if (self = [super init]) {
_layer = layer;
}
return self;
}

- (void)onDisplayLink:(CADisplayLink*)link {
[_layer onDisplayLink:link];
}

@end

@implementation FlutterMetalLayer

@synthesize preferredDevice = _preferredDevice;
Expand All @@ -179,7 +200,9 @@ - (instancetype)init {
self.pixelFormat = MTLPixelFormatBGRA8Unorm;
_availableTextures = [[NSMutableSet alloc] init];

_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onDisplayLink:)];
FlutterMetalLayerDisplayLinkProxy* proxy =
[[FlutterMetalLayerDisplayLinkProxy alloc] initWithLayer:self];
_displayLink = [CADisplayLink displayLinkWithTarget:proxy selector:@selector(onDisplayLink:)];
[self setMaxRefreshRate:DisplayLinkManager.displayRefreshRate forceMax:NO];
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[[NSNotificationCenter defaultCenter] addObserver:self
Expand All @@ -190,6 +213,11 @@ - (instancetype)init {
return self;
}

- (void)dealloc {
[_displayLink invalidate];
[[NSNotificationCenter defaultCenter] removeObserver:self];
Copy link
Member

Choose a reason for hiding this comment

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

This isn't necessary in dealloc.

}

- (void)setMaxRefreshRate:(double)refreshRate forceMax:(BOOL)forceMax {
// This is copied from vsync_waiter_ios.mm. The vsync waiter has display link scheduled on UI
// thread which does not trigger actual core animation frame. As a workaround FlutterMetalLayer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,24 @@ - (void)testTimeout {
[self removeMetalLayer:layer];
}

- (void)testDealloc {
__weak FlutterMetalLayer* weakLayer;
@autoreleasepool {
FlutterMetalLayer* layer = [self addMetalLayer];
weakLayer = layer;
TestCompositor* compositor = [[TestCompositor alloc] initWithLayer:layer];

id<CAMetalDrawable> drawable = [layer nextDrawable];
BAIL_IF_NO_DRAWABLE(drawable);
[drawable present];
[compositor commitTransaction];

[self removeMetalLayer:layer];
// Deallocating the layer after removing is not synchronous.
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
}

XCTAssertNil(weakLayer);
}

@end