platform: UIKit backend renders GLES3 via CAEAGLLayer + CADisplayLink
End-to-end on iOS sim: UIKitPlatform boots an SxAppDelegate, installs an SxGLView (UIView subclass overriding +layerClass to return CAEAGLLayer) as the root view controller's view, sets the drawable properties (EAGLColorFormatRGBA8, non-retained backing — looked up by dlsym so pointer-identity-checked constants match), creates an EAGLContext (GLES3), and registers a CADisplayLink that invokes the user's frame closure on every vsync. end_frame presents the renderbuffer via [EAGLContext presentRenderbuffer:]. The renderbuffer is allocated lazily in -[SxGLView layoutSubviews] once the layer has its real on-screen bounds — allocating earlier (e.g. in didFinishLaunching) failed with INCOMPLETE_ATTACHMENT because the SxGLView's frame was still zero at that point. Setting the SxGLView as the VC's `view` (via setView:) lets the standard VC layout pipeline size it to the window without us having to read CGRect struct returns from objc_msgSend. EAGL drawableProperties dict keys/values are dlsym'd from OpenGLES — the framework checks them by pointer identity, so synthesized NSString literals with the same contents don't work. examples/66-uikit-platform.sx — runnable smoke test that cycles the screen color (red → green → blue every 30 frames) so you can confirm the display-link tick and present pipeline. modules/opengl.sx gains glGenFramebuffers, glGenRenderbuffers, glBindFramebuffer, glBindRenderbuffer, glFramebufferRenderbuffer, glGetRenderbufferParameteriv, glCheckFramebufferStatus — needed for the iOS GLES FBO-to-renderbuffer setup. They're wired into load_gl so SDL and the iOS dlsym loader both pick them up. Compiles cleanly on macOS / WASM / iOS-sim. Non-iOS targets never reference the unresolved UIKit/QuartzCore/OpenGLES symbols because every Obj-C touch lives inside `inline if OS == .ios`. Game's iOS path still goes through SDL3 for now. Touch events + game wire-up + keyboard observer = next steps.
This commit is contained in:
39
examples/66-uikit-platform.sx
Normal file
39
examples/66-uikit-platform.sx
Normal file
@@ -0,0 +1,39 @@
|
||||
// UIKitPlatform end-to-end smoke: boots the AppDelegate, installs an
|
||||
// SxGLView with a CAEAGLLayer + GLES3 context + CADisplayLink, and on
|
||||
// every vsync clears the screen to a cycling color.
|
||||
//
|
||||
// Build + run:
|
||||
// sx build --target ios-sim examples/66-uikit-platform.sx \
|
||||
// -o /tmp/SxUIKitBoot --bundle /tmp/SxUIKitBoot.app \
|
||||
// --bundle-id co.swipelab.sxuikit -F ~/Library/Frameworks
|
||||
// xcrun simctl install booted /tmp/SxUIKitBoot.app
|
||||
// xcrun simctl launch --console booted co.swipelab.sxuikit
|
||||
// xcrun simctl io booted screenshot /tmp/screen.png
|
||||
|
||||
#import "modules/std.sx";
|
||||
#import "modules/std/uikit.sx";
|
||||
#framework "OpenGLES";
|
||||
#framework "QuartzCore";
|
||||
#import "modules/opengl.sx";
|
||||
#import "modules/platform/uikit.sx";
|
||||
|
||||
g_frame_counter : s64 = 0;
|
||||
|
||||
cycle_frame :: () {
|
||||
fc := g_uikit_plat.begin_frame();
|
||||
g_frame_counter += 1;
|
||||
phase := g_frame_counter / 30;
|
||||
r : f32 = if (phase % 3) == 0 then 0.8 else 0.1;
|
||||
g : f32 = if (phase % 3) == 1 then 0.8 else 0.1;
|
||||
b : f32 = if (phase % 3) == 2 then 0.8 else 0.1;
|
||||
glViewport(0, 0, fc.pixel_w, fc.pixel_h);
|
||||
glClearColor(r, g, b, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
g_uikit_plat.end_frame();
|
||||
}
|
||||
|
||||
main :: () -> void {
|
||||
plat : *UIKitPlatform = xx malloc(size_of(UIKitPlatform));
|
||||
plat.init("SxUIKitPlatform", 0, 0);
|
||||
plat.run_frame_loop(closure(cycle_frame));
|
||||
}
|
||||
Reference in New Issue
Block a user