mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Animation rendering updates
This commit is contained in:
parent
c8bc4b7f12
commit
05a0d399dd
6 changed files with 228 additions and 217 deletions
|
|
@ -172,7 +172,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||
private var cachedData: (Data, Bool, EmojiFitzModifier?)?
|
||||
|
||||
private let useMetalCache: Bool
|
||||
private var renderer: (AnimationRenderer & ASDisplayNode)?
|
||||
private var renderer: AnimationRendererPool.Holder?
|
||||
|
||||
public var isPlaying: Bool = false
|
||||
private var currentLoopCount: Int = 0
|
||||
|
|
@ -232,30 +232,42 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||
self.timer.swap(nil)?.invalidate()
|
||||
}
|
||||
|
||||
private static let hardwareRendererPool = AnimationRendererPool(generate: {
|
||||
if #available(iOS 10.0, *) {
|
||||
return CompressedAnimationRenderer()
|
||||
} else {
|
||||
return SoftwareAnimationRenderer()
|
||||
}
|
||||
})
|
||||
|
||||
private static let softwareRendererPool = AnimationRendererPool(generate: {
|
||||
return SoftwareAnimationRenderer()
|
||||
})
|
||||
|
||||
private weak var nodeToCopyFrameFrom: AnimatedStickerNode?
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
if #available(iOS 10.0, *), self.useMetalCache {
|
||||
self.renderer = CompressedAnimationRenderer()
|
||||
self.renderer = AnimatedStickerNode.hardwareRendererPool.take()
|
||||
} else {
|
||||
self.renderer = SoftwareAnimationRenderer()
|
||||
self.renderer = AnimatedStickerNode.softwareRendererPool.take()
|
||||
if let contents = self.nodeToCopyFrameFrom?.renderer?.renderer.contents {
|
||||
self.renderer?.renderer.contents = contents
|
||||
}
|
||||
}
|
||||
|
||||
self.renderer?.frame = CGRect(origin: CGPoint(), size: self.size ?? self.bounds.size)
|
||||
if let contents = self.nodeToCopyFrameFrom?.renderer?.contents {
|
||||
self.renderer?.contents = contents
|
||||
}
|
||||
self.renderer?.renderer.frame = CGRect(origin: CGPoint(), size: self.size ?? self.bounds.size)
|
||||
if let (overlayColor, replace) = self.overlayColor {
|
||||
self.renderer?.setOverlayColor(overlayColor, replace: replace, animated: false)
|
||||
self.renderer?.renderer.setOverlayColor(overlayColor, replace: replace, animated: false)
|
||||
}
|
||||
self.nodeToCopyFrameFrom = nil
|
||||
self.addSubnode(self.renderer!)
|
||||
self.addSubnode(self.renderer!.renderer)
|
||||
}
|
||||
|
||||
public func cloneCurrentFrame(from otherNode: AnimatedStickerNode?) {
|
||||
if let renderer = self.renderer {
|
||||
if let contents = otherNode?.renderer?.contents {
|
||||
if let renderer = self.renderer?.renderer as? SoftwareAnimationRenderer, let otherRenderer = otherNode?.renderer?.renderer as? SoftwareAnimationRenderer {
|
||||
if let contents = otherRenderer.contents {
|
||||
renderer.contents = contents
|
||||
}
|
||||
} else {
|
||||
|
|
@ -428,7 +440,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||
return
|
||||
}
|
||||
|
||||
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||
strongSelf.renderer?.renderer.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -532,7 +544,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||
return
|
||||
}
|
||||
|
||||
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||
strongSelf.renderer?.renderer.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -685,7 +697,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||
return
|
||||
}
|
||||
|
||||
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||
strongSelf.renderer?.renderer.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -715,11 +727,11 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||
|
||||
public func updateLayout(size: CGSize) {
|
||||
self.size = size
|
||||
self.renderer?.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.renderer?.renderer.frame = CGRect(origin: CGPoint(), size: size)
|
||||
}
|
||||
|
||||
public func setOverlayColor(_ color: UIColor?, replace: Bool, animated: Bool) {
|
||||
self.overlayColor = (color, replace)
|
||||
self.renderer?.setOverlayColor(color, replace: replace, animated: animated)
|
||||
self.renderer?.renderer.setOverlayColor(color, replace: replace, animated: animated)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,47 @@ public enum AnimationRendererFrameType {
|
|||
case dct
|
||||
}
|
||||
|
||||
protocol AnimationRenderer {
|
||||
final class AnimationRendererPool {
|
||||
final class Holder {
|
||||
let pool: AnimationRendererPool
|
||||
let renderer: AnimationRenderer
|
||||
|
||||
init(pool: AnimationRendererPool, renderer: AnimationRenderer) {
|
||||
self.pool = pool
|
||||
self.renderer = renderer
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.renderer.removeFromSupernode()
|
||||
self.pool.putBack(renderer: self.renderer)
|
||||
}
|
||||
}
|
||||
|
||||
private let generate: () -> AnimationRenderer
|
||||
|
||||
private var items: [AnimationRenderer] = []
|
||||
|
||||
init(generate: @escaping () -> AnimationRenderer) {
|
||||
self.generate = generate
|
||||
}
|
||||
|
||||
func take() -> Holder {
|
||||
if !self.items.isEmpty {
|
||||
let item = self.items.removeLast()
|
||||
return Holder(pool: self, renderer: item)
|
||||
} else {
|
||||
return Holder(pool: self, renderer: self.generate())
|
||||
}
|
||||
}
|
||||
|
||||
private func putBack(renderer: AnimationRenderer) {
|
||||
#if DEBUG
|
||||
self.items.append(renderer)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
protocol AnimationRenderer: ASDisplayNode {
|
||||
func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, mulAlpha: Bool, completion: @escaping () -> Void)
|
||||
|
||||
func setOverlayColor(_ color: UIColor?, replace: Bool, animated: Bool)
|
||||
|
|
|
|||
|
|
@ -88,66 +88,6 @@ final class CompressedAnimationRenderer: ASDisplayNode, AnimationRenderer {
|
|||
case .yuva:
|
||||
self.renderer.renderYuva(metalLayer: self.layer, width: width, height: height, data: data, completion: completion)
|
||||
}
|
||||
|
||||
/*assert(bytesPerRow > 0)
|
||||
queue.async { [weak self] in
|
||||
switch type {
|
||||
case .dct:
|
||||
break
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
var image: UIImage?
|
||||
|
||||
autoreleasepool {
|
||||
image = generateImagePixel(CGSize(width: CGFloat(width), height: CGFloat(height)), scale: 1.0, pixelGenerator: { _, pixelData, contextBytesPerRow in
|
||||
switch type {
|
||||
case .yuva:
|
||||
data.withUnsafeBytes { bytes -> Void in
|
||||
guard let baseAddress = bytes.baseAddress else {
|
||||
return
|
||||
}
|
||||
if bytesPerRow <= 0 || height <= 0 || width <= 0 || bytesPerRow * height > bytes.count {
|
||||
assert(false)
|
||||
return
|
||||
}
|
||||
decodeYUVAToRGBA(baseAddress.assumingMemoryBound(to: UInt8.self), pixelData, Int32(width), Int32(height), Int32(contextBytesPerRow))
|
||||
}
|
||||
case .argb:
|
||||
var data = data
|
||||
data.withUnsafeMutableBytes { bytes -> Void in
|
||||
guard let baseAddress = bytes.baseAddress else {
|
||||
return
|
||||
}
|
||||
if mulAlpha {
|
||||
var srcData = vImage_Buffer(data: baseAddress.assumingMemoryBound(to: UInt8.self), height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow)
|
||||
var destData = vImage_Buffer(data: pixelData, height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow)
|
||||
|
||||
let permuteMap: [UInt8] = [3, 2, 1, 0]
|
||||
vImagePermuteChannels_ARGB8888(&srcData, &destData, permuteMap, vImage_Flags(kvImageDoNotTile))
|
||||
vImagePremultiplyData_ARGB8888(&destData, &destData, vImage_Flags(kvImageDoNotTile))
|
||||
vImagePermuteChannels_ARGB8888(&destData, &destData, permuteMap, vImage_Flags(kvImageDoNotTile))
|
||||
} else {
|
||||
memcpy(pixelData, baseAddress.assumingMemoryBound(to: UInt8.self), bytes.count)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Queue.mainQueue().async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.contents = image?.cgImage
|
||||
strongSelf.updateHighlightedContentNode()
|
||||
if strongSelf.highlightedContentNode?.frame != strongSelf.bounds {
|
||||
strongSelf.highlightedContentNode?.frame = strongSelf.bounds
|
||||
}
|
||||
completion()
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private func updateHighlightedContentNode() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue