Skip to content

Commit adf36b8

Browse files
committed
Support 16/32 bit color depth
Mado currently supports 32-bit color depth for desktop and laptop display devices. To enhance its compatibility across diverse Linux framebuffer environments, I have made the following changes to support both 16-bit and 32-bit color depths: - Distinguish the color format and perform color format conversion. - Examine the correctness of the framebuffer format based on the color format. These updates improve Mado's compatibility, enabling it to be used on devices with low memory overhead, such as the Raspberry Pi, in addition to desktop display devices.
1 parent efe7d49 commit adf36b8

File tree

1 file changed

+43
-7
lines changed

1 file changed

+43
-7
lines changed

backend/fbdev.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
#define FBDEV_DEFAULT "/dev/fb0"
2323
#define SCREEN(x) ((twin_context_t *) x)->screen
2424
#define PRIV(x) ((twin_fbdev_t *) ((twin_context_t *) x)->priv)
25-
25+
#define RGB32_TO_ARGB8565(pixel)(((pixel & 0x00f80000) >> 8) | \
26+
((pixel & 0x0000fc00) >> 5) | \
27+
((pixel & 0x000000f8) >> 3) )
2628
typedef struct {
2729
twin_screen_t *screen;
2830

@@ -59,7 +61,23 @@ static void _twin_fbdev_put_span(twin_coord_t left,
5961
off_t off = top * screen->width + left;
6062
uint32_t *dest =
6163
(uint32_t *) ((uintptr_t) tx->fb_base + (off * sizeof(*dest)));
62-
memcpy(dest, pixels, width * sizeof(*dest));
64+
65+
/* If the framebuffer is in 16 bpp mode, convert each pixel from 32 bpp (ARGB) to 16 bpp (RGB565).
66+
* - Extracts the red, green, and blue channels from the 32-bit color value.
67+
* - Shifts and masks each channel to fit into the 16-bit RGB565 format:
68+
* - 5 bits for red
69+
* - 6 bits for green
70+
* - 5 bits for blue
71+
* - Combines the shifted color values into a single 16-bit pixel.
72+
* If the framebuffer is in 32 bpp mode, directly copy the pixels to the framebuffer.
73+
*/
74+
if(tx->fb_var.bits_per_pixel == 16){
75+
for (int i = 0; i < width; i++) {
76+
dest[i] = RGB32_TO_ARGB8565(pixels[i]);
77+
}
78+
}else{
79+
memcpy(dest, pixels, width * sizeof(*dest));
80+
}
6381
}
6482

6583
static void twin_fbdev_get_screen_size(twin_fbdev_t *tx,
@@ -88,6 +106,18 @@ static bool twin_fbdev_work(void *closure)
88106
return true;
89107
}
90108

109+
static bool fb_is_rgb565(twin_fbdev_t* tx) {
110+
return tx->fb_var.red.offset == 11 && tx->fb_var.red.length == 5 &&
111+
tx->fb_var.green.offset == 5 && tx->fb_var.green.length == 6 &&
112+
tx->fb_var.blue.offset == 0 && tx->fb_var.blue.length == 5;
113+
}
114+
115+
static bool fb_is_argb32(twin_fbdev_t* tx) {
116+
return tx->fb_var.red.offset == 16 && tx->fb_var.red.length == 8 &&
117+
tx->fb_var.green.offset == 8 && tx->fb_var.green.length == 8 &&
118+
tx->fb_var.blue.offset == 0 && tx->fb_var.blue.length == 8;
119+
}
120+
91121
static bool twin_fbdev_apply_config(twin_fbdev_t *tx)
92122
{
93123
/* Read changable information of the framebuffer */
@@ -99,7 +129,6 @@ static bool twin_fbdev_apply_config(twin_fbdev_t *tx)
99129
/* Set the virtual screen size to be the same as the physical screen */
100130
tx->fb_var.xres_virtual = tx->fb_var.xres;
101131
tx->fb_var.yres_virtual = tx->fb_var.yres;
102-
tx->fb_var.bits_per_pixel = 32;
103132
if (ioctl(tx->fb_fd, FBIOPUT_VSCREENINFO, &tx->fb_var) < 0) {
104133
log_error("Failed to set framebuffer mode");
105134
return false;
@@ -111,10 +140,17 @@ static bool twin_fbdev_apply_config(twin_fbdev_t *tx)
111140
return false;
112141
}
113142

114-
/* Check bits per pixel */
115-
if (tx->fb_var.bits_per_pixel != 32) {
116-
log_error("Failed to set framebuffer bpp to 32");
117-
return false;
143+
/* Examine the framebuffer format */
144+
if (tx->fb_var.bits_per_pixel == 16) {
145+
if(!fb_is_rgb565(tx)){
146+
log_error("Invalid framebuffer format for 16 bpp");
147+
return false;
148+
}
149+
}else{
150+
if(!fb_is_argb32(tx)){
151+
log_error("Invalid framebuffer format for 32 bpp");
152+
return false;
153+
}
118154
}
119155

120156
/* Read unchangable information of the framebuffer */

0 commit comments

Comments
 (0)