mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
iOS: Keep the TV's layer until its output's removal has been handled
The add request holds the layer unretained, and the swapchain only takes a reference once it's handled. If the TV disconnected (or the setting changed) before that, the window and the layer were freed with the add still queued. The view controller now keeps a reference for the requests, released after Native_RemoveOutputAndWait, off the main thread. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
be4bdf3590
commit
22aa12d047
1 file changed
+14
-3
@@ -42,6 +42,8 @@ static bool g_launched = false;
|
||||
// Adds the view's layer as a Game output once it has a size, and keeps the output's size up to date.
|
||||
@interface ExternalDisplayViewController : UIViewController
|
||||
@property (nonatomic) int outputId;
|
||||
// A reference to the layer for the output's requests, which hold it unretained. Released once it's removed.
|
||||
@property (nonatomic) void *retainedLayer;
|
||||
@end
|
||||
|
||||
@implementation ExternalDisplayViewController {
|
||||
@@ -73,7 +75,8 @@ static bool g_launched = false;
|
||||
}
|
||||
Draw::SwapchainDesc desc{};
|
||||
desc.winsys = WINDOWSYSTEM_METAL_EXT;
|
||||
desc.data1 = (__bridge void *)self.view.layer;
|
||||
self.retainedLayer = (void *)CFBridgingRetain(self.view.layer);
|
||||
desc.data1 = self.retainedLayer;
|
||||
desc.width = width;
|
||||
desc.height = height;
|
||||
desc.tag = "ExternalDisplay";
|
||||
@@ -137,8 +140,16 @@ static bool g_launched = false;
|
||||
}
|
||||
ExternalDisplayViewController *viewController = (ExternalDisplayViewController *)self.window.rootViewController;
|
||||
if (viewController.outputId) {
|
||||
// The swapchain keeps the layer alive until the removal has gone through.
|
||||
Native_RemoveOutput(viewController.outputId);
|
||||
// The window and its layer go now, but the add may still be queued, so our reference to the layer has to
|
||||
// stay until the removal has been handled. Waited for off the main thread, which the render thread may
|
||||
// be waiting on. If that times out, the layer is kept, as the add may still come.
|
||||
const int outputId = viewController.outputId;
|
||||
void *layer = viewController.retainedLayer;
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{
|
||||
if (Native_RemoveOutputAndWait(outputId)) {
|
||||
CFRelease(layer);
|
||||
}
|
||||
});
|
||||
}
|
||||
self.window = nil;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user