Remove bj_renderer from the public API #114

Closed
opened 2026-05-29 08:51:04 +02:00 by OragonEfreet · 0 comments
Owner

After #107 (draw-callback model) removed bj_get_framebuffer and bj_present, the bj_renderer type's user-facing role collapsed to exactly four lines of ceremony every program has to repeat:

bj_renderer* renderer = bj_create_renderer(BJ_RENDERER_TYPE_SOFTWARE, 0);
bj_renderer_configure(renderer, window, 0);
/* ... user never touches `renderer` between these lines ... */
bj_destroy_renderer(renderer);

A grep across examples/ confirms zero examples touch the renderer between configure and destroy. Banjo also only has one renderer type (BJ_RENDERER_TYPE_SOFTWARE); the enum exists for forward compatibility with GL/Vulkan that hasn't shipped and isn't currently scheduled. Today the abstraction is pure tax.

The draw callback already receives an opaque bj_render_target. That stays — it's the right shape for handing a renderable surface to user code without committing to "this is a CPU bitmap." The renderer object itself adds no value on top of it.

Outcome

Public API removals:

  • bj_create_renderer
  • bj_destroy_renderer
  • bj_renderer_configure
  • enum bj_renderer_type (and BJ_RENDERER_TYPE_SOFTWARE)
  • struct bj_renderer (kept internal as a private framebuffer holder)
  • inc/banjo/renderer.h deleted; the remaining surface (bj_render_target, bj_render_target_bitmap) moves to inc/banjo/window.h

New behaviour:

  • bj_bind_window(title, x, y, w, h, flags, err) allocates the software framebuffer at window creation time — the user has nothing else to do before registering a draw callback.
  • bj_unbind_window(window) releases it.
  • The fire helper (bj_window_fire_draw_callback) reads the framebuffer directly from window->framebuffer instead of going through window->bound_renderer.

Per-backend refactor (all five real backends + fake):

  • The current *_renderer_configure / *_create_renderer / *_destroy_renderer functions fold into the existing create_window / delete_window paths.
  • A new internal create_framebuffer(window, err) or similar layer op may help keep window creation focused while still picking up the backend-specific framebuffer setup (X11 XImage, Wayland shm buffer, Win32 HDC/HBITMAP, Cocoa buffer, Emscripten canvas).

Migration

Examples: 18 files, each loses the 4-line renderer dance plus the bj_renderer* renderer = 0; declaration. ~90 lines net deletion across the example tree.

Tutorials in headers: start.c, pong.c, drawing_2d.c, load_bmp.c (and any other paired tutorial blocks) need their walkthroughs updated to reflect the simpler init sequence.

Tests: unit_draw_callback's fixture currently creates a renderer; it switches to plain bj_bind_window.

Forward compatibility with GL/Vk

When (if) GL/Vk arrives, options on the table:

  • Window creation flag: bj_bind_window(... flags=BJ_WINDOW_FLAG_GL ...).
  • Separate bind function: bj_bind_window_gl(...).
  • Reintroduce the renderer object for the multi-renderer case only.

That's a real design decision then, not now. Today's removal doesn't lock anything in — bj_render_target is still an opaque type whose backing can be any future kind.

