mirror of
https://github.com/HaishinKit/HaishinKit.swift.git
synced 2026-05-07 20:12:28 +00:00
88 lines
2.8 KiB
Swift
88 lines
2.8 KiB
Swift
import Accelerate
|
|
import AVFoundation
|
|
import CoreImage
|
|
import CoreImage.CIFilterBuiltins
|
|
|
|
final class ScreenRendererByGPU: ScreenRenderer {
|
|
var bounds: CGRect = .init(origin: .zero, size: Screen.size)
|
|
let imageOptions: [CIImageOption: Any]?
|
|
var synchronizationClock: CMClock?
|
|
var presentationTimeStamp: CMTime = .zero
|
|
|
|
let context: CIContext
|
|
|
|
var backgroundColor = CGColor(red: 0x00, green: 0x00, blue: 0x00, alpha: 0x00) {
|
|
didSet {
|
|
guard backgroundColor != oldValue else {
|
|
return
|
|
}
|
|
backgroundCIColor = CIColor(cgColor: backgroundColor)
|
|
}
|
|
}
|
|
|
|
private var canvas: CIImage = .init()
|
|
private var images: [ScreenObject: CIImage] = [:]
|
|
private var pixelBuffer: CVPixelBuffer?
|
|
private let dynamicRangeMode: DynamicRangeMode
|
|
private var backgroundCIColor = CIColor()
|
|
private var roundedRectangleFactory = RoundedRectangleFactory()
|
|
|
|
init(dynamicRangeMode: DynamicRangeMode) {
|
|
self.dynamicRangeMode = dynamicRangeMode
|
|
context = dynamicRangeMode.makeCIContext()
|
|
if let colorSpace = dynamicRangeMode.colorSpace {
|
|
imageOptions = [.colorSpace: colorSpace]
|
|
} else {
|
|
imageOptions = nil
|
|
}
|
|
}
|
|
|
|
func setTarget(_ pixelBuffer: CVPixelBuffer?) {
|
|
guard let pixelBuffer else {
|
|
return
|
|
}
|
|
self.pixelBuffer = pixelBuffer
|
|
canvas = CIImage(color: backgroundCIColor).cropped(to: bounds)
|
|
}
|
|
|
|
func layout(_ screenObject: ScreenObject) {
|
|
guard let image: CIImage = screenObject.makeImage(self) else {
|
|
return
|
|
}
|
|
if 0 < screenObject.cornerRadius {
|
|
if let mask = roundedRectangleFactory.cornerRadius(screenObject.bounds.size, cornerRadius: screenObject.cornerRadius) {
|
|
images[screenObject] = image.applyingFilter("CIBlendWithAlphaMask", parameters: [
|
|
"inputMaskImage": mask
|
|
])
|
|
} else {
|
|
images[screenObject] = image
|
|
}
|
|
} else {
|
|
images[screenObject] = image
|
|
}
|
|
}
|
|
|
|
func draw(_ screenObject: ScreenObject) {
|
|
guard let image = images[screenObject] else {
|
|
return
|
|
}
|
|
let origin = screenObject.bounds.origin
|
|
if origin.x == 0 && origin.y == 0 {
|
|
canvas = image
|
|
.composited(over: canvas)
|
|
} else {
|
|
canvas = image
|
|
.transformed(by: .init(translationX: origin.x, y: bounds.height - origin.y - screenObject.bounds.height))
|
|
.composited(over: canvas)
|
|
}
|
|
}
|
|
|
|
func render() {
|
|
guard let pixelBuffer else {
|
|
return
|
|
}
|
|
context.render(canvas, to: pixelBuffer, bounds: canvas.extent, colorSpace: dynamicRangeMode.colorSpace)
|
|
dynamicRangeMode.attach(pixelBuffer)
|
|
}
|
|
}
|