Skip to content

Commit 9d6c6eb

Browse files
committed
Add AndroidLooper, AndroidChoreographer, and AndroidSystem targets
1 parent 95b2534 commit 9d6c6eb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+10053
-16
lines changed

Package.swift

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,55 @@ let package = Package(
55
name: "swift-android-native",
66
products: [
77
.library(name: "AndroidNative", targets: ["AndroidNative"]),
8-
.library(name: "AndroidLogging", targets: ["AndroidLogging"])
8+
.library(name: "AndroidLogging", targets: ["AndroidLogging"]),
9+
.library(name: "AndroidLooper", targets: ["AndroidLooper"]),
10+
.library(name: "AndroidChoreographer", targets: ["AndroidLooper"]),
11+
],
12+
dependencies: [
913
],
1014
targets: [
11-
.systemLibrary(name: "AndroidNDK"),
12-
.target(name: "AndroidLogging", dependencies: [.target(name: "AndroidNDK", condition: .when(platforms: [.android]))]),
13-
.testTarget(name: "AndroidLoggingTests", dependencies: ["AndroidLogging"]),
14-
.target(name: "AndroidNative", dependencies: ["AndroidLogging"]),
15-
.testTarget(name: "AndroidNativeTests", dependencies: ["AndroidNative"]),
15+
.target(name: "AndroidNDK", linkerSettings: [
16+
.linkedLibrary("android", .when(platforms: [.android])),
17+
.linkedLibrary("log", .when(platforms: [.android])),
18+
]),
19+
.target(name: "ConcurrencyRuntimeC"),
20+
.target(name: "AndroidSystem", dependencies: [
21+
.target(name: "AndroidNDK", condition: .when(platforms: [.android]))
22+
], swiftSettings: [
23+
.define("SYSTEM_PACKAGE_DARWIN", .when(platforms: [.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .visionOS])),
24+
.define("SYSTEM_PACKAGE"),
25+
]),
26+
.testTarget(name: "AndroidSystemTests", dependencies: [
27+
"AndroidSystem",
28+
]),
29+
.target(name: "AndroidLogging", dependencies: [
30+
.target(name: "AndroidNDK", condition: .when(platforms: [.android])),
31+
]),
32+
.testTarget(name: "AndroidLoggingTests", dependencies: [
33+
"AndroidLogging",
34+
]),
35+
.target(name: "AndroidLooper", dependencies: [
36+
"AndroidSystem",
37+
"AndroidLogging",
38+
"ConcurrencyRuntimeC",
39+
]),
40+
.testTarget(name: "AndroidLooperTests", dependencies: [
41+
"AndroidLooper",
42+
]),
43+
.target(name: "AndroidChoreographer", dependencies: [
44+
"AndroidSystem",
45+
"AndroidLogging",
46+
]),
47+
.testTarget(name: "AndroidChoreographerTests", dependencies: [
48+
"AndroidChoreographer",
49+
]),
50+
.target(name: "AndroidNative", dependencies: [
51+
"AndroidLogging",
52+
"AndroidLooper",
53+
"AndroidChoreographer",
54+
]),
55+
.testTarget(name: "AndroidNativeTests", dependencies: [
56+
"AndroidNative",
57+
]),
1658
]
1759
)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#if os(Android)
2+
import Android
3+
import AndroidNDK
4+
import AndroidLogging
5+
6+
let logger = Logger(subsystem: "AndroidChoreographer", category: "AndroidChoreographer")
7+
8+
public final class AndroidChoreographer : @unchecked Sendable {
9+
private let _choreographer: OpaquePointer
10+
11+
/// Get the AChoreographer instance for the main thread.
12+
///
13+
/// Must be initialized at startup time with `setupMainChoreographer()`
14+
public private(set) static var main: AndroidChoreographer!
15+
16+
/// Get the AChoreographer instance for the current thread.
17+
///
18+
/// This must be called on an ALooper thread.
19+
public static var current: AndroidChoreographer {
20+
AndroidChoreographer(choreographer: AChoreographer_getInstance())
21+
}
22+
23+
init(choreographer: OpaquePointer) {
24+
self._choreographer = choreographer
25+
}
26+
27+
/// Add a callback to the Choreographer to invoke `_dispatch_main_queue_callback_4CF` on each frame to drain the main queue
28+
public static func setupMainChoreographer() {
29+
if Self.main == nil {
30+
logger.info("setupMainQueue")
31+
Self.main = AndroidChoreographer.current
32+
//enqueueMainChoreographer()
33+
}
34+
}
35+
36+
// public func postFrameCallback(_ callback: @convention(c)(Int64, UnsafeMutableRawPointer?) -> ()) {
37+
// AChoreographer_postFrameCallback64(_choreographer, callback, nil)
38+
// }
39+
}
40+
41+
// no longer used: we use the AndroidLooper instead, which will be more efficient than trying to drain the main queue on every frame render
42+
43+
//private func enqueueMainChoreographer() {
44+
// AndroidChoreographer.current.postFrameCallback(choreographerCallback)
45+
//}
46+
//
47+
//// C-compatible callback wrapper
48+
//private var choreographerCallback: AChoreographer_frameCallback64 = { _, _ in
49+
// // Drain the main queue
50+
// _dispatch_main_queue_callback_4CF()
51+
//
52+
// // AChoreographer_postFrameCallback64 is single-shot, so we need to re-enqueue the callback each frame
53+
// enqueueMainChoreographer()
54+
//}
55+
//
56+
//// https://github.com/apple-oss-distributions/libdispatch/blob/bd82a60ee6a73b4eca50af028b48643d51aaf1ea/src/queue.c#L8237
57+
//// https://forums.swift.org/t/main-dispatch-queue-in-linux-sdl-app/31708/3
58+
//@_silgen_name("_dispatch_main_queue_callback_4CF")
59+
//func _dispatch_main_queue_callback_4CF()
60+
61+
#endif

0 commit comments

Comments
 (0)