API Design
/* A render view = one PVR2 scene submission cycle. */
typedef struct {
int priority; /* Lower = rendered first */
int enabled; /* 0 = skip this frame */
char name[16]; /* Debug label */
/* What to render */
void *stage; /* Game-defined stage pointer (scene data) */
/* Camera */
sh_mat4_t view_matrix;
sh_mat4_t proj_matrix;
float near_z, far_z;
/* Viewport (screen region) */
int vp_x, vp_y;
int vp_w, vp_h;
/* Callbacks */
void (*submit)(struct sh_view *view); /* Called during render to submit geometry */
} sh_view_t;
/* Compositor manages ordered views. */
typedef struct {
sh_view_t *views[8]; /* Max 8 views */
int view_count;
int frame_count; /* Running frame counter */
} sh_compositor_t;
/* Initialize compositor. */
void sh_compositor_init(sh_compositor_t *comp);
/* Add a view. Returns view index. */
int sh_compositor_add_view(sh_compositor_t *comp, sh_view_t *view);
/* Remove a view by index. */
void sh_compositor_remove_view(sh_compositor_t *comp, int index);
/* Execute one frame. Sorts views by priority, calls submit() for each.
Wraps pvr_scene_begin() / pvr_scene_finish(). */
void sh_compositor_render(sh_compositor_t *comp);
/* --- Typical frame --- */
/*
* sh_compositor_render() does:
* 1. Sort views by priority
* 2. pvr_wait_ready()
* 3. pvr_scene_begin()
* 4. For each enabled view:
* a. Set viewport (pvr_set_bg_color or scissor)
* b. Load view/proj matrices to XMTRX
* c. Call view->submit(view)
* (game code submits pvr_poly_hdr + vertices per material)
* 5. pvr_scene_finish()
* 6. comp->frame_count++
*
* VMU rendering happens OUTSIDE the PVR2 scene cycle — it's Maple bus,
* not PVR2. Games call sh_vmu_present() whenever they want.
*/