Skip to content

Add display-list compositing for transparent backgrounds, RGB LCD driver, and new port commands#13

Draft
drlinux wants to merge 8 commits into
atomvm:mainfrom
drlinux:feature/display-list-compositing-and-rgb-lcd
Draft

Add display-list compositing for transparent backgrounds, RGB LCD driver, and new port commands#13
drlinux wants to merge 8 commits into
atomvm:mainfrom
drlinux:feature/display-list-compositing-and-rgb-lcd

Conversation

@drlinux

@drlinux drlinux commented Jun 17, 2026

Copy link
Copy Markdown

Summary

This PR adds several improvements to AtomGL, developed and tested on a Waveshare ESP32-S3 7-inch RGB Touch LCD (waveshare,esp32-s3-touch-lcd-7).

1. Display-list compositing for transparent backgrounds

When a primitive uses transparent background, partial-alpha pixels (from anti-aliased uFont text or RGBA images) were previously blended against the current framebuffer content. With double-buffered region rendering, this produces visual artifacts because the work framebuffer contains uninitialized memory.

The fix adds dcs_lcd_resolve_pixel_rgb565() which walks the display list to find the solid colour from the next lower opaque item, then blends partial-alpha pixels over that resolved colour. This enables correct anti-aliased text on any background without a solid background rectangle behind the text.

2. RGB LCD display driver (ESP-IDF 5+)

A new driver for RGB LCD panels using the ESP32-S3 LCD peripheral. Developed and verified on the Waveshare ESP32-S3 7-inch 800×480 RGB touch display.

Supports:

  • Double framebuffering in PSRAM for tear-free rendering
  • Region-based partial updates (update_region)
  • Direct RGB565 binary drawing (draw_rgb565_raw)
  • Base64-encoded RLE RGB565 images with nearest-neighbour scaling
  • Fullscreen background image buffer with per-line restore before region renders

Compatible strings: esp_lcd,rgb and waveshare,esp32-s3-touch-lcd-7

3. New port commands

  • update_region — partial screen region update (pre-acked)
  • draw_rgb565_raw — draw raw RGB565 binary directly (pre-acked)

4. Bug fixes

  • Fix missing & 0xFF mask on red channel extraction in rgba8888_color_to_rgb565
  • Fix EPD uFont pixel byte order to write RGBA bytes individually instead of relying on uint32 endianness
  • Add display_color_to_rgb565 and display_color_to_surface helpers for internal display color conversions

Documentation

  • New RGB LCD driver section in docs/display-drivers.md with all options, compat strings, and example
  • update_region and draw_rgb565_raw command documentation
  • Transparent compositing behaviour documented in docs/primitives.md
  • RGB LCD panels listed in README supported hardware

Compatibility

All existing drivers continue to work unchanged. The RGB LCD driver is conditionally compiled for ESP-IDF 5+ only.

Hardware tested

  • Waveshare ESP32-S3 7-inch RGB Touch LCD (800×480, RGB565, 16-bit parallel RGB interface)

drlinux added 6 commits June 17, 2026 14:06
Add display_color_to_rgb565() and display_color_to_surface() helpers
for converting internal display color values (0xRRGGBBAA format) to
RGB565 and surface-ready format.  Fix missing & 0xFF mask on the red
channel extraction in rgba8888_color_to_rgb565().  Use the new helpers
consistently for brcolor and fgcolor fields.

Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org>
When a primitive has transparent background (brcolor == 0), partial-alpha
pixels were previously blended against the current framebuffer content,
which is unreliable with double-buffered region rendering: the work
framebuffer contains uninitialized PSRAM data rather than the intended
lower display-list layer.

Add dcs_lcd_resolve_pixel_rgb565() and per-primitive pixel resolution
functions that walk the display list to find the solid colour from the
next lower opaque item.  Partial-alpha transparent pixels now blend
over that resolved lower-layer pixel instead of framebuffer memory.

This enables correct anti-aliased uFont text rendering over transparent
backgrounds on RGB LCD displays.

Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org>
…l byte order

Add update_region (partial screen update) and draw_rgb565_raw (direct
RGB565 binary draw) to the pre-ack list so callers receive an immediate
acknowledgement without risk of mailbox queue timeout.

Fix epd_draw_pixel to write RGBA bytes individually instead of relying
on uint32_t endianness.  The previous code wrote alpha in the MSB of a
uint32_t, which on little-endian ESP32 placed the R and B channels in
reversed positions relative to the declared RGBA byte order.

Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org>
Add a new display driver for RGB LCD panels using the esp_lcd RGB
interface (ESP-IDF 5+).  The driver supports:

- Double framebuffering in PSRAM for tear-free rendering
- Full-screen and region-based partial updates (update_region)
- Direct raw RGB565 pixel drawing (draw_rgb565_raw)
- base64-encoded RLE RGB565 images with nearest-neighbour scaling
- Fullscreen background image storage in PSRAM with per-line
  restore before each region update
- Frame buffer mirroring across inactive framebuffers

The RGB LCD driver is only compiled when ESP-IDF >= 5.  Compatible
strings: "waveshare,esp32-s3-touch-lcd-7" and "esp_lcd,rgb".

Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org>
…ansparent compositing

Add documentation for the new RGB LCD display driver to
display-drivers.md, including all configuration options, compat
strings, and an example configuration.

Document the update_region and draw_rgb565_raw port commands.

Update the primitives documentation to describe the display-list
transparent background compositing behaviour for anti-aliased
uFont text.

Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org>
Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org>
@drlinux drlinux force-pushed the feature/display-list-compositing-and-rgb-lcd branch from e73730d to 3db31a1 Compare June 17, 2026 12:06
drlinux added 2 commits June 17, 2026 14:06
Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org>
When update_region, draw_rgb565_raw, or the RLE cover path write only
their target region to the work framebuffer and then switch to it,
the rest of the screen content is lost because the work FB contains
stale data.

Fix: copy the full active framebuffer to the work FB before writing
the region pixels, so the entire screen state is preserved across
all framebuffer switches.

Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org>
@drlinux drlinux marked this pull request as draft June 17, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant