From e21b1c797955a231f2bcf71818e0259fbb6aeba1 Mon Sep 17 00:00:00 2001
From: Runt <qingingrunt2010@qq.com>
Date: Fri, 27 Jun 2025 15:57:25 +0000
Subject: [PATCH] 相机权限

---
 LiveProject/tool/MetalRenderer.swift |   55 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/LiveProject/tool/MetalRenderer.swift b/LiveProject/tool/MetalRenderer.swift
index 791dfc8..a2aa4ba 100644
--- a/LiveProject/tool/MetalRenderer.swift
+++ b/LiveProject/tool/MetalRenderer.swift
@@ -4,35 +4,68 @@
 //  渲染工具
 //  Created by 倪路朋 on 6/26/25.
 //
-import CoreVideo
-import Metal
 import MetalKit
 
 class MetalRenderer: NSObject, MTKViewDelegate {
-    var device: MTLDevice!
-    var commandQueue: MTLCommandQueue!
+    private var device: MTLDevice!
+    private var commandQueue: MTLCommandQueue!
+    private var textureCache: CVMetalTextureCache!
+    private var currentPixelBuffer: CVPixelBuffer?
 
     func setup(view: MTKView) {
         self.device = view.device
         self.commandQueue = device.makeCommandQueue()
-        // 初始化 texture、pipeline 等
+        CVMetalTextureCacheCreate(nil, nil, device, nil, &textureCache)
     }
 
-    // ✅ 必须实现的方法 1:窗口大小改变时调用
-    func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
-        // 可以留空或更新视图缩放、渲染区域等
+    func updateFrame(pixelBuffer: CVPixelBuffer) {
+        self.currentPixelBuffer = pixelBuffer
     }
 
-    // ✅ 必须实现的方法 2:每一帧绘制时调用
+    func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {}
+
     func draw(in view: MTKView) {
         guard let drawable = view.currentDrawable,
-              let descriptor = view.currentRenderPassDescriptor else { return }
+              let descriptor = view.currentRenderPassDescriptor,
+              let pixelBuffer = currentPixelBuffer else { return }
+
+        var textureRef: CVMetalTexture?
+        let width = CVPixelBufferGetWidth(pixelBuffer)
+        let height = CVPixelBufferGetHeight(pixelBuffer)
+
+        let status = CVMetalTextureCacheCreateTextureFromImage(
+            nil, textureCache, pixelBuffer, nil,
+            .bgra8Unorm, width, height, 0, &textureRef)
+
+        guard status == kCVReturnSuccess,
+              let cvTexture = textureRef,
+              let texture = CVMetalTextureGetTexture(cvTexture) else { return }
 
         let commandBuffer = commandQueue.makeCommandBuffer()!
         let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)!
-        // 渲染逻辑,如绘制纹理
+        encoder.setFragmentTexture(texture, index: 0)
         encoder.endEncoding()
+
+        // 简单拷贝(不做 shader 处理)
+        let blitEncoder = commandBuffer.makeBlitCommandEncoder()!
+        let dstTexture = drawable.texture
+        if dstTexture.width != texture.width || dstTexture.height != texture.height {
+            print("❌ 尺寸不一致,无法 blit:src = \(texture.width)x\(texture.height), dst = \(dstTexture.width)x\(dstTexture.height)")
+            return
+        }
+        blitEncoder.copy(from: texture,
+                         sourceSlice: 0,
+                         sourceLevel: 0,
+                         sourceOrigin: MTLOrigin(x: 0, y: 0, z: 0),
+                         sourceSize: MTLSize(width: width, height: height, depth: 1),
+                         to: drawable.texture,
+                         destinationSlice: 0,
+                         destinationLevel: 0,
+                         destinationOrigin: MTLOrigin(x: 0, y: 0, z: 0))
+        blitEncoder.endEncoding()
+
         commandBuffer.present(drawable)
         commandBuffer.commit()
+        print("绘制画面")
     }
 }

--
Gitblit v1.9.1