Skip to content

Commit da07048

Browse files
drlinuxcursoragent
andcommitted
fix(rgb_lcd): device-proven compositor, uFont color, and draw_buffer
Blend transparent RGBA pixels over restored background with optional lower-layer resolve instead of stalling on alpha==0. Restore RRGGBBAA uFont fgcolor layout. Accept draw_buffer binary tuples and persist partial cover draws into background_buffer. Signed-off-by: Ibrahim YILMAZ <ibrahim@drlinux.org> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 171539a commit da07048

3 files changed

Lines changed: 61 additions & 29 deletions

File tree

dcs_lcd_draw.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,13 @@ int dcs_lcd_draw_image_x(const struct DCSLCDScreen *screen,
249249
pixmem16[drawn_pixels] = rgb565_color_to_surface(blended);
250250
} else if (alpha > 0) {
251251
uint16_t color = rgba8888_color_to_rgb565(img_pixel);
252-
uint16_t lower = 0;
253-
(void) dcs_lcd_resolve_pixel_rgb565(screen, xpos + drawn_pixels, ypos, items, items_len, item_index + 1, &lower);
252+
uint16_t lower = rgb565_color_to_surface(pixmem16[drawn_pixels]);
253+
uint16_t resolved = 0;
254+
if (dcs_lcd_resolve_pixel_rgb565(screen, xpos + drawn_pixels, ypos, items, items_len, item_index + 1, &resolved)) {
255+
lower = resolved;
256+
}
254257
uint16_t blended = alpha_blend_rgb565(color, lower, alpha);
255258
pixmem16[drawn_pixels] = rgb565_color_to_surface(blended);
256-
} else {
257-
return drawn_pixels;
258259
}
259260
drawn_pixels++;
260261
pixels++;
@@ -427,12 +428,13 @@ int dcs_lcd_draw_scaled_cropped_img_x(const struct DCSLCDScreen *screen,
427428
pixmem16[drawn_pixels] = rgb565_color_to_surface(blended);
428429
} else if (alpha > 0) {
429430
uint16_t color = rgba8888_color_to_rgb565(img_pixel);
430-
uint16_t lower = 0;
431-
(void) dcs_lcd_resolve_pixel_rgb565(screen, xpos + drawn_pixels, ypos, items, items_len, item_index + 1, &lower);
431+
uint16_t lower = rgb565_color_to_surface(pixmem16[drawn_pixels]);
432+
uint16_t resolved = 0;
433+
if (dcs_lcd_resolve_pixel_rgb565(screen, xpos + drawn_pixels, ypos, items, items_len, item_index + 1, &resolved)) {
434+
lower = resolved;
435+
}
432436
uint16_t blended = alpha_blend_rgb565(color, lower, alpha);
433437
pixmem16[drawn_pixels] = rgb565_color_to_surface(blended);
434-
} else {
435-
return drawn_pixels;
436438
}
437439
drawn_pixels++;
438440
int next_rel_x = j + 1;

display_items.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ struct Surface
3636
int width;
3737
int height;
3838
void *buffer;
39-
uint32_t fg_color; // RGB bytes in 0x00BBGGRR order; alpha is cleared
40-
// so epd_draw_pixel can append per-pixel alpha.
39+
uint32_t fg_color; // 0xRRGGBBAA from Erlang color << 8 | 0xFF
4140
};
4241

4342
#define BPP 4
@@ -60,9 +59,9 @@ void epd_draw_pixel(int xpos, int ypos, uint8_t color, void *buffer)
6059
// the foreground RGB on transparent with anti-aliased alpha
6160
// derived from the inverted grayscale.
6261
uint8_t alpha = (15 - (color >> 4)) * 17;
63-
pixel[0] = surface->fg_color & 0xFFu;
64-
pixel[1] = (surface->fg_color >> 8) & 0xFFu;
65-
pixel[2] = (surface->fg_color >> 16) & 0xFFu;
62+
pixel[0] = (surface->fg_color >> 24) & 0xFFu;
63+
pixel[1] = (surface->fg_color >> 16) & 0xFFu;
64+
pixel[2] = (surface->fg_color >> 8) & 0xFFu;
6665
pixel[3] = alpha;
6766
}
6867
#endif /* ENABLE_UFONT */
@@ -97,8 +96,8 @@ static bool parse_image_tuple(term img, Context *ctx, int *width, int *height, c
9796

9897
size_t expected = (size_t) *width * (size_t) *height * bytes_per_pixel;
9998
if (term_binary_size(data_term) < expected) {
100-
fprintf(stderr, "image binary too small (%zu < %zu)\n",
101-
term_binary_size(data_term), expected);
99+
fprintf(stderr, "image binary too small (%lu < %zu)\n",
100+
(unsigned long) term_binary_size(data_term), expected);
102101
return false;
103102
}
104103

@@ -272,12 +271,7 @@ void display_items_init_item(BaseDisplayItem *item, term req, Context *ctx)
272271
return;
273272
}
274273
memset(surface.buffer, 0, surface_bytes);
275-
// Convert Erlang fgcolor (0xRRGGBBAA) to RGBA8888 little-
276-
// endian byte order (R in low byte, alpha byte cleared) so
277-
// epd_draw_pixel can OR it with the per-pixel alpha.
278-
surface.fg_color = ((fgcolor >> 24) & 0xFFu)
279-
| (((fgcolor >> 16) & 0xFFu) << 8)
280-
| (((fgcolor >> 8) & 0xFFu) << 16);
274+
surface.fg_color = fgcolor;
281275
int text_x = 0;
282276
int text_y = loaded_font->ascender;
283277
enum EpdDrawError res = epd_write_default(loaded_font, text, &text_x, &text_y, &surface);

