22
22
#define FBDEV_DEFAULT "/dev/fb0"
23
23
#define SCREEN (x ) ((twin_context_t *) x)->screen
24
24
#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)
25
39
26
40
typedef struct {
27
41
twin_screen_t * screen ;
@@ -43,22 +57,43 @@ typedef struct {
43
57
size_t fb_len ;
44
58
} twin_fbdev_t ;
45
59
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 )
51
65
{
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
+ }
54
73
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
+ }
57
87
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 );
58
96
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 )));
62
97
memcpy (dest , pixels , width * sizeof (* dest ));
63
98
}
64
99
@@ -88,6 +123,27 @@ static bool twin_fbdev_work(void *closure)
88
123
return true;
89
124
}
90
125
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
+
91
147
static bool twin_fbdev_apply_config (twin_fbdev_t * tx )
92
148
{
93
149
/* Read changable information of the framebuffer */
@@ -110,6 +166,34 @@ static bool twin_fbdev_apply_config(twin_fbdev_t *tx)
110
166
return false;
111
167
}
112
168
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 )
113
197
/* Read unchangable information of the framebuffer */
114
198
ioctl (tx -> fb_fd , FBIOGET_FSCREENINFO , & tx -> fb_fix );
115
199
@@ -213,9 +297,20 @@ twin_context_t *twin_fbdev_init(int width, int height)
213
297
goto bail_vt_fd ;
214
298
}
215
299
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
+
216
306
/* 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 );
219
314
220
315
/* Create Linux input system object */
221
316
tx -> input = twin_linux_input_create (ctx -> screen );
0 commit comments