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+ #define ARGB32_TO_RGB565 (pixel ) \
26+ (((pixel & 0x00f80000) >> 8) | ((pixel & 0x0000fc00) >> 5) | \
27+ ((pixel & 0x000000f8) >> 3))
28+
29+ /* Requires validation in 24-bit per pixel environments. */
30+ #define ARGB32_TO_RGB888 (pixel ) (0xff000000 | (pixel))
31+ #define GET_TWIN_FBDEV (left , top , closure , dest ) \
32+ do { \
33+ twin_screen_t *screen = SCREEN(closure); \
34+ twin_fbdev_t *tx = PRIV(closure); \
35+ off_t off = (top) * (screen->width) + (left); \
36+ *(dest) = \
37+ (uint32_t *) ((uintptr_t) tx->fb_base + (off * sizeof(uint32_t))); \
38+ } while (0)
2539
2640typedef struct {
2741 twin_screen_t * screen ;
@@ -43,22 +57,43 @@ typedef struct {
4357 size_t fb_len ;
4458} twin_fbdev_t ;
4559
46- static void _twin_fbdev_put_span (twin_coord_t left ,
47- twin_coord_t top ,
48- twin_coord_t right ,
49- twin_argb32_t * pixels ,
50- void * closure )
60+ static void _twin_fbdev_put_span16 (twin_coord_t left ,
61+ twin_coord_t top ,
62+ twin_coord_t right ,
63+ twin_argb32_t * pixels ,
64+ void * closure )
5165{
52- twin_screen_t * screen = SCREEN (closure );
53- twin_fbdev_t * tx = PRIV (closure );
66+ uint32_t * dest ;
67+ GET_TWIN_FBDEV (left , top , closure , & dest );
68+ twin_coord_t width = right - left ;
69+ for (int i = 0 ; i < width ; i ++ ) {
70+ dest [i ] = ARGB32_TO_RGB565 (pixels [i ]);
71+ }
72+ }
5473
55- if (tx -> fb_base == MAP_FAILED )
56- return ;
74+ static void _twin_fbdev_put_span24 (twin_coord_t left ,
75+ twin_coord_t top ,
76+ twin_coord_t right ,
77+ twin_argb32_t * pixels ,
78+ void * closure )
79+ {
80+ uint32_t * dest ;
81+ GET_TWIN_FBDEV (left , top , closure , & dest );
82+ twin_coord_t width = right - left ;
83+ for (int i = 0 ; i < width ; i ++ ) {
84+ dest [i ] = ARGB32_TO_RGB888 (pixels [i ]);
85+ }
86+ }
5787
88+ static void _twin_fbdev_put_span32 (twin_coord_t left ,
89+ twin_coord_t top ,
90+ twin_coord_t right ,
91+ twin_argb32_t * pixels ,
92+ void * closure )
93+ {
94+ uint32_t * dest ;
95+ GET_TWIN_FBDEV (left , top , closure , & dest );
5896 twin_coord_t width = right - left ;
59- off_t off = top * screen -> width + left ;
60- uint32_t * dest =
61- (uint32_t * ) ((uintptr_t ) tx -> fb_base + (off * sizeof (* dest )));
6297 memcpy (dest , pixels , width * sizeof (* dest ));
6398}
6499
@@ -88,6 +123,27 @@ static bool twin_fbdev_work(void *closure)
88123 return true;
89124}
90125
126+ static bool twin_fbdev_is_rgb565 (twin_fbdev_t * tx )
127+ {
128+ return tx -> fb_var .red .offset == 11 && tx -> fb_var .red .length == 5 &&
129+ tx -> fb_var .green .offset == 5 && tx -> fb_var .green .length == 6 &&
130+ tx -> fb_var .blue .offset == 0 && tx -> fb_var .blue .length == 5 ;
131+ }
132+
133+ static bool twin_fbdev_is_rgb888 (twin_fbdev_t * tx )
134+ {
135+ return tx -> fb_var .red .offset == 16 && tx -> fb_var .red .length == 8 &&
136+ tx -> fb_var .green .offset == 8 && tx -> fb_var .green .length == 8 &&
137+ tx -> fb_var .blue .offset == 0 && tx -> fb_var .blue .length == 8 ;
138+ }
139+
140+ static bool twin_fbdev_is_argb32 (twin_fbdev_t * tx )
141+ {
142+ return tx -> fb_var .red .offset == 16 && tx -> fb_var .red .length == 8 &&
143+ tx -> fb_var .green .offset == 8 && tx -> fb_var .green .length == 8 &&
144+ tx -> fb_var .blue .offset == 0 && tx -> fb_var .blue .length == 8 ;
145+ }
146+
91147static bool twin_fbdev_apply_config (twin_fbdev_t * tx )
92148{
93149 /* Read changable information of the framebuffer */
@@ -110,6 +166,34 @@ static bool twin_fbdev_apply_config(twin_fbdev_t *tx)
110166 return false;
111167 }
112168
169+ <<<<<<< HEAD
170+ == = == ==
171+ /* Examine the framebuffer format */
172+ switch (tx -> fb_var .bits_per_pixel ) {
173+ case 16 : // RGB565
174+ if (!twin_fbdev_is_rgb565 (tx )) {
175+ log_error ("Invalid framebuffer format for 16 bpp" );
176+ return false;
177+ }
178+ break ;
179+ case 24 : // RGB888
180+ if (!twin_fbdev_is_rgb888 (tx )) {
181+ log_error ("Invalid framebuffer format for 24 bpp" );
182+ return false;
183+ }
184+ break ;
185+ case 32 : // ARGB32
186+ if (!twin_fbdev_is_argb32 (tx )) {
187+ log_error ("Invalid framebuffer format for 32 bpp" );
188+ return false;
189+ }
190+ break ;
191+ default :
192+ log_error ("Unsupported bits per pixel: %d" , tx -> fb_var .bits_per_pixel );
193+ break ;
194+ }
195+
196+ >>>>>>> f56a638 (Support 16 /32 bit color depth )
113197 /* Read unchangable information of the framebuffer */
114198 ioctl (tx -> fb_fd , FBIOGET_FSCREENINFO , & tx -> fb_fix );
115199
@@ -213,9 +297,20 @@ twin_context_t *twin_fbdev_init(int width, int height)
213297 goto bail_vt_fd ;
214298 }
215299
300+ /* Examine if framebuffer mapping is valid */
301+ if (tx -> fb_base == MAP_FAILED ) {
302+ log_error ("Failed to map framebuffer memory" );
303+ return ;
304+ }
305+
216306 /* Create TWIN screen */
217- ctx -> screen =
218- twin_screen_create (width , height , NULL , _twin_fbdev_put_span , ctx );
307+ ctx -> screen = twin_screen_create (
308+ width , height , NULL ,
309+ (tx -> fb_var .bits_per_pixel == 16 ) ? _twin_fbdev_put_span16
310+ : (tx -> fb_var .bits_per_pixel == 24 ) ? _twin_fbdev_put_span24
311+ : (tx -> fb_var .bits_per_pixel == 32 ) ? _twin_fbdev_put_span32
312+ : NULL ,
313+ ctx );
219314
220315 /* Create Linux input system object */
221316 tx -> input = twin_linux_input_create (ctx -> screen );
0 commit comments