mirror of
https://github.com/yattee/yattee.git
synced 2026-11-01 01:17:20 +00:00
Reflect the video below the hinge in the tabletop layout
The iPhone Duo tabletop layout mirrors every presented frame into the lower half, blurred and fading out, like a screen standing on a glossy table. The render view blits a quarter-resolution copy of the display framebuffer into a ring of IOSurface-backed buffers (no Y flip, so the surface is already mirrored) and hands it to a CALayer hosted by MPVReflectionView; the simulator's software renderer feeds the same layer a flipped CGImage. Off during PiP, for audio-only streams, and via the new Playback → Foldable → "Reflection Below Video" setting.
This commit is contained in:
52
Yattee/Services/Player/MPV/MPVReflectionLayer.swift
Normal file
52
Yattee/Services/Player/MPV/MPVReflectionLayer.swift
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// MPVReflectionLayer.swift
|
||||
// Yattee
|
||||
//
|
||||
// Layer that shows a vertically mirrored copy of the rendered video frame,
|
||||
// used for the "reflection" below the video in the iPhone Duo tabletop
|
||||
// layout. The render view feeds it every presented frame.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import QuartzCore
|
||||
import IOSurface
|
||||
|
||||
#if canImport(UIKit)
|
||||
import UIKit
|
||||
|
||||
final class MPVReflectionLayer: CALayer {
|
||||
override init() {
|
||||
super.init()
|
||||
contentsGravity = .resizeAspect
|
||||
isOpaque = false
|
||||
// Frame updates must not trigger implicit fades.
|
||||
actions = ["contents": NSNull(), "bounds": NSNull(), "position": NSNull(), "transform": NSNull()]
|
||||
}
|
||||
|
||||
override init(layer: Any) {
|
||||
super.init(layer: layer)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
|
||||
/// Show a surface whose rows are already mirrored (GL blit without Y flip).
|
||||
func display(_ surface: IOSurface) {
|
||||
contents = surface
|
||||
}
|
||||
|
||||
/// Show an upright image; the layer mirrors it itself.
|
||||
func displayMirrored(_ image: CGImage) {
|
||||
if CATransform3DIsIdentity(transform) {
|
||||
transform = CATransform3DMakeScale(1, -1, 1)
|
||||
}
|
||||
contents = image
|
||||
}
|
||||
|
||||
func clear() {
|
||||
contents = nil
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user