Acceptance criteria

  • nm libbanjo.a shows no bj_create_renderer / bj_destroy_renderer / bj_renderer_configure symbols.
  • grep -r bj_renderer inc/ returns nothing public-facing.
  • All 18 examples migrated; wc -l examples/*.c drops by ~90 lines net.
  • ctest 30/30 (no test relies on the removed API).
  • Linux + mingw + Emscripten builds clean. Cocoa builds clean on macOS.
  • Doxygen clean (renderer.h removed; references in other headers re-target).

Out of scope

  • GL/Vk renderer (out, separate card whenever that lands).
  • A "pixel mode accessor" (was a follow-up of #107 — would become bj_window_pixel_mode(window) after this card; reference but don't bundle).
  • Inlining draw(state, bitmap) helpers into on_draw in the examples — separate small cleanup card, possibly bundle with this if the touch overlaps.

Depends on

  • #107 (draw-callback model) — merged, makes this possible.
  • Independent of frame-pacing work (#108). Either can land first.
After #107 (draw-callback model) removed `bj_get_framebuffer` and `bj_present`, the `bj_renderer` type's user-facing role collapsed to exactly four lines of ceremony every program has to repeat: ```c bj_renderer* renderer = bj_create_renderer(BJ_RENDERER_TYPE_SOFTWARE, 0); bj_renderer_configure(renderer, window, 0); /* ... user never touches `renderer` between these lines ... */ bj_destroy_renderer(renderer); ``` A grep across `examples/` confirms zero examples touch the renderer between configure and destroy. Banjo also only has one renderer type (`BJ_RENDERER_TYPE_SOFTWARE`); the enum exists for forward compatibility with GL/Vulkan that hasn't shipped and isn't currently scheduled. Today the abstraction is pure tax. The draw callback already receives an opaque `bj_render_target`. That stays — it's the right shape for handing a renderable surface to user code without committing to "this is a CPU bitmap." The renderer object itself adds no value on top of it. ## Outcome **Public API removals:** - `bj_create_renderer` - `bj_destroy_renderer` - `bj_renderer_configure` - `enum bj_renderer_type` (and `BJ_RENDERER_TYPE_SOFTWARE`) - `struct bj_renderer` (kept internal as a private framebuffer holder) - `inc/banjo/renderer.h` deleted; the remaining surface (`bj_render_target`, `bj_render_target_bitmap`) moves to `inc/banjo/window.h` **New behaviour:** - `bj_bind_window(title, x, y, w, h, flags, err)` allocates the software framebuffer at window creation time — the user has nothing else to do before registering a draw callback. - `bj_unbind_window(window)` releases it. - The fire helper (`bj_window_fire_draw_callback`) reads the framebuffer directly from `window->framebuffer` instead of going through `window->bound_renderer`. **Per-backend refactor** (all five real backends + fake): - The current `*_renderer_configure` / `*_create_renderer` / `*_destroy_renderer` functions fold into the existing `create_window` / `delete_window` paths. - A new internal `create_framebuffer(window, err)` or similar layer op may help keep window creation focused while still picking up the backend-specific framebuffer setup (X11 XImage, Wayland shm buffer, Win32 HDC/HBITMAP, Cocoa buffer, Emscripten canvas). ## Migration **Examples**: 18 files, each loses the 4-line renderer dance plus the `bj_renderer* renderer = 0;` declaration. ~90 lines net deletion across the example tree. **Tutorials in headers**: `start.c`, `pong.c`, `drawing_2d.c`, `load_bmp.c` (and any other paired tutorial blocks) need their walkthroughs updated to reflect the simpler init sequence. **Tests**: `unit_draw_callback`'s fixture currently creates a renderer; it switches to plain `bj_bind_window`. ## Forward compatibility with GL/Vk When (if) GL/Vk arrives, options on the table: - Window creation flag: `bj_bind_window(... flags=BJ_WINDOW_FLAG_GL ...)`. - Separate bind function: `bj_bind_window_gl(...)`. - Reintroduce the renderer object for the multi-renderer case only. That's a real design decision *then*, not now. Today's removal doesn't lock anything in — `bj_render_target` is still an opaque type whose backing can be any future kind. ## Acceptance criteria - `nm libbanjo.a` shows no `bj_create_renderer` / `bj_destroy_renderer` / `bj_renderer_configure` symbols. - `grep -r bj_renderer inc/` returns nothing public-facing. - All 18 examples migrated; `wc -l examples/*.c` drops by ~90 lines net. - ctest 30/30 (no test relies on the removed API). - Linux + mingw + Emscripten builds clean. Cocoa builds clean on macOS. - Doxygen clean (`renderer.h` removed; references in other headers re-target). ## Out of scope - GL/Vk renderer (out, separate card whenever that lands). - A "pixel mode accessor" (was a follow-up of #107 — would become `bj_window_pixel_mode(window)` after this card; reference but don't bundle). - Inlining `draw(state, bitmap)` helpers into `on_draw` in the examples — separate small cleanup card, possibly bundle with this if the touch overlaps. ## Depends on - #107 (draw-callback model) — merged, makes this possible. - Independent of frame-pacing work (#108). Either can land first.
OragonEfreet added this to the 1.0 milestone 2026-05-29 08:51:04 +02:00
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
OragonEfreet/banjo#114
No description provided.