|
Ultralight C API 2.0.0
|
Core renderer singleton for the library, coordinates all library functions.
#include <Ultralight/CAPI/CAPI_Renderer.h>
The Renderer class is responsible for creating and painting Views, managing Sessions, as well as coordinating network requests, events, JavaScript execution, and more.
Before creating the Renderer, you should define your platform handlers via the Platform singleton (see CAPI_Platform.h). This can be used to customize file loading, font loading, clipboard access, and other functionality typically provided by the OS.
Default implementations for most platform handlers ship as Zlib-licensed source in the SDK's platform folder. You can use these stock implementations by copying the code into your project, or you can write your own.
At a minimum, you must provide a ULFileSystem and a ULFontLoader. Without them, the library exits the process with an error when it first needs them.
Once you've set up the Platform handlers you can create the Renderer by calling ulCreateRenderer().
You should call ulUpdate() from your main update loop as often as possible to give the library an opportunity to dispatch events and timers:
When your program is ready to display a new frame (usually in sync with the monitor's refresh rate), you should call ulRefreshDisplay() and ulRender() so the library can render all active Views as needed.
Animations and smooth scrolling advance with each ulRefreshDisplay() call. Call it once per frame you present (once per display refresh for a vsynced loop, or once per rendered frame for a vsync-off or variable-refresh game loop).
Classes | |
| struct | ULGCInfo |
| A snapshot of the JavaScript heap's state. More... | |
Functions | |
| ULRenderer | ulCreateRenderer (ULConfig config) |
| Create the core renderer singleton for the library. | |
| void | ulDestroyRenderer (ULRenderer renderer) |
| Destroy a renderer previously created with ulCreateRenderer(). | |
| void | ulUpdate (ULRenderer renderer) |
| Update timers and dispatch internal callbacks (JavaScript and network). | |
| void | ulRefreshDisplay (ULRenderer renderer, unsigned int display_id) |
| Notify the renderer that a display has refreshed. | |
| void | ulRefreshDisplayWithTimestamp (ULRenderer renderer, unsigned int display_id, double target_timestamp) |
| Notify the renderer that a display has refreshed, and when the resulting frame will be shown. | |
| void | ulRendererSetDisplayRefreshRate (ULRenderer renderer, unsigned int display_id, double refresh_rate) |
| Declare a display's refresh rate. | |
| double | ulRendererGetDisplayRefreshRate (ULRenderer renderer, unsigned int display_id) |
| Get the refresh rate declared for a display. | |
| void | ulRendererSetDisplayUsesCustomClock (ULRenderer renderer, unsigned int display_id, bool uses_custom_clock) |
| Declare that a display's refresh timestamps are on your own timeline rather than the system clock (Default = False). | |
| bool | ulRendererGetDisplayUsesCustomClock (ULRenderer renderer, unsigned int display_id) |
| Get whether a display was declared to use a custom clock. | |
| void | ulRender (ULRenderer renderer) |
| Render all active Views to their respective surfaces and render targets. | |
| void | ulRendererPostTask (ULRenderer renderer, ULRendererTaskCallback task, void *user_data, ULUserDataDestroyCallback destroy_user_data) |
| Post a task to run on the Renderer's thread during a future call to ulUpdate(). | |
| void | ulRendererPostDelayedTask (ULRenderer renderer, double delay_ms, ULRendererTaskCallback task, void *user_data, ULUserDataDestroyCallback destroy_user_data) |
| Post a task to run on the Renderer's thread once a delay has elapsed. | |
| void | ulRecycle (ULRenderer renderer, ULRecycleMode mode) |
| Recycle internal caches and memory. | |
| void | ulPurgeMemory (ULRenderer renderer) |
| Attempt to release as much memory as possible. | |
| void | ulLogMemoryUsage (ULRenderer renderer) |
| Print detailed memory usage statistics to the log. | |
| bool | ulStartRemoteInspectorServer (ULRenderer renderer, const char *address, unsigned short port) |
| Start the remote inspector server. | |
| void | ulSetGamepadDetails (ULRenderer renderer, unsigned int index, ULString id, unsigned int axis_count, unsigned int button_count) |
| Describe the details of a gamepad, to be used with ulFireGamepadEvent and related events below. | |
| void | ulFireGamepadEvent (ULRenderer renderer, ULGamepadEvent evt) |
| Fire a gamepad event (connection / disconnection). | |
| void | ulFireGamepadAxisEvent (ULRenderer renderer, ULGamepadAxisEvent evt) |
| Fire a gamepad axis event (to be called when an axis value is changed). | |
| void | ulFireGamepadButtonEvent (ULRenderer renderer, ULGamepadButtonEvent evt) |
| Fire a gamepad button event (to be called when a button value is changed). | |
| void | ulRenderOnly (ULRenderer renderer, ULView *view_array, unsigned int view_array_len) |
| Render a subset of Views to their respective surfaces and render targets. | |
| ULString | ulGetMemoryUsage (ULRenderer renderer) |
| Get formatted memory usage statistics as a string. | |
| void | ulRendererSetSystemColorScheme (ULRenderer renderer, ULColorScheme scheme) |
| Set the system color scheme that Views report to pages via the prefers-color-scheme CSS media feature. | |
| ULColorScheme | ulRendererGetSystemColorScheme (ULRenderer renderer) |
| Get the current system color scheme. | |
| bool | ulRendererBeginRenderTrace (ULRenderer renderer, const char *path, bool verbose) |
| Begin recording a render trace to the specified file path. | |
| void | ulRendererEndRenderTrace (ULRenderer renderer) |
| End the current render trace. | |
| bool | ulRendererIsRenderTraceActive (ULRenderer renderer) |
| Check if a render trace is currently being recorded. | |
| void | ulRendererSetGCRequestGCCallback (ULRenderer renderer, ULGCRequestGCCallback callback, void *user_data, ULUserDataDestroyCallback destroy_user_data) |
| Set the callback for when the engine wants to run a collection on your thread (see ULGCRequestGCCallback). | |
| void | ulRendererSetGCPressureChangedCallback (ULRenderer renderer, ULGCPressureChangedCallback callback, void *user_data, ULUserDataDestroyCallback destroy_user_data) |
| Set the callback for when reclaimable memory rises past a threshold (see ULGCPressureChangedCallback). | |
| void | ulRendererSetGCCollectCompleteCallback (ULRenderer renderer, ULGCCollectCompleteCallback callback, void *user_data, ULUserDataDestroyCallback destroy_user_data) |
| Set the callback for when a collection on your thread finishes (see ULGCCollectCompleteCallback). | |
| ULGCInfo | ulRendererGetGCStatus (ULRenderer renderer) |
| Get a snapshot of the JavaScript heap's state. | |
| void | ulRecycleEx (ULRenderer renderer, ULRecycleMode mode, ULCodeDropMode code) |
| Reclaim memory, choosing how much compiled code to discard. | |
| void | ulRendererCollectNow (ULRenderer renderer, ULCodeDropMode code, bool sync) |
| Collect the JavaScript heap now, leaving rendering and GPU caches intact. | |
Typedefs | |
| typedef void(*) | ULRendererTaskCallback(void *user_data) |
| typedef void(*) | ULGCRequestGCCallback(void *user_data, ULRenderer caller, ULGCInfo info, ULCodeDropMode code) |
| Called when the engine wants to run a collection on your thread. | |
| typedef void(*) | ULGCPressureChangedCallback(void *user_data, ULRenderer caller, ULGCInfo info) |
| Called when reclaimable memory rises past a threshold (see ULGCInfo). | |
| typedef void(*) | ULGCCollectCompleteCallback(void *user_data, ULRenderer caller, ULGCInfo info, ULCodeDropMode code, double duration_ms, unsigned long long bytes_reclaimed) |
| Called after a collection on your thread finishes. | |
Enumerations | |
| enum | ULRecycleMode { kRecycleMode_Lightweight = 0 , kRecycleMode_Full } |
| Controls how aggressively ulRecycle() reclaims memory. More... | |
| enum | ULCodeDropMode { kCodeDropMode_Nothing = 0 , kCodeDropMode_Linked , kCodeDropMode_All } |
| How much compiled JavaScript code a collection discards. More... | |
| ULRenderer ulCreateRenderer | ( | ULConfig | config | ) |
Create the core renderer singleton for the library.
You should set up the Platform singleton (see CAPI_Platform.h) before calling this function.
| config | The configuration to use for the renderer. |
| void ulDestroyRenderer | ( | ULRenderer | renderer | ) |
Destroy a renderer previously created with ulCreateRenderer().
| renderer | The renderer instance to destroy (can be NULL). |
| void ulFireGamepadAxisEvent | ( | ULRenderer | renderer, |
| ULGamepadAxisEvent | evt ) |
Fire a gamepad axis event (to be called when an axis value is changed).
| renderer | The active renderer instance. |
| evt | The event to fire. |
| void ulFireGamepadButtonEvent | ( | ULRenderer | renderer, |
| ULGamepadButtonEvent | evt ) |
Fire a gamepad button event (to be called when a button value is changed).
| renderer | The active renderer instance. |
| evt | The event to fire. |
| void ulFireGamepadEvent | ( | ULRenderer | renderer, |
| ULGamepadEvent | evt ) |
Fire a gamepad event (connection / disconnection).
| renderer | The active renderer instance. |
| evt | The event to fire. |
| ULString ulGetMemoryUsage | ( | ULRenderer | renderer | ) |
Get formatted memory usage statistics as a string.
This is the same information ulLogMemoryUsage() prints, in a form you can show in a debug overlay or capture programmatically.
| renderer | The active renderer instance. |
| void ulLogMemoryUsage | ( | ULRenderer | renderer | ) |
Print detailed memory usage statistics to the log.
| renderer | The active renderer instance. |
| void ulPurgeMemory | ( | ULRenderer | renderer | ) |
Attempt to release as much memory as possible.
This also discards all compiled JavaScript code, so pages run slower for a while as it's recompiled.
| renderer | The active renderer instance. |
| void ulRecycle | ( | ULRenderer | renderer, |
| ULRecycleMode | mode ) |
Recycle internal caches and memory.
| renderer | The active renderer instance. |
| mode | How aggressively to reclaim memory. |
| void ulRecycleEx | ( | ULRenderer | renderer, |
| ULRecycleMode | mode, | ||
| ULCodeDropMode | code ) |
Reclaim memory, choosing how much compiled code to discard.
This works like ulRecycle(). With kRecycleMode_Full, code sets how much compiled code the collection discards (it has no effect with kRecycleMode_Lightweight).
| renderer | The Renderer. |
| mode | How aggressively to reclaim memory. |
| code | How much compiled code to discard. |
| void ulRefreshDisplay | ( | ULRenderer | renderer, |
| unsigned int | display_id ) |
Notify the renderer that a display has refreshed.
When your program is ready to display a new frame (usually in synchrony with the monitor refresh rate), you should call ulRefreshDisplay() and ulRender() so the library can render all active Views as needed.
Animations and smooth scroll advance to each ulRefreshDisplay() call. Call it once per frame you present (once per display refresh for a vsynced loop, or once per rendered frame for a vsync-off or variable-refresh game loop).
Call this once per frame you present, for each display (usually right after vsync). It advances animations, smooth scrolling, and window.requestAnimationFrame() for the Views on that display, so they can repaint during the next ulRender().
| renderer | The active renderer instance. |
| display_id | The id of the display that refreshed (see ulViewConfigSetDisplayId()). |
| void ulRefreshDisplayWithTimestamp | ( | ULRenderer | renderer, |
| unsigned int | display_id, | ||
| double | target_timestamp ) |
Notify the renderer that a display has refreshed, and when the resulting frame will be shown.
This works like ulRefreshDisplay(), but animation time follows your timestamps instead of the wall clock, so animations are timed for the moment the frame reaches the screen.
| renderer | The active renderer instance. |
| display_id | The id of the display that refreshed. |
| target_timestamp | When this frame will be shown, in seconds. Use the system's monotonic clock (eg, the target time your display link reports), or your own timeline after calling ulRendererSetDisplayUsesCustomClock(). Timestamps must never decrease. |
| void ulRender | ( | ULRenderer | renderer | ) |
Render all active Views to their respective surfaces and render targets.
| renderer | The active renderer instance. |
| bool ulRendererBeginRenderTrace | ( | ULRenderer | renderer, |
| const char * | path, | ||
| bool | verbose ) |
Begin recording a render trace to the specified file path.
| renderer | The active renderer instance. |
| path | Output file path (eg, "render_trace.perfetto-trace"). |
| verbose | If true, enables verbose mode (args + events in addition to scopes). |
| void ulRendererCollectNow | ( | ULRenderer | renderer, |
| ULCodeDropMode | code, | ||
| bool | sync ) |
Collect the JavaScript heap now, leaving rendering and GPU caches intact.
Unlike ulRecycle(), this reclaims only the JavaScript heap, so rendering stays fast. You can call it from your ULGCRequestGCCallback or at any moment when a short pause won't be noticed.
| renderer | The Renderer. |
| code | How much compiled code to discard. |
| sync | If true, collect before returning. If false, collect in the background. |
| void ulRendererEndRenderTrace | ( | ULRenderer | renderer | ) |
End the current render trace.
The trace file is finished and closed shortly after this returns (on the next ulUpdate()).
| renderer | The active renderer instance. |
| double ulRendererGetDisplayRefreshRate | ( | ULRenderer | renderer, |
| unsigned int | display_id ) |
Get the refresh rate declared for a display.
| renderer | The active renderer instance. |
| display_id | The display ID. |
| bool ulRendererGetDisplayUsesCustomClock | ( | ULRenderer | renderer, |
| unsigned int | display_id ) |
Get whether a display was declared to use a custom clock.
| renderer | The active renderer instance. |
| display_id | The display ID. |
| ULGCInfo ulRendererGetGCStatus | ( | ULRenderer | renderer | ) |
Get a snapshot of the JavaScript heap's state.
| renderer | The Renderer. |
| ULColorScheme ulRendererGetSystemColorScheme | ( | ULRenderer | renderer | ) |
Get the current system color scheme.
| renderer | The active renderer instance. |
| bool ulRendererIsRenderTraceActive | ( | ULRenderer | renderer | ) |
Check if a render trace is currently being recorded.
| renderer | The active renderer instance. |
| void ulRendererPostDelayedTask | ( | ULRenderer | renderer, |
| double | delay_ms, | ||
| ULRendererTaskCallback | task, | ||
| void * | user_data, | ||
| ULUserDataDestroyCallback | destroy_user_data ) |
Post a task to run on the Renderer's thread once a delay has elapsed.
The delay is measured against the ulUpdate() cadence rather than a background timer. The task runs during the first ulUpdate() at or after the deadline, so delivery waits while ulUpdate() is not being called (for example, a paused application). Tasks whose deadlines fall in the same ulUpdate() run in posting order.
| renderer | The active renderer instance. |
| delay_ms | Minimum delay before the task may run, in milliseconds. |
| task | Invoked once on the Renderer's thread with user_data. |
| user_data | Pointer passed through to task (can be NULL). |
| destroy_user_data | Invoked exactly once after task runs, or without task running if the Renderer is destroyed first or renderer is NULL (can be NULL). |
| void ulRendererPostTask | ( | ULRenderer | renderer, |
| ULRendererTaskCallback | task, | ||
| void * | user_data, | ||
| ULUserDataDestroyCallback | destroy_user_data ) |
Post a task to run on the Renderer's thread during a future call to ulUpdate().
You can use this to hand work from your other threads to the thread that drives the Renderer (the only thread that may touch Views and the DOM API).
Tasks run in posting order during the next ulUpdate() after they are posted. A task posted while ulUpdate() is draining tasks runs at the following ulUpdate().
| renderer | The active renderer instance. |
| task | Invoked once on the Renderer's thread with user_data. A NULL task posts nothing; destroy_user_data then runs at once. |
| user_data | Pointer passed through to task (can be NULL). |
| destroy_user_data | Invoked exactly once after task runs, or without task running if the Renderer is destroyed first or renderer is NULL (can be NULL). |
| void ulRendererSetDisplayRefreshRate | ( | ULRenderer | renderer, |
| unsigned int | display_id, | ||
| double | refresh_rate ) |
Declare a display's refresh rate.
Pages see the declared rate through window.requestAnimationFrame() scheduling. Call this when the display's mode changes (eg, a variable-rate display switching between 120 Hz and 48 Hz). Small changes are absorbed, and a change reaches pages at most once a second.
| renderer | The active renderer instance. |
| display_id | The id of the display. |
| refresh_rate | The display mode's nominal refresh rate in Hz (eg, 60.0, 59.94, 120.0), or 0 to clear it (the library then measures how often ulRefreshDisplay() is called). |
| void ulRendererSetDisplayUsesCustomClock | ( | ULRenderer | renderer, |
| unsigned int | display_id, | ||
| bool | uses_custom_clock ) |
Declare that a display's refresh timestamps are on your own timeline rather than the system clock (Default = False).
By default, the timestamps you pass to ulRefreshDisplayWithTimestamp() are treated as readings of the system's monotonic clock. Declare a custom clock when they're on a timeline of your own (eg, a media timeline for offline rendering, or simulation time): animation then follows your timestamps exactly.
| renderer | The active renderer instance. |
| display_id | The id of the display. |
| uses_custom_clock | True if timestamps for this display are on your own timeline. |
| void ulRendererSetGCCollectCompleteCallback | ( | ULRenderer | renderer, |
| ULGCCollectCompleteCallback | callback, | ||
| void * | user_data, | ||
| ULUserDataDestroyCallback | destroy_user_data ) |
Set the callback for when a collection on your thread finishes (see ULGCCollectCompleteCallback).
| renderer | The Renderer. |
| callback | The callback to invoke, or NULL to remove it. |
| user_data | Pointer passed through to callback (can be NULL). Ownership transfers to the Renderer. |
| destroy_user_data | Invoked exactly once on user_data when the callback is replaced or the Renderer is destroyed, or right away if renderer is NULL. Can be NULL. |
| void ulRendererSetGCPressureChangedCallback | ( | ULRenderer | renderer, |
| ULGCPressureChangedCallback | callback, | ||
| void * | user_data, | ||
| ULUserDataDestroyCallback | destroy_user_data ) |
Set the callback for when reclaimable memory rises past a threshold (see ULGCPressureChangedCallback).
| renderer | The Renderer. |
| callback | The callback to invoke, or NULL to remove it. |
| user_data | Pointer passed through to callback (can be NULL). Ownership transfers to the Renderer. |
| destroy_user_data | Invoked exactly once on user_data when the callback is replaced or the Renderer is destroyed, or right away if renderer is NULL. Can be NULL. |
| void ulRendererSetGCRequestGCCallback | ( | ULRenderer | renderer, |
| ULGCRequestGCCallback | callback, | ||
| void * | user_data, | ||
| ULUserDataDestroyCallback | destroy_user_data ) |
Set the callback for when the engine wants to run a collection on your thread (see ULGCRequestGCCallback).
Setting a callback replaces the previous one. With no callback set, the engine collects right away.
| renderer | The Renderer. |
| callback | The callback to invoke, or NULL to remove it. |
| user_data | Pointer passed through to callback (can be NULL). Ownership transfers to the Renderer. |
| destroy_user_data | Invoked exactly once on user_data when the callback is replaced or the Renderer is destroyed (never while the callback is running), or right away if renderer is NULL. Can be NULL. |
| void ulRendererSetSystemColorScheme | ( | ULRenderer | renderer, |
| ULColorScheme | scheme ) |
Set the system color scheme that Views report to pages via the prefers-color-scheme CSS media feature.
(Default = kColorScheme_Light)
The library never reads the OS setting itself, so the scheme stays Light until you call this.
A change re-evaluates prefers-color-scheme media queries in every View whose preferred color scheme is kColorScheme_Auto. Views pinned to Light or Dark are unaffected.
| renderer | The active renderer instance. |
| scheme | kColorScheme_Light or kColorScheme_Dark. kColorScheme_Auto or an out-of-range value logs a warning and is ignored. |
| void ulRenderOnly | ( | ULRenderer | renderer, |
| ULView * | view_array, | ||
| unsigned int | view_array_len ) |
Render a subset of Views to their respective surfaces and render targets.
| renderer | The active renderer instance. |
| view_array | A C-array of ULView handles to render. |
| view_array_len | The number of elements in the array. |
| void ulSetGamepadDetails | ( | ULRenderer | renderer, |
| unsigned int | index, | ||
| ULString | id, | ||
| unsigned int | axis_count, | ||
| unsigned int | button_count ) |
Describe the details of a gamepad, to be used with ulFireGamepadEvent and related events below.
This can be called multiple times with the same index if the details change.
| renderer | The active renderer instance. |
| index | The gamepad's connection slot, and the array position the page sees. A gamepad described at index 1 arrives as navigator.getGamepads()[1] with gamepad.index 1, leaving slot 0 null. Number your controllers from 0. |
| id | A string ID representing the device, this will be made available in JavaScript as gamepad.id |
| axis_count | The number of axes on the device. |
| button_count | The number of buttons on the device. |
| bool ulStartRemoteInspectorServer | ( | ULRenderer | renderer, |
| const char * | address, | ||
| unsigned short | port ) |
Start the remote inspector server.
While it runs, another Ultralight app (on the same machine or over the network) can inspect this renderer's Views by loading this URL in a View:
| renderer | The active renderer instance. |
| address | The address for the server to listen on (eg, "127.0.0.1") |
| port | The port for the server to listen on (eg, 9222) |
| void ulUpdate | ( | ULRenderer | renderer | ) |
Update timers and dispatch internal callbacks (JavaScript and network).
| renderer | The active renderer instance. |
| typedef void(*) ULGCCollectCompleteCallback(void *user_data, ULRenderer caller, ULGCInfo info, ULCodeDropMode code, double duration_ms, unsigned long long bytes_reclaimed) |
Called after a collection on your thread finishes.
This covers the engine's own collections and the ones you start with ulRendererCollectNow(), ulRecycle(), ulRecycleEx(), or ulPurgeMemory(). It's called during the next ulUpdate().
| user_data | The pointer you passed to ulRendererSetGCCollectCompleteCallback(). |
| caller | The Renderer. |
| info | The heap state when this is called. |
| code | How much compiled code the collection was asked to discard. |
| duration_ms | How long the collection took in milliseconds. |
| bytes_reclaimed | How many bytes the collection freed. |
| typedef void(*) ULGCPressureChangedCallback(void *user_data, ULRenderer caller, ULGCInfo info) |
Called when reclaimable memory rises past a threshold (see ULGCInfo).
You can use this to decide when to reclaim memory yourself (eg, with ulRendererCollectNow()). It fires again only after the pressure drops and rises again.
| user_data | The pointer you passed to ulRendererSetGCPressureChangedCallback(). |
| caller | The Renderer. |
| info | The current heap state. |
| typedef void(*) ULGCRequestGCCallback(void *user_data, ULRenderer caller, ULGCInfo info, ULCodeDropMode code) |
Called when the engine wants to run a collection on your thread.
The Renderer collects JavaScript garbage continuously in the background on other threads, so most collection work never touches your thread. Occasionally it needs a larger collection that runs on the thread that calls ulUpdate() and pauses it while it runs.
Your application knows better than the engine when a pause won't be noticed (eg, a loading screen or a quiet moment in your update loop). So the engine asks first, when there's been no input for a while (see ulConfigSetIdleGCEnabled()). One idle period can bring two requests: a lighter one first, then, if the app stays idle, one that drops more compiled code. A request you don't act on isn't offered again until new input ends the idle period.
From the callback, call ulRendererCollectNow() with code to collect right away, or call it later at a moment you choose, or skip the collection. With no callback set, the engine collects right away.
| user_data | The pointer you passed to ulRendererSetGCRequestGCCallback(). |
| caller | The Renderer to collect on. |
| info | The current heap state. |
| code | How much compiled code the engine recommends discarding (pass it to ulRendererCollectNow()). |
| typedef void(*) ULRendererTaskCallback(void *user_data) |
| enum ULCodeDropMode |
How much compiled JavaScript code a collection discards.
Compiled code keeps some JavaScript objects alive, so discarding it lets a collection free more memory. Pages then run slower for a while as their code is compiled again.
| enum ULRecycleMode |
Controls how aggressively ulRecycle() reclaims memory.