Skip to content

Instantly share code, notes, and snippets.

@sebjvidal
Created January 24, 2026 13:24
Show Gist options
  • Select an option

  • Save sebjvidal/a33efee620ddc2388b651e728133992c to your computer and use it in GitHub Desktop.

Select an option

Save sebjvidal/a33efee620ddc2388b651e728133992c to your computer and use it in GitHub Desktop.
NSView CARenderer Demo
extension NSView {
func renderWithCARenderer() -> NSImage? {
let width = Int(frame.width * 2)
let height = Int(frame.height * 2)
frame.origin = CGPoint(x: 0, y: 0)
let descriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .rgba8Unorm, width: width, height: height, mipmapped: true)
descriptor.usage = [.shaderRead, .shaderWrite, .renderTarget]
let device = MTLCreateSystemDefaultDevice()!
let options = [CIContextOption.workingColorSpace: NSNull()]
let context = CIContext(mtlDevice: device, options: options)
let texture = device.makeTexture(descriptor: descriptor)!
let renderer = CARenderer(mtlTexture: texture)
renderer.layer = layer
renderer.bounds = CGRect(x: 0, y: 0, width: width, height: height)
renderer.layer?.transform = CGAffineTransform(scaleX: 2, y: 2)
CATransaction.flush()
renderer.beginFrame(atTime: .currentMediaTime)
renderer.addUpdate(renderer.bounds)
renderer.render()
renderer.endFrame()
let ciImage = CIImage(mtlTexture: texture)!
let cgImage = context.createCGImage(ciImage, from: ciImage.extent)!
let nsImage = NSImage(cgImage: cgImage, size: cgImage.size)
return nsImage
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment