docs
Loading...
Searching...
No Matches
CAPI_Surface.h
Go to the documentation of this file.
1///
2/// Copyright (C) 2026 Ultralight, Inc. All rights reserved.
3/// A license is required for commercial use. https://ultralig.ht
4///
5
6///
7/// @file CAPI_Surface.h
8///
9/// User-defined pixel buffer surface.
10///
11/// `#include <Ultralight/CAPI/CAPI_Surface.h>`
12///
13/// The library uses this to store pixel data when rendering Views on the CPU (see
14/// ulViewIsAccelerated()).
15///
16/// You can provide the library with your own Surface implementation to reduce the latency of
17/// displaying pixels in your application (Views will be drawn directly to a block of memory
18/// controlled by you).
19///
20/// When a View is rendered on the CPU, you can retrieve the backing Surface via ulViewGetSurface().
21/// After each paint the Surface lists the rectangles the library changed
22/// (ulSurfaceGetDirtyRectCount(), ulSurfaceGetDirtyRect()); ulSurfaceGetDirtyBounds() is their
23/// union.
24///
25/// @pre This is automatically managed for you when using ulCreateApp(), if you want to override
26/// ULSurfaceDefinition, you'll need to use ulCreateRenderer() instead.
27///
28/// ## Default Implementation
29///
30/// A default Surface implementation, BitmapSurface, is automatically provided by the library when
31/// you call ulCreateRenderer() without defining a custom ULSurfaceDefinition.
32///
33/// You should cast the ULSurface to a ULBitmapSurface and call ulBitmapSurfaceGetBitmap() to access
34/// the underlying Bitmap.
35///
36/// ## Setting the Surface Implementation
37///
38/// To define your own implementation, you should implement the ULSurfaceDefinition callbacks,
39/// and then pass an instance of ULSurfaceDefinition containing your callbacks to
40/// ulPlatformSetSurfaceDefinition() before calling ulCreateRenderer().
41///
42#ifndef ULTRALIGHT_CAPI_SURFACE_H
43#define ULTRALIGHT_CAPI_SURFACE_H
44
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51/******************************************************************************
52 * Surface
53 *****************************************************************************/
54
55///
56/// Width (in pixels).
57///
58ULExport unsigned int ulSurfaceGetWidth(ULSurface surface);
59
60///
61/// Height (in pixels).
62///
64
65///
66/// Number of bytes between rows (usually width * 4)
67///
69
70///
71/// Size in bytes.
72///
74
75///
76/// Lock the pixel buffer and get a pointer to the beginning of the data for reading/writing.
77///
78/// Native pixel format is premultiplied BGRA 32-bit (8 bits per channel).
79///
81
82///
83/// Unlock the pixel buffer.
84///
86
87///
88/// Resize the pixel buffer to a certain width and height (both in pixels).
89///
90/// This should never be called while pixels are locked.
91///
92ULExport void ulSurfaceResize(ULSurface surface, unsigned int width, unsigned int height);
93
94///
95/// Set the dirty bounds to a certain value.
96///
97/// This is called after the Renderer paints to an area of the pixel buffer. (The new value will be
98/// joined with the existing dirty_bounds())
99///
101
102///
103/// Get the dirty bounds.
104///
105/// This value can be used to determine which portion of the pixel buffer has been updated since the
106/// last call to ulSurfaceClearDirtyBounds().
107///
108/// The general algorithm to determine if a Surface needs display is:
109/// ```
110/// if (!ulIntRectIsEmpty(ulSurfaceGetDirtyBounds(surface))) {
111/// // Surface pixels are dirty and needs display.
112/// // Cast Surface to native Surface and use it here (pseudo code)
113/// DisplaySurface(surface);
114///
115/// // Once you're done, clear the dirty bounds:
116/// ulSurfaceClearDirtyBounds(surface);
117/// }
118/// ```
119///
121
122///
123/// Clear the dirty bounds.
124///
125/// You should call this after you're done displaying the Surface.
126///
128
129///
130/// Shift a rectangle of pixels by a certain offset (see ULSurfaceDefinitionScrollCallback for the
131/// rules).
132///
133/// @param surface The surface handle.
134///
135/// @param rect The rectangle to shift (in pixels).
136///
137/// @param dx The horizontal shift, in pixels (positive moves pixels to the right).
138///
139/// @param dy The vertical shift, in pixels (positive moves pixels down).
140///
141/// @return Returns the scroll callback's answer, or false for the default surface.
142///
143ULExport bool ulSurfaceScroll(ULSurface surface, ULIntRect rect, int dx, int dy);
144
145///
146/// Shift a rectangle of 32-bit pixels in place.
147///
148/// Use this from your scroll callback to move the pixels of `rect` by `dx` and `dy` through the
149/// pointer you returned from the lock callback; overlapping rows and columns are handled for you.
150///
151/// @param pixels Pointer to the first pixel of the buffer.
152///
153/// @param row_bytes Number of bytes between rows (usually width * 4).
154///
155/// @param rect The rectangle to shift (in pixels).
156///
157/// @param dx The horizontal shift, in pixels (positive moves pixels to the right).
158///
159/// @param dy The vertical shift, in pixels (positive moves pixels down).
160///
161ULExport void ulSurfaceShiftPixels(void* pixels, unsigned int row_bytes, ULIntRect rect, int dx,
162 int dy);
163
164///
165/// Get the number of dirty rectangles (0 when nothing has been painted since the last clear).
166///
167/// @param surface The surface handle.
168///
169/// @return Returns the number of dirty rectangles.
170///
172
173///
174/// Get a dirty rectangle by index.
175///
176/// Each lies inside the dirty bounds; the dirty bounds are their union, so you can copy each one
177/// instead of the union to move fewer pixels.
178///
179/// @param surface The surface handle.
180///
181/// @param index The index of the rectangle (less than ulSurfaceGetDirtyRectCount()).
182///
183/// @return Returns the rectangle, or an empty rectangle for an index out of range.
184///
186
187///
188/// Get the underlying user data pointer (this is only valid if you have set a custom surface
189/// implementation via ulPlatformSetSurfaceDefinition).
190///
191/// This will return nullptr if this surface is the default ULBitmapSurface.
192///
194
195/******************************************************************************
196 * BitmapSurface
197 *****************************************************************************/
198
199///
200/// Get the underlying Bitmap from the default Surface.
201///
202/// @note Do not call ulDestroyBitmap() on the returned value, it is owned by the surface.
203///
205
206/******************************************************************************
207 * Surface Definition
208 *****************************************************************************/
209
210///
211/// The callback invoked when a Surface is created.
212///
213/// @param width The width in pixels.
214/// @param height The height in pixels.
215///
216/// @return Return a pointer to user-defined data for the instance. This user data pointer will be
217/// passed to all other callbacks when operating on the instance.
218///
219typedef void* (*ULSurfaceDefinitionCreateCallback)(unsigned int width, unsigned int height);
220
221///
222/// The callback invoked when a Surface is destroyed.
223///
224/// @param user_data User data pointer uniquely identifying the surface.
225///
226typedef void (*ULSurfaceDefinitionDestroyCallback)(void* user_data);
227
228///
229/// The callback invoked when a Surface's width (in pixels) is requested.
230///
231/// @param user_data User data pointer uniquely identifying the surface.
232///
233typedef unsigned int (*ULSurfaceDefinitionGetWidthCallback)(void* user_data);
234
235///
236/// The callback invoked when a Surface's height (in pixels) is requested.
237///
238/// @param user_data User data pointer uniquely identifying the surface.
239///
240typedef unsigned int (*ULSurfaceDefinitionGetHeightCallback)(void* user_data);
241
242///
243/// The callback invoked when a Surface's row bytes is requested.
244///
245/// @note This value is also known as "stride". Usually width * 4.
246///
247/// @param user_data User data pointer uniquely identifying the surface.
248///
249typedef unsigned int (*ULSurfaceDefinitionGetRowBytesCallback)(void* user_data);
250
251///
252/// The callback invoked when a Surface's size (in bytes) is requested.
253///
254/// @param user_data User data pointer uniquely identifying the surface.
255///
256typedef size_t (*ULSurfaceDefinitionGetSizeCallback)(void* user_data);
257
258///
259/// The callback invoked when a Surface's pixel buffer is requested to be locked for reading/writing
260/// (should return a pointer to locked bytes).
261///
262/// @param user_data User data pointer uniquely identifying the surface.
263///
264typedef void* (*ULSurfaceDefinitionLockPixelsCallback)(void* user_data);
265
266///
267/// The callback invoked when a Surface's pixel buffer is requested to be unlocked after previously
268/// being locked.
269///
270/// @param user_data User data pointer uniquely identifying the surface.
271///
272typedef void (*ULSurfaceDefinitionUnlockPixelsCallback)(void* user_data);
273
274///
275/// The callback invoked when a Surface is requested to be resized to a certain width/height.
276///
277/// @param user_data User data pointer uniquely identifying the surface.
278///
279/// @param width Width in pixels.
280///
281/// @param height Height in pixels.
282///
283typedef void (*ULSurfaceDefinitionResizeCallback)(void* user_data, unsigned int width,
284 unsigned int height);
285
286///
287/// The callback invoked when a Surface is asked to shift a rectangle of pixels by an offset.
288///
289/// The library calls this during ulRender() when a page scrolls, moving already painted pixels
290/// instead of repainting them. Afterward, the library repaints only the exposed strip.
291///
292/// The Surface pixel buffer is the source the library paints into. The destination is wherever
293/// you copy those pixels to display them (eg, a GPU texture or a window). This callback always
294/// shifts the source.
295///
296/// Most implementations do this with one call to ulSurfaceShiftPixels().
297///
298/// @param user_data User data pointer uniquely identifying the surface.
299///
300/// @param rect The rectangle to shift (in pixels). This always lies inside the surface, and
301/// the shift is smaller than the rectangle on each axis.
302///
303/// @param dx The horizontal shift, in pixels (positive moves pixels to the right).
304///
305/// @param dy The vertical shift, in pixels (positive moves pixels down).
306///
307/// @return Return false in most cases. This means the destination was not shifted. The
308/// library then adds `rect` to the dirty bounds so you copy the moved pixels from the
309/// source to the destination again. Return true only in the rare case where you
310/// shifted the destination by the same offset yourself (eg, you scrolled your
311/// window or copied within your GPU texture)-- the library then reports only the
312/// newly exposed strip as dirty.
313///
314/// \parblock
315/// @note This is called while pixels are locked (between the lock and unlock callbacks). Shift
316/// through the pointer you returned from the lock callback-- do not lock the buffer again.
317/// \endparblock
318///
319/// \parblock
320/// @note Rows may be padded. Step rows by the row bytes, never by width * 4.
321/// \endparblock
322///
323typedef bool (*ULSurfaceDefinitionScrollCallback)(void* user_data, ULIntRect rect, int dx,
324 int dy);
325
326///
327/// User-defined surface interface.
328///
329/// You should implement each of these callbacks, then pass an instance of this struct containing
330/// your callbacks to ulPlatformSetSurfaceDefinition().
331///
332/// Zero-initialize the struct (`ULSurfaceDefinition def = {0};`) so a callback you leave unset
333/// reads as NULL.
334///
335typedef struct {
336 /// Callback invoked when a Surface is created.
338 /// Callback invoked when a Surface is destroyed.
340 /// Callback invoked to get the Surface width in pixels.
342 /// Callback invoked to get the Surface height in pixels.
344 /// Callback invoked to get the number of bytes per row.
346 /// Callback invoked to get the Surface size in bytes.
348 /// Callback invoked to lock the pixel buffer for reading/writing.
350 /// Callback invoked to unlock the pixel buffer.
352 /// Callback invoked to resize the pixel buffer.
354 /// Callback invoked to shift a rectangle of pixels (may be NULL, the library then shifts the
355 /// locked buffer itself and reports the whole rectangle dirty).
358
359#ifdef __cplusplus
360} // extern "C"
361#endif
362
363#endif // ULTRALIGHT_CAPI_SURFACE_H
unsigned int(*) ULSurfaceDefinitionGetWidthCallback(void *user_data)
The callback invoked when a Surface's width (in pixels) is requested.
Definition CAPI_Surface.h:233
void ulSurfaceResize(ULSurface surface, unsigned int width, unsigned int height)
Resize the pixel buffer to a certain width and height (both in pixels).
unsigned int ulSurfaceGetRowBytes(ULSurface surface)
Number of bytes between rows (usually width * 4).
void * ulSurfaceLockPixels(ULSurface surface)
Lock the pixel buffer and get a pointer to the beginning of the data for reading/writing.
void ulSurfaceClearDirtyBounds(ULSurface surface)
Clear the dirty bounds.
void ulSurfaceUnlockPixels(ULSurface surface)
Unlock the pixel buffer.
void *(*) ULSurfaceDefinitionLockPixelsCallback(void *user_data)
The callback invoked when a Surface's pixel buffer is requested to be locked for reading/writing (sho...
Definition CAPI_Surface.h:264
bool(*) ULSurfaceDefinitionScrollCallback(void *user_data, ULIntRect rect, int dx, int dy)
The callback invoked when a Surface is asked to shift a rectangle of pixels by an offset.
Definition CAPI_Surface.h:323
void * ulSurfaceGetUserData(ULSurface surface)
Get the underlying user data pointer (this is only valid if you have set a custom surface implementat...
void(*) ULSurfaceDefinitionResizeCallback(void *user_data, unsigned int width, unsigned int height)
The callback invoked when a Surface is requested to be resized to a certain width/height.
Definition CAPI_Surface.h:283
void ulSurfaceSetDirtyBounds(ULSurface surface, ULIntRect bounds)
Set the dirty bounds to a certain value.
unsigned int ulSurfaceGetHeight(ULSurface surface)
Height (in pixels).
void ulSurfaceShiftPixels(void *pixels, unsigned int row_bytes, ULIntRect rect, int dx, int dy)
Shift a rectangle of 32-bit pixels in place.
size_t(*) ULSurfaceDefinitionGetSizeCallback(void *user_data)
The callback invoked when a Surface's size (in bytes) is requested.
Definition CAPI_Surface.h:256
ULIntRect ulSurfaceGetDirtyRect(ULSurface surface, unsigned int index)
Get a dirty rectangle by index.
unsigned int ulSurfaceGetWidth(ULSurface surface)
Width (in pixels).
bool ulSurfaceScroll(ULSurface surface, ULIntRect rect, int dx, int dy)
Shift a rectangle of pixels by a certain offset (see ULSurfaceDefinitionScrollCallback for the rules)...
void(*) ULSurfaceDefinitionUnlockPixelsCallback(void *user_data)
The callback invoked when a Surface's pixel buffer is requested to be unlocked after previously being...
Definition CAPI_Surface.h:272
void(*) ULSurfaceDefinitionDestroyCallback(void *user_data)
The callback invoked when a Surface is destroyed.
Definition CAPI_Surface.h:226
size_t ulSurfaceGetSize(ULSurface surface)
Size in bytes.
unsigned int ulSurfaceGetDirtyRectCount(ULSurface surface)
Get the number of dirty rectangles (0 when nothing has been painted since the last clear).
unsigned int(*) ULSurfaceDefinitionGetRowBytesCallback(void *user_data)
The callback invoked when a Surface's row bytes is requested.
Definition CAPI_Surface.h:249
ULIntRect ulSurfaceGetDirtyBounds(ULSurface surface)
Get the dirty bounds.
ULBitmap ulBitmapSurfaceGetBitmap(ULBitmapSurface surface)
Get the underlying Bitmap from the default Surface.
unsigned int(*) ULSurfaceDefinitionGetHeightCallback(void *user_data)
The callback invoked when a Surface's height (in pixels) is requested.
Definition CAPI_Surface.h:240
void *(*) ULSurfaceDefinitionCreateCallback(unsigned int width, unsigned int height)
The callback invoked when a Surface is created.
Definition CAPI_Surface.h:219
Various defines and utility functions for the C API.
struct C_Surface * ULBitmapSurface
Opaque handle to a BitmapSurface (the default Surface implementation).
Definition CAPI_Defines.h:125
#define ULExport
Definition CAPI_Defines.h:42
struct C_Surface * ULSurface
Opaque handle to a Surface object.
Definition CAPI_Defines.h:122
struct C_Bitmap * ULBitmap
Opaque handle to a Bitmap object.
Definition CAPI_Defines.h:93
Integer rectangle defined by left, top, right, and bottom coordinates.
Definition CAPI_Defines.h:548
User-defined surface interface.
Definition CAPI_Surface.h:335
ULSurfaceDefinitionGetHeightCallback get_height
Callback invoked to get the Surface height in pixels.
Definition CAPI_Surface.h:343
ULSurfaceDefinitionUnlockPixelsCallback unlock_pixels
Callback invoked to unlock the pixel buffer.
Definition CAPI_Surface.h:351
ULSurfaceDefinitionScrollCallback scroll
Callback invoked to shift a rectangle of pixels (may be NULL, the library then shifts the locked buff...
Definition CAPI_Surface.h:356
ULSurfaceDefinitionCreateCallback create
Callback invoked when a Surface is created.
Definition CAPI_Surface.h:337
ULSurfaceDefinitionResizeCallback resize
Callback invoked to resize the pixel buffer.
Definition CAPI_Surface.h:353
ULSurfaceDefinitionLockPixelsCallback lock_pixels
Callback invoked to lock the pixel buffer for reading/writing.
Definition CAPI_Surface.h:349
ULSurfaceDefinitionGetWidthCallback get_width
Callback invoked to get the Surface width in pixels.
Definition CAPI_Surface.h:341
ULSurfaceDefinitionGetRowBytesCallback get_row_bytes
Callback invoked to get the number of bytes per row.
Definition CAPI_Surface.h:345
ULSurfaceDefinitionGetSizeCallback get_size
Callback invoked to get the Surface size in bytes.
Definition CAPI_Surface.h:347
ULSurfaceDefinitionDestroyCallback destroy
Callback invoked when a Surface is destroyed.
Definition CAPI_Surface.h:339