rgb_lcd_display_driver.c

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,24 @@ static void do_draw_rgb565_rle_base64(Context *ctx, int x, int y, int width, int
753753
do_draw_rgb565_rle_base64_scaled(ctx, x, y, width, height, width, height, b64_term);
754754
}
755755

756+
static void maybe_store_cover_background(
757+
struct RGBLCDDriver *driver, int x, int y, int width, int height, const uint16_t *pixels)
758+
{
759+
if (!driver->background_buffer || x < 0 || y < 0 || width <= 0 || height <= 0) {
760+
return;
761+
}
762+
if (x + width > driver->screen.w || y + height > driver->screen.h) {
763+
return;
764+
}
765+
766+
for (int row = 0; row < height; row++) {
767+
memcpy(
768+
driver->background_buffer + ((size_t) (y + row) * driver->screen.w) + x,
769+
pixels + ((size_t) row * width),
770+
(size_t) width * sizeof(uint16_t));
771+
}
772+
}
773+
756774
static void draw_rgb565_region(struct RGBLCDDriver *driver, int x, int y, int width, int height, const uint16_t *pixels)
757775
{
758776
if (driver->framebuffer_count > 1) {
@@ -785,6 +803,7 @@ static void draw_rgb565_region(struct RGBLCDDriver *driver, int x, int y, int wi
785803
mirror_region_to_inactive_framebuffers(driver, x, y, width, height, pixels);
786804
}
787805

806+
maybe_store_cover_background(driver, x, y, width, height, pixels);
788807
ESP_LOGI(TAG, "draw_rgb565_region: %dx%d pixels at (%d,%d)", width, height, x, y);
789808
}
790809

@@ -840,14 +859,31 @@ static void process_message(Message *message, Context *ctx)
840859
int y = term_to_int(term_get_tuple_element(req, 2));
841860
int width = term_to_int(term_get_tuple_element(req, 3));
842861
int height = term_to_int(term_get_tuple_element(req, 4));
843-
unsigned long addr_low = term_to_int(term_get_tuple_element(req, 5));
844-
unsigned long addr_high = term_to_int(term_get_tuple_element(req, 6));
845-
const uint16_t *data = (const uint16_t *) (addr_low | (addr_high << 16));
846-
847-
if (!data || width <= 0 || height <= 0 || x < 0 || y < 0
848-
|| x + width > driver->screen.w || y + height > driver->screen.h) {
849-
ESP_LOGE(TAG, "Invalid draw_buffer arguments.");
850-
return;
862+
term payload = term_get_tuple_element(req, 5);
863+
const uint16_t *data = NULL;
864+
865+
if (term_is_binary(payload)) {
866+
size_t expected = (size_t) width * (size_t) height * 2;
867+
if (width <= 0 || height <= 0 || x < 0 || y < 0
868+
|| x + width > driver->screen.w || y + height > driver->screen.h
869+
|| term_binary_size(payload) < expected) {
870+
ESP_LOGE(TAG, "Invalid draw_buffer binary arguments.");
871+
return;
872+
}
873+
data = (const uint16_t *) term_binary_data(payload);
874+
} else {
875+
if (term_get_tuple_arity(req) < 7) {
876+
ESP_LOGE(TAG, "Invalid draw_buffer pointer arguments.");
877+
return;
878+
}
879+
unsigned long addr_low = term_to_int(payload);
880+
unsigned long addr_high = term_to_int(term_get_tuple_element(req, 6));
881+
data = (const uint16_t *) (addr_low | (addr_high << 16));
882+
if (!data || width <= 0 || height <= 0 || x < 0 || y < 0
883+
|| x + width > driver->screen.w || y + height > driver->screen.h) {
884+
ESP_LOGE(TAG, "Invalid draw_buffer pointer arguments.");
885+
return;
886+
}
851887
}
852888

853889
draw_rgb565_region(driver, x, y, width, height, data);

0 commit comments

Comments
 (0)