libwebsockets
Lightweight C library for HTML5 websockets
|
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:
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.
DLOs are quite capable
lws_fx
integer fixed-point)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.
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.
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 |
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.
Create the display state (the dynamic counterpart of the const, static lws_display
definition) and the empty display list.
Instantiate the lws_display
and bind the display list to it
if (!lws_display_dlo_png_new(&dl, &box, data, len)) {
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;
lds->disp->blit(lds, (uint8_t *)&dl, &box); ```