mirror of
https://libwebsockets.org/repo/libwebsockets
synced 2024-12-04 13:57:15 +00:00
e3dca87f23
This adds optional display list support to lws_display, using DLOs (Display List Objects). DLOs for rectangle / rounded rectangle (with circle as the degenerate case), PNGs, JPEG and compressed, antialiased bitmapped fonts and text primitives are provided. Logical DLOs are instantiated on heap and listed into an lws_display_list owner, DLOs handle attributes like position, bounding box, colour + opacity, and local error diffusion backing buffer. When the display list is complete, it can be rasterized a line at a time, with scoped error diffusion resolved, such that no allocation for the framebuffer is required at any point. DLOs are freed as the rasterization moves beyond their bounding box. Adds a platform registry binding names and other metadata to lws_display fonts / PNGs / JPEGs. Provides registration, destruction and best match selection apis.
149 lines
5.4 KiB
Markdown
149 lines
5.4 KiB
Markdown
# lws_display_list
|
|
|
|
`lws_display_list` is a modernized 1970s-style Display List of graphic
|
|
primitives held in an `lws_dll2` list of Display List Objects (DLOs).
|
|
|
|
Provided DLO primitives are:
|
|
|
|
- filled rectangle (with individually controllable rounded corners)
|
|
- PNG (1:1 and original orientation only, transparency supported)
|
|
- JPEG (1:1 and original orientation only)
|
|
- utf-8 text areas (using compressed, antialiased mcufonts)
|
|
|
|
The aim of it is to process some other representation to describe the
|
|
logical scene completely using DLOs in memory, discard the earlier
|
|
representation and then rasterize the Display List a single line at a
|
|
time from top to bottom, so no backing framebuffer is required at all.
|
|
DLOs are destroyed as they go out of scope during rasterization.
|
|
|
|
Although the memory required does scale with scene complexity in
|
|
terms of number of DLOs, it hardly scales at all with output
|
|
resolution, allowing modern 32-bpp rendering on very constrained
|
|
devices, if slowly.
|
|
|
|
## DLO capabilities
|
|
|
|
DLOs are quite capable
|
|
|
|
- no floats (`lws_fx` integer fixed-point)
|
|
- 16-bit signed coordinate space with off-surface clipping handled
|
|
- Internal 32-bpp RGBA colourspace (8-bit opacity)
|
|
- correct Z-order opacity resolution
|
|
- Supports arbitrary paletteization (down to 1bpp) and error diffusion
|
|
- DLO-private error diffusion for clean opaque overlaid objects
|
|
- Antialised bitmap text using compressed fonts (eg 7 font sizes 10-
|
|
32px in both regular and bold < ~100KB)
|
|
- Very lightweight stateful PNG and JPEG decode
|
|
|
|
All DLOs in a Display List are consumed as they are rasterized,
|
|
individual DLOs are destroyed as soon as they go out of scope during
|
|
top - bottom rendering, freeing any related resources as soon as possible.
|
|
|
|
## DLO PNGs
|
|
|
|
DLOs may point to a compressed PNG, which is decompressed on the fly
|
|
and the decompression context destroyed as the rasterization goes
|
|
beyond its bounding box. Using the lws stateful rewrite of upng, the
|
|
memory cost of 32-bpp PNG decode of any dimensions is 40K + 16 x width
|
|
bytes, including error diffusion line buffers. Decoding of the
|
|
compressed PNG data is done statefully on demand as needed to fill an
|
|
output line, so no memory is needed to hold excess decode production.
|
|
|
|
Multiple PNG DLOs including PNG-over-PNG (with alpha mixing) are
|
|
allowed. PNGs only take heap memory while the current rasterization
|
|
line intersects them, so any number of PNGs that don't intersect
|
|
vertically do not cost any more peak memory allocation than decoding one,
|
|
since the decoding contexts and DLOs of the earlier ones have been
|
|
destroyed before the next one's decoding context is allocated.
|
|
|
|
## DLO JPEGs
|
|
|
|
DLOs can also represent JPEGs using a stream parsing rewite of picojpeg.
|
|
No framebuffer is required to hold the output, it produces one line of
|
|
pixels at a time. JPEGs use either 8- or 16- line deep MCUs,
|
|
necessitating an 8 or 16 line RGB (or Y if grayscale) pixel buffer
|
|
during decode.
|
|
|
|
Heap requirements while a JPG is being rasterized is 2.5KB plus the
|
|
MCU buffer dependent on the chroma coding:
|
|
|
|
|Image type|Fixed alloc|MCU buffer|
|
|
|---|---|---|
|
|
|grayscale|2.5KB|image width x 8 bytes|
|
|
|YUV 4:4:4|2.5KB|image width x 24 bytes|
|
|
|YUV 4:4:2v|2.5KB|image width x 24 bytes|
|
|
|YUV 4:4:2h|2.5KB|image width x 48 bytes|
|
|
|YUV 4:4:0|2.5KB|image width x 48 bytes|
|
|
|
|
## DLO text
|
|
|
|
Text DLOs are predicated around unicode utf-8 and a stream parsing
|
|
rewrite of mcufont decoder.
|
|
|
|
mcufont includes a ttf renderer app which is ported into lws as well,
|
|
this allows production of antialised (16 alpha level) compressed
|
|
bitmaped fonts from any ttf font at a selected size and including
|
|
specified subsets of unicode code points.
|
|
|
|
Font glyphs are decompressed statefully as part of the DLO line
|
|
rasterization process, so there are no glyph buffers or caching.
|
|
The decompression is very fast and allows fitting over a dozen
|
|
font sizes and weights into 100KB.
|
|
|
|
Wrapping inside a bounding box is supported as is "run-on", where text
|
|
DLOs follow one another inline, used for example to use a bold font
|
|
in part of a text using a different DLO with a different font before
|
|
continuing with another DLO using the non-bold font cleanly. DLOs
|
|
are marked as running-on or not.
|
|
|
|
Centering and right-justification is possible by summing run-ons on
|
|
the current line by walking the display list backwards until a non-
|
|
run-on DLO is seen, and adjusting the affected DLOs x position.
|
|
|
|
## Display List lifecycle
|
|
|
|
### Create empty display list
|
|
|
|
Create the display state (the dynamic counterpart of the const, static
|
|
`lws_display` definition) and the empty display list.
|
|
|
|
```
|
|
lws_display_state_t lds;
|
|
lws_displaylist_t dl;
|
|
```
|
|
|
|
Instantiate the `lws_display` and bind the display list to it
|
|
```
|
|
lws_display_state_init(&lds, cx, 30000, 10000, lls, &disp.disp);
|
|
|
|
lws_display_dl_init(&dl, &lds);
|
|
|
|
|
|
|
|
### Create DLOs into the list
|
|
|
|
Eg, create a png from `data` / `len`, return NULL if failed.
|
|
|
|
```
|
|
if (!lws_display_dlo_png_new(&dl, &box, data, len)) {
|
|
```
|
|
|
|
Eg, create a white background rectange the size of the `lws_display`
|
|
|
|
```
|
|
lws_dlo_rect_t *dr;
|
|
lws_box_t box = { 0, 0, dl.ds->disp->ic.wh_px[0].whole,
|
|
dl.ds->disp->ic.wh_px[1].whole };
|
|
|
|
dr = lws_display_dlo_rect_new(&dl, &box, 0,
|
|
LWSDC_RGBA(255, 255, 255, 255));
|
|
if (!dr)
|
|
return 1;
|
|
```
|
|
|
|
### Rendering into an lws_display
|
|
|
|
```
|
|
lds->disp->blit(lds, (uint8_t *)&dl, &box);
|
|
```
|