ffi 1.33: uikit.sx final sweep — Phase 1D for uikit.sx complete

Six remaining dispatch clusters migrated in one pass:
- `uikit_setup_renderbuffer`: `renderbufferStorage:fromDrawable:` (BOOL).
- `uikit_present_renderbuffer`: `presentRenderbuffer:` (BOOL, every frame).
- `uikit_gl_view_tick`: `targetTimestamp` and `duration` reads (f64,
  every frame — three call sites total across the keyboard-anim path
  and the frame-closure path).
- `uikit_compute_layer_pixel_size`: `bounds` (CGRect HFA).
- `uikit_touch_location`: `locationInView:` (CGPoint HFA — first
  standalone `#objc_call(CGPoint)` exercise, structurally identical to
  the 2×f64 NSPoint already verified by ffi-objc-call-05).
- `uikit_first_touch`: `anyObject` (*void).

Net -15 lines. uikit.sx is now 839 lines — Phase 1D started at 937,
so this is -98 cumulative across the migration. Zero `xx objc_msgSend`
typed casts left in the file.

iOS-sim chess regression smoke: launched chess, tapped a black pawn
through the Simulator window, watched the move (d7→d5) play, then a
second tap played d5→d4. The render loop, touch handlers, layout
math, and the BOOL-returning EAGL presentation calls are all on the
exercised path, so this is the strongest runtime verification any
Phase 1D commit has had so far.

22 `sel_registerName` calls remain in the file, all legitimate:
- `class_addMethod` IMP registrations (runtime class build-out).
- SEL-as-arg to dispatch selectors that take a SEL value
  (`addObserver:selector:name:object:`,
  `displayLinkWithTarget:selector:`). A future `#objc_selector("foo")`
  literal would replace these, but it's not part of Phase 1.
This commit is contained in:
agra
2026-05-19 21:06:53 +03:00
parent e1d300c661
commit 56f6ae3681

View File

@@ -590,9 +590,7 @@ uikit_setup_renderbuffer :: (plat: *UIKitPlatform) {
glBindRenderbuffer(GL_RENDERBUFFER, plat.color_renderbuffer);
sel_renderbuffer_storage := sel_registerName("renderbufferStorage:fromDrawable:".ptr);
msg_o_u32_o : (*void, *void, u32, *void) -> u8 = xx objc_msgSend;
msg_o_u32_o(plat.gl_ctx, sel_renderbuffer_storage, GL_RENDERBUFFER, plat.gl_layer);
#objc_call(bool)(plat.gl_ctx, "renderbufferStorage:fromDrawable:", GL_RENDERBUFFER, plat.gl_layer);
glBindFramebuffer(GL_FRAMEBUFFER, plat.framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, plat.color_renderbuffer);
@@ -624,9 +622,7 @@ uikit_setup_renderbuffer :: (plat: *UIKitPlatform) {
uikit_present_renderbuffer :: (self: *UIKitPlatform) {
inline if OS != .ios { return; }
glBindRenderbuffer(GL_RENDERBUFFER, self.color_renderbuffer);
sel_present := sel_registerName("presentRenderbuffer:".ptr);
msg_ou : (*void, *void, u32) -> u8 = xx objc_msgSend;
msg_ou(self.gl_ctx, sel_present, GL_RENDERBUFFER);
#objc_call(bool)(self.gl_ctx, "presentRenderbuffer:", GL_RENDERBUFFER);
}
// ── SxGLView class ─────────────────────────────────────────────────────────
@@ -651,9 +647,7 @@ uikit_gl_view_tick :: (self: *void, _cmd: *void, link: *void) callconv(.c) {
// and keyboardLayoutGuide — none eliminated the lag without
// cascade-breaking the GL view's frame.
if plat.kb_animating {
sel_target_ts := sel_registerName("targetTimestamp".ptr);
msg_d2 : (*void, *void) -> f64 = xx objc_msgSend;
target_ts := msg_d2(link, sel_target_ts);
target_ts := #objc_call(f64)(link, "targetTimestamp");
elapsed := target_ts - plat.kb_anim_start;
// Negative elapsed can happen if the just-fired willChangeFrame
// set kb_anim_start to a wall time AFTER the tick already
@@ -680,14 +674,11 @@ uikit_gl_view_tick :: (self: *void, _cmd: *void, link: *void) callconv(.c) {
if !plat.has_frame_closure { return; }
if !plat.gl_initialized { return; }
sel_dur := sel_registerName("duration".ptr);
sel_tts := sel_registerName("targetTimestamp".ptr);
msg_d : (*void, *void) -> f64 = xx objc_msgSend;
dur_d : f64 = msg_d(link, sel_dur);
dur_d := #objc_call(f64)(link, "duration");
plat.delta_time = xx dur_d;
// Stash the targetTimestamp so begin_frame can hand it down to the
// game in FrameContext for Metal presentDrawable:atTime:.
plat.last_target_ts = msg_d(link, sel_tts);
plat.last_target_ts = #objc_call(f64)(link, "targetTimestamp");
fn := plat.frame_closure;
fn();
@@ -715,9 +706,7 @@ uikit_compute_layer_pixel_size :: (plat: *UIKitPlatform) {
inline if OS != .ios { return; }
if plat.gl_view == null { return; }
sel_bounds := sel_registerName("bounds".ptr);
msg_rect : (*void, *void) -> CGRect = xx objc_msgSend;
b := msg_rect(plat.gl_view, sel_bounds);
b := #objc_call(CGRect)(plat.gl_view, "bounds");
w_pts : f64 = b.width;
h_pts : f64 = b.height;
@@ -737,16 +726,12 @@ uikit_compute_layer_pixel_size :: (plat: *UIKitPlatform) {
// Event into the platform's queue for the next poll_events drain.
uikit_touch_location :: (touch: *void, view: *void) -> Point {
sel_location := sel_registerName("locationInView:".ptr);
msg_pt : (*void, *void, *void) -> CGPoint = xx objc_msgSend;
p := msg_pt(touch, sel_location, view);
p := #objc_call(CGPoint)(touch, "locationInView:", view);
Point.{ x = xx p.x, y = xx p.y };
}
uikit_first_touch :: (touches: *void) -> *void {
sel_any := sel_registerName("anyObject".ptr);
msg_o : (*void, *void) -> *void = xx objc_msgSend;
msg_o(touches, sel_any);
#objc_call(*void)(touches, "anyObject");
}
uikit_gl_view_touches_began :: (self: *void, _cmd: *void, touches: *void, event: *void) callconv(.c) {