Split akgl_render_bind2d out of akgl_render_init2d

A host that owns its own window -- an embedded interpreter, which must not
create one -- wants the six 2D function pointers without the window, the
camera and the property registry that came with them. Until now the only
options were to let libakgl own the window or to assign the vtable by hand.

akgl_render_bind2d() installs the methods and nothing else, deliberately
leaving self->sdl_renderer alone so a caller's own renderer survives it and
a caller without one gets a backend that reports AKERR_NULLPOINTER rather
than crashing. akgl_render_init2d() calls it once its window exists.

tests/renderer.c is new and needs no display: the binding, frame start and
end, both draw_texture paths and the draw_mesh stub against a software
renderer under the dummy video driver. src/renderer.c goes from 10% line
coverage to 56%.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 12:51:58 -04:00
parent 18399f2726
commit ede3452c49
4 changed files with 264 additions and 2 deletions

View File

@@ -43,6 +43,18 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_render_init2d(akgl_RenderBackend *self)
camera->w = screenwidth;
camera->h = screenheight;
PASS(e, akgl_render_bind2d(self));
SUCCEED_RETURN(e);
}
akerr_ErrorContext AKERR_NOIGNORE *akgl_render_bind2d(akgl_RenderBackend *self)
{
PREPARE_ERROR(e);
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
// Deliberately does not touch self->sdl_renderer: a host that owns its own
// window has already put one there, and this is the only way it gets a
// usable backend without libakgl creating a second window.
self->shutdown = &akgl_render_2d_shutdown;
self->frame_start = &akgl_render_2d_frame_start;
self->frame_end = &akgl_render_2d_frame_end;