C ABI Reference¶
This page is the wrapper-facing reference for the public C headers under include/zr/.
For generated symbol docs, see API reference (Doxygen).
Public Headers¶
Primary wrapper surface:
zr_engine.h- lifecycle, poll/submit/present, metrics, caps, runtime config, debug APIszr_config.h- create/runtime config structs and validationzr_result.h- result/error modelzr_version.h- pinned versions for negotiation
Binary format headers:
zr_drawlist.h- drawlist structs/opcodeszr_event.h- packed event batch structs/types
Drawlist protocol additions:
ZR_DL_OP_DRAW_CANVAScommand payload (zr_dl_cmd_draw_canvas_t)- sub-cell selector enum (
zr_blitter_t) ZR_DL_OP_DRAW_IMAGEcommand payload (zr_dl_cmd_draw_image_t)ZR_DL_OP_BLIT_RECTcommand payload (zr_dl_cmd_blit_rect_t, drawlist v2)- drawlist v1 image numeric fields in payload:
format:0=RGBA,1=PNGprotocol:0=auto,1=kitty,2=sixel,3=iterm2fit_mode:0=fill,1=contain,2=cover
Supported drawlist versions: ZR_DRAWLIST_VERSION_V1, ZR_DRAWLIST_VERSION_V2.
Result Model¶
ZR_OKis0- failures are negative
ZR_ERR_*
Special case:
engine_poll_events()returns:> 0bytes written (success)0timeout/no queued events (success)< 0failure (ZR_ERR_*)
Ownership and Lifetimes¶
- Engine owns all engine allocations.
- Caller never frees engine memory.
- Engine does not retain drawlist/event output buffer pointers across calls.
- Caller provides buffers for:
- drawlist input bytes
- event batch output bytes
- optional debug export/query payload buffers
Threading Contract¶
This section is the wrapper-facing threading source of truth and must stay
aligned with include/zr/zr_engine.h.
- Engine is single-threaded by default.
- Call engine APIs from one engine thread.
engine_post_user_event()is intended for cross-thread wake/event injection.- During teardown,
engine_post_user_event()may returnZR_ERR_INVALID_ARGUMENT. - Wrappers should quiesce posting threads before
engine_destroy().
Lifecycle¶
Typical sequence:
zr_engine_config_default()- set requested versions from
zr_version.h engine_create()- loop:
engine_poll_events()-> build drawlist ->engine_submit_drawlist()->engine_present() - optional telemetry via
engine_get_metrics()/engine_get_caps()/engine_get_terminal_profile() engine_destroy()
Core API Contracts¶
engine_create(zr_engine_t** out_engine, const zr_engine_config_t* cfg)¶
- Validates config and version negotiation.
- Creates platform backend and enters raw mode.
- Initializes framebuffers, event queue, output/damage buffers, arenas.
- Enqueues an initial
ZR_EV_RESIZEevent. - On failure: returns error and leaves
*out_engine == NULL.
Common failures:
ZR_ERR_INVALID_ARGUMENTZR_ERR_UNSUPPORTED(version/config mismatch)ZR_ERR_OOMZR_ERR_PLATFORM
void engine_destroy(zr_engine_t* e)¶
- Safe with
NULL. - Leaves raw mode best-effort, destroys platform state, releases all engine-owned memory.
- Should be called after post threads are quiesced.
int engine_poll_events(zr_engine_t* e, int timeout_ms, uint8_t* out_buf, int out_cap)¶
- Waits for input (bounded by
timeout_ms) and packs queued events intoout_buf. - Uses packed event-batch format (
zr_event.h). - Returns bytes written,
0on timeout/no events, or negative error.
Validation rules:
timeout_ms < 0->ZR_ERR_INVALID_ARGUMENTout_cap < 0->ZR_ERR_INVALID_ARGUMENTout_cap > 0without_buf == NULL->ZR_ERR_INVALID_ARGUMENT
Behavior notes:
- If queue already has events, polling does not block.
- Tick events may be injected based on configured frame cadence.
- Truncation is success-mode (
ZR_EV_BATCH_TRUNCATED) when full batch does not fit.
zr_result_t engine_post_user_event(zr_engine_t* e, uint32_t tag, const uint8_t* payload, int payload_len)¶
- Appends a wrapper-defined user event (
ZR_EV_USER) to the queue. - Best-effort wakes blocked platform wait.
- Payload is copied during call.
- Returns
ZR_ERR_INVALID_ARGUMENTwhen teardown has started.
zr_result_t engine_submit_drawlist(zr_engine_t* e, const uint8_t* bytes, int bytes_len)¶
- Validates drawlist bytes against caps and wire-format rules.
- Executes into staging framebuffer first.
- Commits to next framebuffer only on success (no partial effects).
zr_result_t engine_present(zr_engine_t* e)¶
- Diffs previous and next framebuffers.
- Emits terminal bytes into internal output buffer.
- Performs a single platform write on success.
- Commits frame/metrics only after successful write.
zr_result_t engine_get_metrics(zr_engine_t* e, zr_metrics_t* out_metrics)¶
- Prefix-copy semantics: caller sets
out_metrics->struct_sizeto receive compatible prefix. - Engine writes current struct size into copied snapshot field.
zr_result_t engine_get_caps(zr_engine_t* e, zr_terminal_caps_t* out_caps)¶
- Returns capability snapshot detected from active backend.
- Struct is fixed-width POD (ABI-safe for wrappers).
Fields include output feature gates used by the diff renderer:
supports_underline_styles- enables SGR underline variants (4:n)supports_colored_underlines- enables SGR underline color (58/59)supports_hyperlinks- enables OSC 8 hyperlink emission
engine_get_terminal_profile() exposes additional image-protocol detection fields used by drawlist v1 image selection:
supports_kitty_graphicssupports_sixelsupports_iterm2_images- cell pixel metrics (
cell_width_px,cell_height_px) used for protocol scaling targets
const zr_terminal_profile_t* engine_get_terminal_profile(const zr_engine_t* e)¶
- Returns pointer to engine-owned extended profile snapshot.
- Pointer remains owned by engine and is invalid after
engine_destroy(). - Includes terminal identity, probe metadata, and extended render capability fields.
zr_result_t engine_set_config(zr_engine_t* e, const zr_engine_runtime_config_t* cfg)¶
- Validates runtime config.
- Applies updates with "no partial effects" allocation/commit behavior.
- Platform sub-config changes are rejected with
ZR_ERR_UNSUPPORTED.
Debug Trace API¶
Debug APIs are optional diagnostics hooks:
engine_debug_enable/engine_debug_disableengine_debug_queryengine_debug_get_payloadengine_debug_get_statsengine_debug_exportengine_debug_reset
Notes:
- Disabled trace behaves as empty trace.
engine_debug_export()returns0when tracing is disabled or empty.- Query can be used in count-only mode by passing
out_headers = NULL.
Config Negotiation Essentials¶
From zr_engine_config_t at create time:
requested_engine_abi_*must match pinned ABI macros.requested_drawlist_versionmust beZR_DRAWLIST_VERSION_V1orZR_DRAWLIST_VERSION_V2. UseZR_DRAWLIST_VERSION_V2when emittingZR_DL_OP_BLIT_RECT.requested_event_batch_versionmust match pinned event version.cap_force_flags/cap_suppress_flagsapply deterministic capability overrides (suppresswins overforce).
Use values directly from zr_version.h; do not hardcode copies in wrappers.
Wrapper Integration Skeleton¶
zr_engine_config_t cfg = zr_engine_config_default();
cfg.requested_engine_abi_major = ZR_ENGINE_ABI_MAJOR;
cfg.requested_engine_abi_minor = ZR_ENGINE_ABI_MINOR;
cfg.requested_engine_abi_patch = ZR_ENGINE_ABI_PATCH;
cfg.requested_drawlist_version = ZR_DRAWLIST_VERSION_V2;
cfg.requested_event_batch_version = ZR_EVENT_BATCH_VERSION_V1;
zr_engine_t* e = NULL;
zr_result_t rc = engine_create(&e, &cfg);
if (rc != ZR_OK) {
/* fail early */
}
/* frame loop... */
engine_destroy(e);