mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-23 00:00:06 +01:00
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);
|
||
|
```
|