-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDisplayLink.swift
More file actions
69 lines (64 loc) · 2.08 KB
/
DisplayLink.swift
File metadata and controls
69 lines (64 loc) · 2.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import Combine
public protocol DisplayLinkProtocol: AnyObject {
var frameSubject: PassthroughSubject<CFTimeInterval, Never> { get }
func activate()
var timestamp: CFTimeInterval { get }
}
#if os(macOS)
import CoreVideo
public final class DisplayLink: DisplayLinkProtocol {
public var frameSubject = PassthroughSubject<CFTimeInterval, Never>()
public private(set) var timestamp: CFTimeInterval = CFAbsoluteTimeGetCurrent()
private var link: CVDisplayLink?
public init() {}
deinit {
guard let link = link else { return }
CVDisplayLinkStop(link)
}
private var opaquePointerToSelf: UnsafeMutableRawPointer {
UnsafeMutableRawPointer(
Unmanaged
.passUnretained(self)
.toOpaque()
)
}
public func activate() {
CVDisplayLinkCreateWithActiveCGDisplays(&link)
guard let link = link else { return }
CVDisplayLinkSetOutputHandler(link) { [unowned self] link, now, outputTime, flagsIn, flagsOut in
consume(now)
return kCVReturnSuccess
}
CVDisplayLinkStart(link)
}
private func screenDidRender() {
let timestamp = timestamp
frameSubject.send(timestamp)
}
private func consume(_ now: UnsafePointer<CVTimeStamp>) {
timestamp = Double(now.pointee.hostTime) / Double(now.pointee.videoTimeScale)
screenDidRender()
}
}
#elseif os(iOS)
import QuartzCore
public final class DisplayLink: DisplayLinkProtocol {
public var frameSubject = PassthroughSubject<CFTimeInterval, Never>()
public var timestamp: CFTimeInterval { link.timestamp }
private lazy var link = makeLink()
public init() {}
deinit {
link.remove(from: .main, forMode: .common)
}
public func activate() {
link.add(to: .main, forMode: .common)
}
private func makeLink() -> CADisplayLink {
CADisplayLink(target: self, selector: #selector(screenDidRender))
}
@objc private func screenDidRender() {
let timestamp = timestamp
frameSubject.send(timestamp)
}
}
#endif