ffi 3.2 C5: migrate uikit.sx view tree + GL drawables cluster
Final Phase 3.2 cluster. CALayer / CAEAGLLayer / EAGLContext declared
as `#foreign #objc_class` blocks, plus `setContentScaleFactor` added
to UIView and `-layer` now returns `*CALayer` (was opaque `*void`).
Classes declared:
- CALayer → setOpaque (instance)
- CAEAGLLayer → setDrawableProperties (instance)
- EAGLContext → alloc (class), initWithAPI (instance),
setCurrentContext (class — takes EAGLContext arg),
renderbufferStorage_fromDrawable (instance),
presentRenderbuffer (instance)
- UIView → +setContentScaleFactor (existing decl extended)
The C5 group sits above UIView in the file so the `-layer` return type
`*CALayer` forward-resolves cleanly.
Migration sites in uikit.sx:
- `uikit_create_gl_context` → `EAGLContext.alloc().initWithAPI(api)`
+ `EAGLContext.setCurrentContext(ctx)`.
- `uikit_setup_renderbuffer` → cast `*EAGLContext` and
`gl_ctx.renderbufferStorage_fromDrawable(target, layer)`.
- `uikit_present_renderbuffer` → same cast + `presentRenderbuffer(target)`.
- Scene-connect bring-up: `gl_layer.setOpaque(1)`,
`eagl_layer.setDrawableProperties(...)`,
`gl_view.setContentScaleFactor(scale)`.
One more `objc_getClass(...)` lookup (EAGLContext) retired — the class
slot comes from the declarative binding via `__sx_objc_class_init`.
**Phase 3.2 complete.** Five clusters migrated (C1: Foundation
utility; C2: Notifications + Bundle; C3: RunLoop + display timing;
C4: UIKit chrome; C5: view tree + GL drawables). 8 foreign Cocoa
classes declared; ~30 `#objc_call(T)(...)` sites rewritten to
`recv.method(args)` / `Cls.method(args)`; 6 `objc_getClass`
lookups retired. Sx-defined classes (SxAppDelegate, SxSceneDelegate,
SxGLView, SxMetalView) and a handful of foreign sites that exercise
delegate/protocol surfaces stay on the explicit `#objc_call` form
pending Phase 3.7's class synthesis.
167/167 example tests; chess clean on macOS / iOS sim / Android via
`tools/verify-step.sh`.
This commit is contained in:
@@ -113,6 +113,25 @@ CADisplayLink :: #foreign #objc_class("CADisplayLink") {
|
||||
duration :: (self: *Self) -> f64;
|
||||
}
|
||||
|
||||
// ── View tree + GL drawables (Phase 3.2 C5) ────────────────────────────
|
||||
// (Declared before UIView so `layer :: (...) -> *CALayer` can reference it.)
|
||||
|
||||
CALayer :: #foreign #objc_class("CALayer") {
|
||||
setOpaque :: (self: *Self, opaque: s8);
|
||||
}
|
||||
|
||||
CAEAGLLayer :: #foreign #objc_class("CAEAGLLayer") {
|
||||
setDrawableProperties :: (self: *Self, props: *void);
|
||||
}
|
||||
|
||||
EAGLContext :: #foreign #objc_class("EAGLContext") {
|
||||
alloc :: () -> *EAGLContext;
|
||||
initWithAPI :: (self: *Self, api: s32) -> *EAGLContext;
|
||||
setCurrentContext :: (ctx: *EAGLContext);
|
||||
renderbufferStorage_fromDrawable :: (self: *Self, target: u32, drawable: *void) -> s8;
|
||||
presentRenderbuffer :: (self: *Self, target: u32) -> s8;
|
||||
}
|
||||
|
||||
// ── UIKit chrome (Phase 3.2 C4) ────────────────────────────────────────
|
||||
|
||||
UIScreen :: #foreign #objc_class("UIScreen") {
|
||||
@@ -122,11 +141,10 @@ UIScreen :: #foreign #objc_class("UIScreen") {
|
||||
}
|
||||
|
||||
UIView :: #foreign #objc_class("UIView") {
|
||||
safeAreaInsets :: (self: *Self) -> UIEdgeInsets;
|
||||
addSubview :: (self: *Self, view: *void);
|
||||
// `-layer` returns a CALayer*; declared as opaque pointer for now
|
||||
// (CALayer's own declarative binding is in the C5 cluster).
|
||||
layer :: (self: *Self) -> *void;
|
||||
safeAreaInsets :: (self: *Self) -> UIEdgeInsets;
|
||||
addSubview :: (self: *Self, view: *void);
|
||||
layer :: (self: *Self) -> *CALayer;
|
||||
setContentScaleFactor :: (self: *Self, scale: f64);
|
||||
}
|
||||
|
||||
UIWindow :: #foreign #objc_class("UIWindow") {
|
||||
@@ -526,17 +544,14 @@ uikit_keyboard_will_change_frame :: (self: *void, _cmd: *void, notification: *vo
|
||||
uikit_create_gl_context :: (plat: *UIKitPlatform) {
|
||||
inline if OS != .ios { return; }
|
||||
|
||||
EAGLContext := objc_getClass("EAGLContext".ptr);
|
||||
// UIScreen class slot comes from the declarative #objc_class binding.
|
||||
|
||||
// Read the screen scale up-front so callers can size font caches and
|
||||
// textures with the right DPI before the window even exists.
|
||||
screen := UIScreen.mainScreen();
|
||||
plat.dpi_scale = xx screen.nativeScale();
|
||||
|
||||
ctx_raw := #objc_call(*void)(EAGLContext, "alloc");
|
||||
plat.gl_ctx = #objc_call(*void)(ctx_raw, "initWithAPI:", EAGL_API_GLES3);
|
||||
#objc_call(void)(EAGLContext, "setCurrentContext:", plat.gl_ctx);
|
||||
ctx := EAGLContext.alloc().initWithAPI(EAGL_API_GLES3);
|
||||
plat.gl_ctx = xx ctx;
|
||||
EAGLContext.setCurrentContext(ctx);
|
||||
|
||||
load_gl(@ios_gl_proc);
|
||||
}
|
||||
@@ -611,12 +626,13 @@ uikit_scene_will_connect_ios :: (delegate: *void, scene: *void) {
|
||||
win.setRootViewController(plat.root_vc);
|
||||
|
||||
gl_view : *UIView = xx plat.gl_view;
|
||||
plat.gl_layer = gl_view.layer();
|
||||
gl_layer := gl_view.layer();
|
||||
plat.gl_layer = xx gl_layer;
|
||||
|
||||
// Mark the layer opaque (no compositor blend). Required for EAGL +
|
||||
// recommended for Metal (CAMetalLayer.opaque defaults to YES but doesn't
|
||||
// hurt to be explicit).
|
||||
#objc_call(void)(plat.gl_layer, "setOpaque:", xx 1);
|
||||
gl_layer.setOpaque(1);
|
||||
|
||||
if plat.gpu_mode == .gles {
|
||||
// EAGL drawable properties dict required by
|
||||
@@ -634,7 +650,8 @@ uikit_scene_will_connect_ios :: (delegate: *void, scene: *void) {
|
||||
dict := NSMutableDictionary.dictionary();
|
||||
dict.setObject_forKey(xx ns_no, retained_key);
|
||||
dict.setObject_forKey(rgba8_value, colorformat_key);
|
||||
#objc_call(void)(plat.gl_layer, "setDrawableProperties:", xx dict);
|
||||
eagl_layer : *CAEAGLLayer = xx gl_layer;
|
||||
eagl_layer.setDrawableProperties(xx dict);
|
||||
}
|
||||
|
||||
// EAGLContext + load_gl were already done in uikit_create_gl_context()
|
||||
@@ -647,7 +664,7 @@ uikit_scene_will_connect_ios :: (delegate: *void, scene: *void) {
|
||||
screen2 := win.screen();
|
||||
scale := screen2.nativeScale();
|
||||
plat.dpi_scale = xx scale;
|
||||
#objc_call(void)(plat.gl_view, "setContentScaleFactor:", scale);
|
||||
gl_view.setContentScaleFactor(scale);
|
||||
|
||||
// Renderbuffer is allocated lazily in -[SxGLView layoutSubviews] once
|
||||
// the layer has its real on-screen bounds. makeKeyAndVisible triggers
|
||||
@@ -691,7 +708,8 @@ uikit_setup_renderbuffer :: (plat: *UIKitPlatform) {
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, plat.color_renderbuffer);
|
||||
|
||||
#objc_call(bool)(plat.gl_ctx, "renderbufferStorage:fromDrawable:", GL_RENDERBUFFER, plat.gl_layer);
|
||||
gl_ctx : *EAGLContext = xx plat.gl_ctx;
|
||||
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);
|
||||
@@ -723,7 +741,8 @@ uikit_setup_renderbuffer :: (plat: *UIKitPlatform) {
|
||||
uikit_present_renderbuffer :: (self: *UIKitPlatform) {
|
||||
inline if OS != .ios { return; }
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, self.color_renderbuffer);
|
||||
#objc_call(bool)(self.gl_ctx, "presentRenderbuffer:", GL_RENDERBUFFER);
|
||||
gl_ctx : *EAGLContext = xx self.gl_ctx;
|
||||
gl_ctx.presentRenderbuffer(GL_RENDERBUFFER);
|
||||
}
|
||||
|
||||
// ── SxGLView class ─────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user