diff --git a/Yattee/Services/Player/MPV/MPVOGLView.swift b/Yattee/Services/Player/MPV/MPVOGLView.swift index 8bb32914..fb146f2a 100644 --- a/Yattee/Services/Player/MPV/MPVOGLView.swift +++ b/Yattee/Services/Player/MPV/MPVOGLView.swift @@ -12,6 +12,7 @@ import AppKit import CoreMedia import CoreVideo import Libmpv +import QuartzCore // MARK: - MPVOGLView @@ -168,8 +169,13 @@ final class MPVOGLView: NSView { stopDisplayLink() startDisplayLink() - // Update contents scale for new window + // Update contents scale for new window. Disable implicit actions so + // Core Animation never builds a presentation copy of the GL layer + // for this change (crashes on macOS 27 beta). + CATransaction.begin() + CATransaction.setDisableActions(true) videoLayer?.contentsScale = window.backingScaleFactor + CATransaction.commit() // Reattaching (e.g. macOS player sheet dismissed via ESC then re-expanded) // detaches this shared view without stopping playback. macOS drawing is @@ -182,9 +188,14 @@ final class MPVOGLView: NSView { override func viewDidChangeBackingProperties() { super.viewDidChangeBackingProperties() - // Update contents scale when backing properties change + // Update contents scale when backing properties change. Disable implicit + // actions so Core Animation never builds a presentation copy of the GL + // layer for this change (crashes on macOS 27 beta). if let scale = window?.backingScaleFactor { + CATransaction.begin() + CATransaction.setDisableActions(true) videoLayer?.contentsScale = scale + CATransaction.commit() } // Update display refresh rate diff --git a/Yattee/Services/Player/MPV/MPVOpenGLLayer.swift b/Yattee/Services/Player/MPV/MPVOpenGLLayer.swift index d11da7a3..54928e9a 100644 --- a/Yattee/Services/Player/MPV/MPVOpenGLLayer.swift +++ b/Yattee/Services/Player/MPV/MPVOpenGLLayer.swift @@ -236,15 +236,12 @@ final class MPVOpenGLLayer: CAOpenGLLayer { self.bufferDepth = previousLayer.bufferDepth self.isSetup = previousLayer.isSetup + // super.init(layer:) already copies presentation values; re-invoking + // setters like `colorspace` on the shadow copy dereferences render + // state the copy doesn't own and crashes (macOS 27 beta routes + // contentsScale changes through this path on screen changes). super.init(layer: layer) - autoresizingMask = previousLayer.autoresizingMask - backgroundColor = previousLayer.backgroundColor - isOpaque = previousLayer.isOpaque - colorspace = previousLayer.colorspace - contentsFormat = previousLayer.contentsFormat - isAsynchronous = previousLayer.isAsynchronous - Task { @MainActor in LoggingService.shared.debug("MPVOpenGLLayer: created shadow copy", category: .mpv) }