LNRenderers.swift 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. import Foundation
  2. import UIKit
  3. import CoreVideo
  4. import CoreImage
  5. import QuartzCore
  6. import Metal
  7. import MetalKit
  8. import simd
  9. @objc public protocol LNHWDMetalViewDelegate: AnyObject {
  10. @objc(onMetalViewUnavailable)
  11. func onMetalViewUnavailable()
  12. }
  13. @objc public protocol LNVAPMetalViewDelegate: AnyObject {
  14. @objc(onMetalViewUnavailable)
  15. func onMetalViewUnavailable()
  16. }
  17. @objc public protocol LNHWDMP4OpenGLViewDelegate: AnyObject {
  18. @objc(onViewUnavailableStatus)
  19. func onViewUnavailableStatus()
  20. }
  21. private enum LNLegacyRuntime {
  22. static func cls(_ name: String) -> AnyClass? {
  23. NSClassFromString(name) ?? NSClassFromString("QGVAPlayer.\(name)")
  24. }
  25. static func instantiate(_ className: String) -> NSObject? {
  26. guard let t = cls(className) as? NSObject.Type else { return nil }
  27. return t.init()
  28. }
  29. static func set(_ obj: NSObject, _ key: String, _ value: Any?) {
  30. let setter = "set\(key.prefix(1).uppercased())\(key.dropFirst()):"
  31. let sel = NSSelectorFromString(setter)
  32. guard obj.responds(to: sel) else { return }
  33. obj.setValue(value, forKey: key)
  34. }
  35. static func callInitWithFrame(_ obj: NSObject, frame: CGRect) -> AnyObject? {
  36. let sel = NSSelectorFromString("initWithFrame:")
  37. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return nil }
  38. typealias Fn = @convention(c) (AnyObject, Selector, CGRect) -> AnyObject
  39. return unsafeBitCast(imp, to: Fn.self)(obj, sel, frame)
  40. }
  41. static func callInitWithFrameBlend(_ obj: NSObject, frame: CGRect, blend: Int) -> AnyObject? {
  42. let sel = NSSelectorFromString("initWithFrame:blendMode:")
  43. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return nil }
  44. typealias Fn = @convention(c) (AnyObject, Selector, CGRect, Int) -> AnyObject
  45. return unsafeBitCast(imp, to: Fn.self)(obj, sel, frame, blend)
  46. }
  47. static func callInitWithMetalLayer(_ obj: NSObject, layer: AnyObject) -> AnyObject? {
  48. let sel = NSSelectorFromString("initWithMetalLayer:")
  49. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return nil }
  50. typealias Fn = @convention(c) (AnyObject, Selector, AnyObject) -> AnyObject
  51. return unsafeBitCast(imp, to: Fn.self)(obj, sel, layer)
  52. }
  53. static func callInitWithMetalLayerBlend(_ obj: NSObject, layer: AnyObject, blend: Int) -> AnyObject? {
  54. let sel = NSSelectorFromString("initWithMetalLayer:blendMode:")
  55. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return nil }
  56. typealias Fn = @convention(c) (AnyObject, Selector, AnyObject, Int) -> AnyObject
  57. return unsafeBitCast(imp, to: Fn.self)(obj, sel, layer, blend)
  58. }
  59. static func callRenderPixelBuffer(_ obj: NSObject, pixelBuffer: CVPixelBuffer?, layer: AnyObject?) {
  60. let sel = NSSelectorFromString("renderPixelBuffer:metalLayer:")
  61. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return }
  62. typealias Fn = @convention(c) (AnyObject, Selector, CVPixelBuffer?, AnyObject?) -> Void
  63. unsafeBitCast(imp, to: Fn.self)(obj, sel, pixelBuffer, layer)
  64. }
  65. static func callRenderPixelBufferMerge(_ obj: NSObject, pixelBuffer: CVPixelBuffer?, layer: AnyObject?, infos: NSArray?) {
  66. let sel = NSSelectorFromString("renderPixelBuffer:metalLayer:mergeInfos:")
  67. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return }
  68. typealias Fn = @convention(c) (AnyObject, Selector, CVPixelBuffer?, AnyObject?, NSArray?) -> Void
  69. unsafeBitCast(imp, to: Fn.self)(obj, sel, pixelBuffer, layer, infos)
  70. }
  71. static func callDisplay(_ obj: NSObject, pixelBuffer: CVPixelBuffer?) {
  72. let sel = NSSelectorFromString("display:")
  73. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return }
  74. typealias Fn = @convention(c) (AnyObject, Selector, CVPixelBuffer?) -> Void
  75. unsafeBitCast(imp, to: Fn.self)(obj, sel, pixelBuffer)
  76. }
  77. static func callDisplayMerge(_ obj: NSObject, pixelBuffer: CVPixelBuffer?, infos: NSArray?) {
  78. let sel = NSSelectorFromString("display:mergeInfos:")
  79. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return }
  80. typealias Fn = @convention(c) (AnyObject, Selector, CVPixelBuffer?, NSArray?) -> Void
  81. unsafeBitCast(imp, to: Fn.self)(obj, sel, pixelBuffer, infos)
  82. }
  83. static func callDisplayPixelBuffer(_ obj: NSObject, pixelBuffer: CVPixelBuffer?) {
  84. let sel = NSSelectorFromString("displayPixelBuffer:")
  85. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return }
  86. typealias Fn = @convention(c) (AnyObject, Selector, CVPixelBuffer?) -> Void
  87. unsafeBitCast(imp, to: Fn.self)(obj, sel, pixelBuffer)
  88. }
  89. static func callNoArgs(_ obj: NSObject, _ selector: String) {
  90. let sel = NSSelectorFromString(selector)
  91. guard obj.responds(to: sel), let imp = obj.method(for: sel) else { return }
  92. typealias Fn = @convention(c) (AnyObject, Selector) -> Void
  93. unsafeBitCast(imp, to: Fn.self)(obj, sel)
  94. }
  95. }
  96. private final class LNPixelBufferLayerRenderer {
  97. private let ciContext = CIContext(options: nil)
  98. func render(pixelBuffer: CVPixelBuffer, into layer: CALayer) {
  99. let image = CIImage(cvPixelBuffer: pixelBuffer)
  100. guard let cgImage = ciContext.createCGImage(image, from: image.extent) else { return }
  101. DispatchQueue.main.async {
  102. layer.contents = cgImage
  103. }
  104. }
  105. }
  106. @available(iOS 13.0, *)
  107. private final class LNHWDMetalCoreRenderer {
  108. private struct LNColorParameters {
  109. var matrix: simd_float3x3
  110. var offset: simd_float2
  111. }
  112. private static let kVertexFunctionName = "hwd_vertexShader"
  113. private static let kFragmentFunctionName = "hwd_yuvFragmentShader"
  114. private static let verticesByBlendMode: [[[Float]]] = [
  115. // alpha left
  116. [
  117. [-1.0, -1.0, 0.0, 1.0, 0.5, 1.0, 0.0, 1.0],
  118. [-1.0, 1.0, 0.0, 1.0, 0.5, 0.0, 0.0, 0.0],
  119. [ 1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.5, 1.0],
  120. [ 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.5, 0.0]
  121. ],
  122. // alpha right
  123. [
  124. [-1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.5, 1.0],
  125. [-1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.0],
  126. [ 1.0, -1.0, 0.0, 1.0, 0.5, 1.0, 1.0, 1.0],
  127. [ 1.0, 1.0, 0.0, 1.0, 0.5, 0.0, 1.0, 0.0]
  128. ],
  129. // alpha top
  130. [
  131. [-1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.5],
  132. [-1.0, 1.0, 0.0, 1.0, 0.0, 0.5, 0.0, 0.0],
  133. [ 1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.5],
  134. [ 1.0, 1.0, 0.0, 1.0, 1.0, 0.5, 1.0, 0.0]
  135. ],
  136. // alpha bottom
  137. [
  138. [-1.0, -1.0, 0.0, 1.0, 0.0, 0.5, 0.0, 1.0],
  139. [-1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.5],
  140. [ 1.0, -1.0, 0.0, 1.0, 1.0, 0.5, 1.0, 1.0],
  141. [ 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.5]
  142. ]
  143. ]
  144. private static let matrix601Full = simd_float3x3(
  145. SIMD3<Float>(1.0, 1.0, 1.0),
  146. SIMD3<Float>(0.0, -0.34413, 1.772),
  147. SIMD3<Float>(1.402, -0.71414, 0.0)
  148. )
  149. private static let matrix709Full = simd_float3x3(
  150. SIMD3<Float>(1.0, 1.0, 1.0),
  151. SIMD3<Float>(0.0, -0.18732, 1.8556),
  152. SIMD3<Float>(1.57481, -0.46813, 0.0)
  153. )
  154. private let device: MTLDevice
  155. private let commandQueue: MTLCommandQueue
  156. private let pipelineState: MTLRenderPipelineState
  157. private var textureCache: CVMetalTextureCache?
  158. private var vertexBuffer: MTLBuffer?
  159. private var yuvMatrixBuffer: MTLBuffer?
  160. private var currentColorMatrix = matrix601Full
  161. init?(metalLayer: CAMetalLayer, blendMode: QGHWDTextureBlendMode) {
  162. guard let device = MTLCreateSystemDefaultDevice(),
  163. let queue = device.makeCommandQueue(),
  164. let library = device.makeDefaultLibrary(),
  165. let vertexFunc = library.makeFunction(name: Self.kVertexFunctionName),
  166. let fragmentFunc = library.makeFunction(name: Self.kFragmentFunctionName) else {
  167. return nil
  168. }
  169. let desc = MTLRenderPipelineDescriptor()
  170. desc.vertexFunction = vertexFunc
  171. desc.fragmentFunction = fragmentFunc
  172. desc.colorAttachments[0].pixelFormat = metalLayer.pixelFormat
  173. guard let pipelineState = try? device.makeRenderPipelineState(descriptor: desc) else {
  174. return nil
  175. }
  176. self.device = device
  177. self.commandQueue = queue
  178. self.pipelineState = pipelineState
  179. metalLayer.device = device
  180. metalLayer.framebufferOnly = false
  181. let cacheStatus = CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, device, nil, &textureCache)
  182. guard cacheStatus == kCVReturnSuccess else { return nil }
  183. updateBlendMode(blendMode)
  184. updateYuvMatrixBuffer(matrix: Self.matrix601Full)
  185. }
  186. func updateBlendMode(_ blendMode: QGHWDTextureBlendMode) {
  187. let modeIndex = max(0, min(Int(blendMode.rawValue), Self.verticesByBlendMode.count - 1))
  188. let flat = Self.verticesByBlendMode[modeIndex].flatMap { $0 }
  189. vertexBuffer = device.makeBuffer(bytes: flat, length: flat.count * MemoryLayout<Float>.size, options: .storageModeShared)
  190. }
  191. func render(pixelBuffer: CVPixelBuffer, metalLayer: CAMetalLayer) {
  192. guard metalLayer.bounds.width > 0,
  193. metalLayer.bounds.height > 0,
  194. let drawable = metalLayer.nextDrawable(),
  195. let commandBuffer = commandQueue.makeCommandBuffer(),
  196. let descriptor = currentRenderPassDescriptor(texture: drawable.texture),
  197. let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor),
  198. let vertexBuffer,
  199. let yuvMatrixBuffer else {
  200. return
  201. }
  202. updateYuvMatrixIfNeeded(pixelBuffer: pixelBuffer)
  203. guard let yTexture = makeTexture(pixelBuffer: pixelBuffer, plane: 0, format: .r8Unorm),
  204. let uvTexture = makeTexture(pixelBuffer: pixelBuffer, plane: 1, format: .rg8Unorm) else {
  205. return
  206. }
  207. encoder.setRenderPipelineState(pipelineState)
  208. encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
  209. encoder.setFragmentBuffer(yuvMatrixBuffer, offset: 0, index: 0)
  210. encoder.setFragmentTexture(yTexture, index: 0)
  211. encoder.setFragmentTexture(uvTexture, index: 1)
  212. encoder.drawPrimitives(type: MTLPrimitiveType.triangleStrip, vertexStart: 0, vertexCount: 4)
  213. encoder.endEncoding()
  214. commandBuffer.present(drawable)
  215. commandBuffer.commit()
  216. }
  217. func dispose() {
  218. if let textureCache {
  219. CVMetalTextureCacheFlush(textureCache, 0)
  220. }
  221. textureCache = nil
  222. vertexBuffer = nil
  223. yuvMatrixBuffer = nil
  224. }
  225. private func makeTexture(pixelBuffer: CVPixelBuffer, plane: Int, format: MTLPixelFormat) -> MTLTexture? {
  226. guard let textureCache else { return nil }
  227. let width = CVPixelBufferGetWidthOfPlane(pixelBuffer, plane)
  228. let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, plane)
  229. var cvTexture: CVMetalTexture?
  230. let status = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
  231. textureCache,
  232. pixelBuffer,
  233. nil,
  234. format,
  235. width,
  236. height,
  237. plane,
  238. &cvTexture)
  239. guard status == kCVReturnSuccess, let cvTexture else { return nil }
  240. return CVMetalTextureGetTexture(cvTexture)
  241. }
  242. private func currentRenderPassDescriptor(texture: MTLTexture) -> MTLRenderPassDescriptor? {
  243. let descriptor = MTLRenderPassDescriptor()
  244. descriptor.colorAttachments[0].texture = texture
  245. descriptor.colorAttachments[0].loadAction = .clear
  246. descriptor.colorAttachments[0].storeAction = .store
  247. descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0)
  248. return descriptor
  249. }
  250. private func updateYuvMatrixIfNeeded(pixelBuffer: CVPixelBuffer) {
  251. let matrixAttachment = CVBufferGetAttachment(pixelBuffer, kCVImageBufferYCbCrMatrixKey, nil)?.takeUnretainedValue()
  252. let matrix = (matrixAttachment != nil && CFEqual(matrixAttachment, kCVImageBufferYCbCrMatrix_ITU_R_709_2)) ? Self.matrix709Full : Self.matrix601Full
  253. guard matrix != currentColorMatrix else { return }
  254. currentColorMatrix = matrix
  255. updateYuvMatrixBuffer(matrix: matrix)
  256. }
  257. private func updateYuvMatrixBuffer(matrix: simd_float3x3) {
  258. let params = LNColorParameters(matrix: matrix, offset: simd_float2(0.5, 0.5))
  259. yuvMatrixBuffer = device.makeBuffer(bytes: [params], length: MemoryLayout<LNColorParameters>.stride, options: .storageModeShared)
  260. }
  261. }
  262. @available(iOS 13.0, *)
  263. private final class LNVAPMetalCoreRenderer {
  264. private struct LNColorParameters {
  265. var matrix: simd_float3x3
  266. var offset: simd_float2
  267. }
  268. private struct LNMaskParameters {
  269. var weightMatrix: simd_float3x3
  270. var coreSize: Int32
  271. var texelOffset: Float
  272. }
  273. private static let matrix601Full = simd_float3x3(
  274. SIMD3<Float>(1.0, 1.0, 1.0),
  275. SIMD3<Float>(0.0, -0.34413, 1.772),
  276. SIMD3<Float>(1.402, -0.71414, 0.0)
  277. )
  278. private static let matrix709Full = simd_float3x3(
  279. SIMD3<Float>(1.0, 1.0, 1.0),
  280. SIMD3<Float>(0.0, -0.18732, 1.8556),
  281. SIMD3<Float>(1.57481, -0.46813, 0.0)
  282. )
  283. private let device: MTLDevice
  284. private let pixelFormat: MTLPixelFormat
  285. private let commandQueue: MTLCommandQueue
  286. private let shaderLoader: LNVAPMetalShaderFunctionLoader
  287. private var textureCache: CVMetalTextureCache?
  288. private var defaultMainPipelineState: MTLRenderPipelineState?
  289. private var mainPipelineStateForMask: MTLRenderPipelineState?
  290. private var mainPipelineStateForMaskBlur: MTLRenderPipelineState?
  291. private var attachmentPipelineState: MTLRenderPipelineState?
  292. private var vertexBuffer: MTLBuffer?
  293. private var yuvMatrixBuffer: MTLBuffer?
  294. private var maskBlurBuffer: MTLBuffer?
  295. private var maskTexture: MTLTexture?
  296. private var currentColorMatrix = matrix601Full
  297. var commonInfo: LNVAPCommonInfo? {
  298. didSet {
  299. updateMainVertexBuffer()
  300. }
  301. }
  302. var maskInfo: LNVAPMaskInfo? {
  303. didSet {
  304. updateMainVertexBuffer()
  305. updateMaskTexture()
  306. }
  307. }
  308. init?(metalLayer: CAMetalLayer) {
  309. guard let device = MTLCreateSystemDefaultDevice(),
  310. let queue = device.makeCommandQueue() else {
  311. return nil
  312. }
  313. self.device = device
  314. self.pixelFormat = metalLayer.pixelFormat
  315. self.commandQueue = queue
  316. self.shaderLoader = LNVAPMetalShaderFunctionLoader(device: device)
  317. metalLayer.device = device
  318. metalLayer.framebufferOnly = false
  319. let cacheStatus = CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, device, nil, &textureCache)
  320. guard cacheStatus == kCVReturnSuccess else { return nil }
  321. updateYuvMatrixBuffer(matrix: Self.matrix601Full)
  322. }
  323. func render(pixelBuffer: CVPixelBuffer, metalLayer: CAMetalLayer, mergeInfos: [LNVAPMergedInfo]) {
  324. guard metalLayer.bounds.width > 0,
  325. metalLayer.bounds.height > 0,
  326. let drawable = metalLayer.nextDrawable(),
  327. let commandBuffer = commandQueue.makeCommandBuffer(),
  328. let descriptor = currentRenderPassDescriptor(texture: drawable.texture),
  329. let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else {
  330. return
  331. }
  332. updateYuvMatrixIfNeeded(pixelBuffer: pixelBuffer)
  333. guard let yTexture = makeTexture(pixelBuffer: pixelBuffer, plane: 0, format: .r8Unorm),
  334. let uvTexture = makeTexture(pixelBuffer: pixelBuffer, plane: 1, format: .rg8Unorm) else {
  335. return
  336. }
  337. drawBackground(encoder: encoder, yTexture: yTexture, uvTexture: uvTexture)
  338. drawMergedAttachments(encoder: encoder, yTexture: yTexture, uvTexture: uvTexture, mergeInfos: mergeInfos)
  339. encoder.endEncoding()
  340. commandBuffer.present(drawable)
  341. commandBuffer.commit()
  342. }
  343. func dispose() {
  344. if let textureCache {
  345. CVMetalTextureCacheFlush(textureCache, 0)
  346. }
  347. textureCache = nil
  348. vertexBuffer = nil
  349. yuvMatrixBuffer = nil
  350. maskBlurBuffer = nil
  351. maskTexture = nil
  352. defaultMainPipelineState = nil
  353. mainPipelineStateForMask = nil
  354. mainPipelineStateForMaskBlur = nil
  355. attachmentPipelineState = nil
  356. }
  357. private func drawBackground(encoder: MTLRenderCommandEncoder, yTexture: MTLTexture, uvTexture: MTLTexture) {
  358. guard let vertexBuffer,
  359. let yuvMatrixBuffer else {
  360. return
  361. }
  362. if let maskInfo,
  363. let maskTexture {
  364. if maskInfo.blurLength > 0 {
  365. guard let pipelineState = mainPipelineStateForMaskBlur ?? makeMaskBlurPipelineState(),
  366. let maskBlurBuffer = maskBlurBuffer ?? makeMaskBlurBuffer() else {
  367. return
  368. }
  369. encoder.setRenderPipelineState(pipelineState)
  370. encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
  371. encoder.setFragmentBuffer(yuvMatrixBuffer, offset: 0, index: 0)
  372. encoder.setFragmentBuffer(maskBlurBuffer, offset: 0, index: 1)
  373. encoder.setFragmentTexture(yTexture, index: 0)
  374. encoder.setFragmentTexture(uvTexture, index: 1)
  375. encoder.setFragmentTexture(maskTexture, index: 2)
  376. encoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
  377. return
  378. }
  379. guard let pipelineState = mainPipelineStateForMask ?? makeMaskPipelineState() else {
  380. return
  381. }
  382. encoder.setRenderPipelineState(pipelineState)
  383. encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
  384. encoder.setFragmentBuffer(yuvMatrixBuffer, offset: 0, index: 0)
  385. encoder.setFragmentTexture(yTexture, index: 0)
  386. encoder.setFragmentTexture(uvTexture, index: 1)
  387. encoder.setFragmentTexture(maskTexture, index: 2)
  388. encoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
  389. return
  390. }
  391. guard let pipelineState = defaultMainPipelineState ?? makeMainPipelineState() else {
  392. return
  393. }
  394. encoder.setRenderPipelineState(pipelineState)
  395. encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
  396. encoder.setFragmentBuffer(yuvMatrixBuffer, offset: 0, index: 0)
  397. encoder.setFragmentTexture(yTexture, index: 0)
  398. encoder.setFragmentTexture(uvTexture, index: 1)
  399. encoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
  400. }
  401. private func drawMergedAttachments(encoder: MTLRenderCommandEncoder, yTexture: MTLTexture, uvTexture: MTLTexture, mergeInfos: [LNVAPMergedInfo]) {
  402. guard !mergeInfos.isEmpty,
  403. let commonInfo,
  404. let pipelineState = attachmentPipelineState ?? makeAttachmentPipelineState(),
  405. let yuvMatrixBuffer else {
  406. return
  407. }
  408. for mergeInfo in mergeInfos {
  409. guard let sourceTexture = mergeInfo.source?.texture,
  410. let colorParamsBuffer = mergeInfo.source?.colorParamsBuffer,
  411. let mergeVertexBuffer = mergeInfo.vertexBuffer(containerSize: commonInfo.size,
  412. maskContianerSize: commonInfo.videoSize,
  413. device: device) else {
  414. continue
  415. }
  416. encoder.setRenderPipelineState(pipelineState)
  417. encoder.setVertexBuffer(mergeVertexBuffer, offset: 0, index: 0)
  418. encoder.setFragmentBuffer(yuvMatrixBuffer, offset: 0, index: 0)
  419. encoder.setFragmentBuffer(colorParamsBuffer, offset: 0, index: 1)
  420. encoder.setFragmentTexture(yTexture, index: 0)
  421. encoder.setFragmentTexture(uvTexture, index: 1)
  422. encoder.setFragmentTexture(sourceTexture, index: 2)
  423. encoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
  424. }
  425. }
  426. private func makeMainPipelineState() -> MTLRenderPipelineState? {
  427. guard let state = createPipelineState(vertexFunction: LNVAPMetalUtil.vapVertexFunctionName,
  428. fragmentFunction: LNVAPMetalUtil.vapYUVFragmentFunctionName) else {
  429. return nil
  430. }
  431. defaultMainPipelineState = state
  432. return state
  433. }
  434. private func makeMaskPipelineState() -> MTLRenderPipelineState? {
  435. guard let state = createPipelineState(vertexFunction: LNVAPMetalUtil.vapVertexFunctionName,
  436. fragmentFunction: LNVAPMetalUtil.vapMaskFragmentFunctionName) else {
  437. return nil
  438. }
  439. mainPipelineStateForMask = state
  440. return state
  441. }
  442. private func makeMaskBlurPipelineState() -> MTLRenderPipelineState? {
  443. guard let state = createPipelineState(vertexFunction: LNVAPMetalUtil.vapVertexFunctionName,
  444. fragmentFunction: LNVAPMetalUtil.vapMaskBlurFragmentFunctionName) else {
  445. return nil
  446. }
  447. mainPipelineStateForMaskBlur = state
  448. return state
  449. }
  450. private func makeAttachmentPipelineState() -> MTLRenderPipelineState? {
  451. guard let state = createPipelineState(vertexFunction: LNVAPMetalUtil.vapAttachmentVertexFunctionName,
  452. fragmentFunction: LNVAPMetalUtil.vapAttachmentFragmentFunctionName) else {
  453. return nil
  454. }
  455. attachmentPipelineState = state
  456. return state
  457. }
  458. private func createPipelineState(vertexFunction: String, fragmentFunction: String) -> MTLRenderPipelineState? {
  459. guard let vertexProgram = shaderLoader.loadFunction(withName: vertexFunction),
  460. let fragmentProgram = shaderLoader.loadFunction(withName: fragmentFunction) else {
  461. return nil
  462. }
  463. let descriptor = MTLRenderPipelineDescriptor()
  464. descriptor.vertexFunction = vertexProgram
  465. descriptor.fragmentFunction = fragmentProgram
  466. descriptor.colorAttachments[0].pixelFormat = pixelFormat
  467. descriptor.colorAttachments[0].isBlendingEnabled = true
  468. descriptor.colorAttachments[0].rgbBlendOperation = .add
  469. descriptor.colorAttachments[0].alphaBlendOperation = .add
  470. descriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
  471. descriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
  472. descriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
  473. descriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
  474. return try? device.makeRenderPipelineState(descriptor: descriptor)
  475. }
  476. private func updateMainVertexBuffer() {
  477. guard let commonInfo else {
  478. vertexBuffer = nil
  479. return
  480. }
  481. let vertices = LNVAPMetalUtil.vapMTLVerticesIdentity
  482. let rgbCoordinates = LNVAPMetalUtil.genTextureCoordinates(rect: commonInfo.rgbAreaRect, containerSize: commonInfo.videoSize, reverse: false, degree: 0)
  483. let alphaCoordinates = LNVAPMetalUtil.genTextureCoordinates(rect: commonInfo.alphaAreaRect, containerSize: commonInfo.videoSize, reverse: false, degree: 0)
  484. let maskCoordinates: [Float]
  485. if let maskInfo {
  486. maskCoordinates = LNVAPMetalUtil.genTextureCoordinates(rect: maskInfo.sampleRect, containerSize: maskInfo.dataSize, reverse: false, degree: 0)
  487. } else {
  488. maskCoordinates = [Float](repeating: 0, count: 8)
  489. }
  490. var vertexData = [Float](repeating: 0, count: 40)
  491. var index = 0
  492. for i in 0..<16 {
  493. vertexData[index] = vertices[i]
  494. index += 1
  495. if i % 4 == 3 {
  496. let row = i / 4
  497. vertexData[index] = rgbCoordinates[row * 2]
  498. index += 1
  499. vertexData[index] = rgbCoordinates[row * 2 + 1]
  500. index += 1
  501. vertexData[index] = alphaCoordinates[row * 2]
  502. index += 1
  503. vertexData[index] = alphaCoordinates[row * 2 + 1]
  504. index += 1
  505. vertexData[index] = maskCoordinates[row * 2]
  506. index += 1
  507. vertexData[index] = maskCoordinates[row * 2 + 1]
  508. index += 1
  509. }
  510. }
  511. vertexBuffer = device.makeBuffer(bytes: vertexData, length: vertexData.count * MemoryLayout<Float>.size, options: .storageModeShared)
  512. }
  513. private func updateMaskTexture() {
  514. guard let maskInfo else {
  515. maskTexture = nil
  516. return
  517. }
  518. let width = Int(maskInfo.dataSize.width)
  519. let height = Int(maskInfo.dataSize.height)
  520. guard width > 0,
  521. height > 0,
  522. !maskInfo.data.isEmpty else {
  523. maskTexture = nil
  524. return
  525. }
  526. let descriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .r8Unorm, width: width, height: height, mipmapped: false)
  527. descriptor.usage = [.shaderRead]
  528. descriptor.storageMode = .shared
  529. guard let texture = device.makeTexture(descriptor: descriptor) else {
  530. maskTexture = nil
  531. return
  532. }
  533. maskInfo.data.withUnsafeBytes { bytes in
  534. guard let base = bytes.baseAddress else { return }
  535. texture.replace(region: MTLRegionMake2D(0, 0, width, height), mipmapLevel: 0, withBytes: base, bytesPerRow: width)
  536. }
  537. maskTexture = texture
  538. }
  539. private func makeMaskBlurBuffer() -> MTLBuffer? {
  540. let weight = simd_float3x3(
  541. SIMD3<Float>(0.0625, 0.125, 0.0625),
  542. SIMD3<Float>(0.125, 0.25, 0.125),
  543. SIMD3<Float>(0.0625, 0.125, 0.0625)
  544. )
  545. let params = LNMaskParameters(weightMatrix: weight, coreSize: 3, texelOffset: 0.01)
  546. let buffer = device.makeBuffer(bytes: [params], length: MemoryLayout<LNMaskParameters>.stride, options: .storageModeShared)
  547. maskBlurBuffer = buffer
  548. return buffer
  549. }
  550. private func makeTexture(pixelBuffer: CVPixelBuffer, plane: Int, format: MTLPixelFormat) -> MTLTexture? {
  551. guard let textureCache else { return nil }
  552. let width = CVPixelBufferGetWidthOfPlane(pixelBuffer, plane)
  553. let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, plane)
  554. var cvTexture: CVMetalTexture?
  555. let status = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
  556. textureCache,
  557. pixelBuffer,
  558. nil,
  559. format,
  560. width,
  561. height,
  562. plane,
  563. &cvTexture)
  564. guard status == kCVReturnSuccess, let cvTexture else { return nil }
  565. return CVMetalTextureGetTexture(cvTexture)
  566. }
  567. private func currentRenderPassDescriptor(texture: MTLTexture) -> MTLRenderPassDescriptor? {
  568. let descriptor = MTLRenderPassDescriptor()
  569. descriptor.colorAttachments[0].texture = texture
  570. descriptor.colorAttachments[0].loadAction = .clear
  571. descriptor.colorAttachments[0].storeAction = .store
  572. descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0)
  573. return descriptor
  574. }
  575. private func updateYuvMatrixIfNeeded(pixelBuffer: CVPixelBuffer) {
  576. let matrixAttachment = CVBufferGetAttachment(pixelBuffer, kCVImageBufferYCbCrMatrixKey, nil)?.takeUnretainedValue()
  577. let matrix = (matrixAttachment != nil && CFEqual(matrixAttachment, kCVImageBufferYCbCrMatrix_ITU_R_709_2)) ? Self.matrix709Full : Self.matrix601Full
  578. guard matrix != currentColorMatrix else { return }
  579. currentColorMatrix = matrix
  580. updateYuvMatrixBuffer(matrix: matrix)
  581. }
  582. private func updateYuvMatrixBuffer(matrix: simd_float3x3) {
  583. let params = LNColorParameters(matrix: matrix, offset: simd_float2(0.5, 0.5))
  584. yuvMatrixBuffer = device.makeBuffer(bytes: [params], length: MemoryLayout<LNColorParameters>.stride, options: .storageModeShared)
  585. }
  586. }
  587. private final class LNMetalUnavailableBridge: NSObject {
  588. var callback: (() -> Void)?
  589. @objc func onMetalViewUnavailable() {
  590. callback?()
  591. }
  592. @objc func onViewUnavailableStatus() {
  593. callback?()
  594. }
  595. }
  596. private enum LNVAPLegacyMapper {
  597. static func toLegacyCommonInfo(_ info: LNVAPCommonInfo?) -> NSObject? {
  598. guard let info, let obj = LNLegacyRuntime.instantiate("QGVAPCommonInfo") else { return nil }
  599. LNLegacyRuntime.set(obj, "version", info.version)
  600. LNLegacyRuntime.set(obj, "framesCount", info.framesCount)
  601. LNLegacyRuntime.set(obj, "size", NSValue(cgSize: info.size))
  602. LNLegacyRuntime.set(obj, "videoSize", NSValue(cgSize: info.videoSize))
  603. LNLegacyRuntime.set(obj, "targetOrientaion", info.targetOrientaion.rawValue)
  604. LNLegacyRuntime.set(obj, "fps", info.fps)
  605. LNLegacyRuntime.set(obj, "isMerged", info.isMerged)
  606. LNLegacyRuntime.set(obj, "alphaAreaRect", NSValue(cgRect: info.alphaAreaRect))
  607. LNLegacyRuntime.set(obj, "rgbAreaRect", NSValue(cgRect: info.rgbAreaRect))
  608. return obj
  609. }
  610. static func toLegacyMaskInfo(_ info: LNVAPMaskInfo?) -> NSObject? {
  611. guard let info, let obj = LNLegacyRuntime.instantiate("QGVAPMaskInfo") else { return nil }
  612. LNLegacyRuntime.set(obj, "data", info.data)
  613. LNLegacyRuntime.set(obj, "dataSize", NSValue(cgSize: info.dataSize))
  614. LNLegacyRuntime.set(obj, "positionInVideoRect", NSValue(cgRect: info.sampleRect))
  615. return obj
  616. }
  617. static func toLegacySourceInfo(_ info: LNVAPSourceInfo?) -> NSObject? {
  618. guard let info, let obj = LNLegacyRuntime.instantiate("QGVAPSourceInfo") else { return nil }
  619. LNLegacyRuntime.set(obj, "contentTag", info.contentTag)
  620. LNLegacyRuntime.set(obj, "contentTagValue", info.contentTagValue)
  621. LNLegacyRuntime.set(obj, "color", info.color)
  622. LNLegacyRuntime.set(obj, "size", NSValue(cgSize: info.size))
  623. LNLegacyRuntime.set(obj, "sourceImage", info.sourceImage)
  624. LNLegacyRuntime.set(obj, "texture", info.texture)
  625. LNLegacyRuntime.set(obj, "colorParamsBuffer", info.colorParamsBuffer)
  626. return obj
  627. }
  628. static func toLegacyMergedInfos(_ infos: [LNVAPMergedInfo]) -> NSArray {
  629. let out = NSMutableArray(capacity: infos.count)
  630. for info in infos {
  631. guard let obj = LNLegacyRuntime.instantiate("QGVAPMergedInfo") else { continue }
  632. LNLegacyRuntime.set(obj, "source", toLegacySourceInfo(info.source))
  633. LNLegacyRuntime.set(obj, "renderIndex", info.renderIndex)
  634. LNLegacyRuntime.set(obj, "renderRect", NSValue(cgRect: info.renderRect))
  635. LNLegacyRuntime.set(obj, "needMask", info.needMask)
  636. LNLegacyRuntime.set(obj, "maskRect", NSValue(cgRect: info.maskRect))
  637. LNLegacyRuntime.set(obj, "maskRotation", info.maskRotation)
  638. out.add(obj)
  639. }
  640. return out
  641. }
  642. }
  643. @objcMembers
  644. public final class LNHWDMetalRenderer: NSObject {
  645. public var blendMode: QGHWDTextureBlendMode {
  646. didSet {
  647. if #available(iOS 13.0, *), let swiftRenderer = swiftRenderer as? LNHWDMetalCoreRenderer {
  648. swiftRenderer.updateBlendMode(blendMode)
  649. }
  650. if let legacy = legacyRenderer {
  651. LNLegacyRuntime.set(legacy, "blendMode", blendMode.rawValue)
  652. }
  653. }
  654. }
  655. private let fallback = LNPixelBufferLayerRenderer()
  656. private let fallbackLayer = CALayer()
  657. private let legacyRenderer: NSObject?
  658. private let swiftRenderer: AnyObject?
  659. @objc(initWithMetalLayer:blendMode:)
  660. public init(metalLayer: AnyObject, blendMode: QGHWDTextureBlendMode) {
  661. self.blendMode = blendMode
  662. if #available(iOS 13.0, *), let metalLayer = metalLayer as? CAMetalLayer {
  663. self.swiftRenderer = LNHWDMetalCoreRenderer(metalLayer: metalLayer, blendMode: blendMode)
  664. } else {
  665. self.swiftRenderer = nil
  666. }
  667. if self.swiftRenderer == nil, let rendererObj = LNLegacyRuntime.instantiate("QGHWDMetalRenderer") {
  668. let created = LNLegacyRuntime.callInitWithMetalLayerBlend(rendererObj, layer: metalLayer, blend: Int(blendMode.rawValue))
  669. self.legacyRenderer = (created as? NSObject) ?? rendererObj
  670. } else {
  671. self.legacyRenderer = nil
  672. }
  673. super.init()
  674. }
  675. @objc(renderPixelBuffer:metalLayer:)
  676. public func renderPixelBuffer(_ pixelBuffer: CVPixelBuffer?, metalLayer: AnyObject) {
  677. if #available(iOS 13.0, *),
  678. let pixelBuffer,
  679. let metalLayer = metalLayer as? CAMetalLayer,
  680. let swiftRenderer = swiftRenderer as? LNHWDMetalCoreRenderer {
  681. swiftRenderer.render(pixelBuffer: pixelBuffer, metalLayer: metalLayer)
  682. return
  683. }
  684. if let legacy = legacyRenderer {
  685. LNLegacyRuntime.callRenderPixelBuffer(legacy, pixelBuffer: pixelBuffer, layer: metalLayer)
  686. return
  687. }
  688. guard let pixelBuffer else { return }
  689. let target = (metalLayer as? CALayer) ?? fallbackLayer
  690. fallback.render(pixelBuffer: pixelBuffer, into: target)
  691. }
  692. @objc(dispose)
  693. public func dispose() {
  694. if #available(iOS 13.0, *), let swiftRenderer = swiftRenderer as? LNHWDMetalCoreRenderer {
  695. swiftRenderer.dispose()
  696. }
  697. if let legacy = legacyRenderer {
  698. LNLegacyRuntime.callNoArgs(legacy, "dispose")
  699. }
  700. }
  701. }
  702. @objcMembers
  703. public final class LNHWDMetalView: UIView {
  704. public weak var delegate: LNHWDMetalViewDelegate?
  705. public weak var lnDelegate: LNHWDMetalViewDelegate? {
  706. get { delegate }
  707. set { delegate = newValue }
  708. }
  709. public var blendMode: QGHWDTextureBlendMode {
  710. didSet {
  711. fallbackRenderer.blendMode = blendMode
  712. }
  713. }
  714. private let unavailableBridge = LNMetalUnavailableBridge()
  715. private var renderLayer: CALayer = CALayer()
  716. private lazy var fallbackRenderer = LNHWDMetalRenderer(metalLayer: renderLayer, blendMode: blendMode)
  717. @objc(initWithFrame:blendMode:)
  718. public init(frame: CGRect, blendMode: QGHWDTextureBlendMode) {
  719. self.blendMode = blendMode
  720. super.init(frame: frame)
  721. setupRenderingLayer(frame: frame)
  722. }
  723. public required init?(coder: NSCoder) {
  724. self.blendMode = .alphaLeft
  725. super.init(coder: coder)
  726. setupRenderingLayer(frame: bounds)
  727. }
  728. private func setupRenderingLayer(frame: CGRect) {
  729. unavailableBridge.callback = { [weak self] in
  730. self?.delegate?.onMetalViewUnavailable()
  731. }
  732. if #available(iOS 13.0, *) {
  733. let metalLayer = CAMetalLayer()
  734. metalLayer.pixelFormat = .bgra8Unorm
  735. renderLayer = metalLayer
  736. } else {
  737. renderLayer = CALayer()
  738. }
  739. renderLayer.frame = frame
  740. renderLayer.contentsScale = UIScreen.main.scale
  741. renderLayer.contentsGravity = .resizeAspect
  742. layer.addSublayer(renderLayer)
  743. }
  744. public override func layoutSubviews() {
  745. super.layoutSubviews()
  746. renderLayer.frame = bounds
  747. }
  748. @objc(display:)
  749. public func display(_ pixelBuffer: CVPixelBuffer?) {
  750. fallbackRenderer.renderPixelBuffer(pixelBuffer, metalLayer: renderLayer)
  751. }
  752. @objc(dispose)
  753. public func dispose() {
  754. renderLayer.contents = nil
  755. }
  756. }
  757. @objcMembers
  758. public final class LNVAPMetalRenderer: NSObject {
  759. public var commonInfo: LNVAPCommonInfo? {
  760. didSet {
  761. if #available(iOS 13.0, *), let swiftRenderer = swiftRenderer as? LNVAPMetalCoreRenderer {
  762. swiftRenderer.commonInfo = commonInfo
  763. }
  764. guard let legacy = legacyRenderer else { return }
  765. LNLegacyRuntime.set(legacy, "commonInfo", LNVAPLegacyMapper.toLegacyCommonInfo(commonInfo))
  766. }
  767. }
  768. public var maskInfo: LNVAPMaskInfo? {
  769. didSet {
  770. if #available(iOS 13.0, *), let swiftRenderer = swiftRenderer as? LNVAPMetalCoreRenderer {
  771. swiftRenderer.maskInfo = maskInfo
  772. }
  773. guard let legacy = legacyRenderer else { return }
  774. LNLegacyRuntime.set(legacy, "maskInfo", LNVAPLegacyMapper.toLegacyMaskInfo(maskInfo))
  775. }
  776. }
  777. private let fallback = LNPixelBufferLayerRenderer()
  778. private let fallbackLayer = CALayer()
  779. private let legacyRenderer: NSObject?
  780. private let swiftRenderer: AnyObject?
  781. @objc(initWithMetalLayer:)
  782. public init(metalLayer: AnyObject) {
  783. if #available(iOS 13.0, *), let metalLayer = metalLayer as? CAMetalLayer {
  784. self.swiftRenderer = LNVAPMetalCoreRenderer(metalLayer: metalLayer)
  785. } else {
  786. self.swiftRenderer = nil
  787. }
  788. if let rendererObj = LNLegacyRuntime.instantiate("QGVAPMetalRenderer") {
  789. let created = LNLegacyRuntime.callInitWithMetalLayer(rendererObj, layer: metalLayer)
  790. self.legacyRenderer = (created as? NSObject) ?? rendererObj
  791. } else {
  792. self.legacyRenderer = nil
  793. }
  794. super.init()
  795. }
  796. @objc(renderPixelBuffer:metalLayer:mergeInfos:)
  797. public func renderPixelBuffer(_ pixelBuffer: CVPixelBuffer?, metalLayer: AnyObject, mergeInfos: [LNVAPMergedInfo]) {
  798. if #available(iOS 13.0, *),
  799. let pixelBuffer,
  800. let metalLayer = metalLayer as? CAMetalLayer,
  801. let swiftRenderer = swiftRenderer as? LNVAPMetalCoreRenderer {
  802. swiftRenderer.render(pixelBuffer: pixelBuffer, metalLayer: metalLayer, mergeInfos: mergeInfos)
  803. return
  804. }
  805. if let legacy = legacyRenderer {
  806. LNLegacyRuntime.set(legacy, "commonInfo", LNVAPLegacyMapper.toLegacyCommonInfo(commonInfo))
  807. LNLegacyRuntime.set(legacy, "maskInfo", LNVAPLegacyMapper.toLegacyMaskInfo(maskInfo))
  808. LNLegacyRuntime.callRenderPixelBufferMerge(legacy,
  809. pixelBuffer: pixelBuffer,
  810. layer: metalLayer,
  811. infos: LNVAPLegacyMapper.toLegacyMergedInfos(mergeInfos))
  812. return
  813. }
  814. guard let pixelBuffer else { return }
  815. let target = (metalLayer as? CALayer) ?? fallbackLayer
  816. fallback.render(pixelBuffer: pixelBuffer, into: target)
  817. }
  818. @objc(dispose)
  819. public func dispose() {
  820. if #available(iOS 13.0, *), let swiftRenderer = swiftRenderer as? LNVAPMetalCoreRenderer {
  821. swiftRenderer.dispose()
  822. }
  823. if let legacy = legacyRenderer {
  824. LNLegacyRuntime.callNoArgs(legacy, "dispose")
  825. }
  826. }
  827. }
  828. @objcMembers
  829. public final class LNVAPMetalView: UIView {
  830. public weak var delegate: LNVAPMetalViewDelegate?
  831. public weak var lnDelegate: LNVAPMetalViewDelegate? {
  832. get { delegate }
  833. set { delegate = newValue }
  834. }
  835. public var commonInfo: LNVAPCommonInfo?
  836. public var maskInfo: LNVAPMaskInfo?
  837. private let unavailableBridge = LNMetalUnavailableBridge()
  838. private var renderLayer: CALayer = CALayer()
  839. private lazy var fallbackRenderer = LNVAPMetalRenderer(metalLayer: renderLayer)
  840. public override init(frame: CGRect) {
  841. super.init(frame: frame)
  842. setupRenderingLayer(frame: frame)
  843. }
  844. public required init?(coder: NSCoder) {
  845. super.init(coder: coder)
  846. setupRenderingLayer(frame: bounds)
  847. }
  848. private func setupRenderingLayer(frame: CGRect) {
  849. unavailableBridge.callback = { [weak self] in
  850. self?.delegate?.onMetalViewUnavailable()
  851. }
  852. if #available(iOS 13.0, *) {
  853. let metalLayer = CAMetalLayer()
  854. metalLayer.pixelFormat = .bgra8Unorm
  855. renderLayer = metalLayer
  856. } else {
  857. renderLayer = CALayer()
  858. }
  859. renderLayer.frame = frame
  860. renderLayer.contentsScale = UIScreen.main.scale
  861. renderLayer.contentsGravity = .resizeAspect
  862. layer.addSublayer(renderLayer)
  863. }
  864. public override func layoutSubviews() {
  865. super.layoutSubviews()
  866. renderLayer.frame = bounds
  867. }
  868. @objc(display:mergeInfos:)
  869. public func display(_ pixelBuffer: CVPixelBuffer?, mergeInfos: [LNVAPMergedInfo]) {
  870. fallbackRenderer.commonInfo = commonInfo
  871. fallbackRenderer.maskInfo = maskInfo
  872. fallbackRenderer.renderPixelBuffer(pixelBuffer, metalLayer: renderLayer, mergeInfos: mergeInfos)
  873. }
  874. @objc(dispose)
  875. public func dispose() {
  876. renderLayer.contents = nil
  877. }
  878. }
  879. @objcMembers
  880. public final class LNHWDMP4OpenGLView: UIView {
  881. public weak var displayDelegate: LNHWDMP4OpenGLViewDelegate?
  882. public var glContext: AnyObject?
  883. public var blendMode: QGHWDTextureBlendMode = .alphaLeft {
  884. didSet {
  885. fallbackRenderer.blendMode = blendMode
  886. }
  887. }
  888. public var pause: Bool = false
  889. private var renderLayer: CALayer = CALayer()
  890. private lazy var fallbackRenderer = LNHWDMetalRenderer(metalLayer: renderLayer, blendMode: blendMode)
  891. public override init(frame: CGRect) {
  892. super.init(frame: frame)
  893. setupRenderingLayer(frame: frame)
  894. }
  895. public required init?(coder: NSCoder) {
  896. super.init(coder: coder)
  897. setupRenderingLayer(frame: bounds)
  898. }
  899. private func setupRenderingLayer(frame: CGRect) {
  900. if #available(iOS 13.0, *) {
  901. let metalLayer = CAMetalLayer()
  902. metalLayer.pixelFormat = .bgra8Unorm
  903. renderLayer = metalLayer
  904. } else {
  905. renderLayer = CALayer()
  906. }
  907. renderLayer.frame = frame
  908. renderLayer.contentsScale = UIScreen.main.scale
  909. renderLayer.contentsGravity = .resizeAspect
  910. layer.addSublayer(renderLayer)
  911. }
  912. public override func layoutSubviews() {
  913. super.layoutSubviews()
  914. renderLayer.frame = bounds
  915. }
  916. @objc(setupGL)
  917. public func setupGL() {
  918. renderLayer.frame = bounds
  919. }
  920. @objc(displayPixelBuffer:)
  921. public func displayPixelBuffer(_ pixelBuffer: CVPixelBuffer?) {
  922. if window == nil {
  923. displayDelegate?.onViewUnavailableStatus()
  924. return
  925. }
  926. guard !pause, let pixelBuffer else { return }
  927. fallbackRenderer.blendMode = blendMode
  928. fallbackRenderer.renderPixelBuffer(pixelBuffer, metalLayer: renderLayer)
  929. }
  930. @objc(dispose)
  931. public func dispose() {
  932. fallbackRenderer.dispose()
  933. renderLayer.contents = nil
  934. }
  935. @objc(updateBackingSize)
  936. public func updateBackingSize() {
  937. renderLayer.frame = bounds
  938. }
  939. }