1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Additional LCD routines not present in the rockbox core
13 * Copyright (C) 2005 Jens Arnold
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
27 #ifdef HAVE_LCD_BITMAP
30 /* sort the given coordinates by increasing x value */
31 static void sort_points_by_increasing_x(int* x1
, int* y1
,
38 if (*x2
< *x3
) /* x2 < x3 < x1 */
40 x
= *x1
; *x1
= *x2
; *x2
= *x3
; *x3
= x
;
41 y
= *y1
; *y1
= *y2
; *y2
= *y3
; *y3
= y
;
43 else if (*x2
> *x1
) /* x3 < x1 < x2 */
45 x
= *x1
; *x1
= *x3
; *x3
= *x2
; *x2
= x
;
46 y
= *y1
; *y1
= *y3
; *y3
= *y2
; *y2
= y
;
48 else /* x3 <= x2 <= x1 */
50 x
= *x1
; *x1
= *x3
; *x3
= x
;
51 y
= *y1
; *y1
= *y3
; *y3
= y
;
56 if (*x2
< *x1
) /* x2 < x1 <= x3 */
58 x
= *x1
; *x1
= *x2
; *x2
= x
;
59 y
= *y1
; *y1
= *y2
; *y2
= y
;
61 else if (*x2
> *x3
) /* x1 <= x3 < x2 */
63 x
= *x2
; *x2
= *x3
; *x3
= x
;
64 y
= *y2
; *y2
= *y3
; *y3
= y
;
66 /* else already sorted */
70 #define sort_points_by_increasing_y(x1, y1, x2, y2, x3, y3) \
71 sort_points_by_increasing_x(y1, x1, y2, x2, y3, x3)
73 /* draw a filled triangle, using horizontal lines for speed */
74 static void xlcd_filltriangle_horizontal(struct screen
* display
,
79 long fp_x1
, fp_x2
, fp_dx1
, fp_dx2
;
81 sort_points_by_increasing_y(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
);
83 if (y1
< y3
) /* draw */
85 fp_dx1
= ((x3
- x1
) << 16) / (y3
- y1
);
86 fp_x1
= (x1
<< 16) + (1<<15) + (fp_dx1
>> 1);
88 if (y1
< y2
) /* first part */
90 fp_dx2
= ((x2
- x1
) << 16) / (y2
- y1
);
91 fp_x2
= (x1
<< 16) + (1<<15) + (fp_dx2
>> 1);
92 for (y
= y1
; y
< y2
; y
++)
94 display
->hline(fp_x1
>> 16, fp_x2
>> 16, y
);
99 if (y2
< y3
) /* second part */
101 fp_dx2
= ((x3
- x2
) << 16) / (y3
- y2
);
102 fp_x2
= (x2
<< 16) + (1<<15) + (fp_dx2
>> 1);
103 for (y
= y2
; y
< y3
; y
++)
105 display
->hline(fp_x1
>> 16, fp_x2
>> 16, y
);
113 /* draw a filled triangle, using vertical lines for speed */
114 static void xlcd_filltriangle_vertical(struct screen
* display
,
119 long fp_y1
, fp_y2
, fp_dy1
, fp_dy2
;
121 sort_points_by_increasing_x(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
);
123 if (x1
< x3
) /* draw */
125 fp_dy1
= ((y3
- y1
) << 16) / (x3
- x1
);
126 fp_y1
= (y1
<< 16) + (1<<15) + (fp_dy1
>> 1);
128 if (x1
< x2
) /* first part */
130 fp_dy2
= ((y2
- y1
) << 16) / (x2
- x1
);
131 fp_y2
= (y1
<< 16) + (1<<15) + (fp_dy2
>> 1);
132 for (x
= x1
; x
< x2
; x
++)
134 display
->vline(x
, fp_y1
>> 16, fp_y2
>> 16);
139 if (x2
< x3
) /* second part */
141 fp_dy2
= ((y3
- y2
) << 16) / (x3
- x2
);
142 fp_y2
= (y2
<< 16) + (1<<15) + (fp_dy2
>> 1);
143 for (x
= x2
; x
< x3
; x
++)
145 display
->vline(x
, fp_y1
>> 16, fp_y2
>> 16);
153 void xlcd_filltriangle(int x1
, int y1
,
157 /* default is main screen */
158 xlcd_filltriangle_screen(rb
->screens
[SCREEN_MAIN
],
159 x1
, y1
, x2
, y2
, x3
, y3
);
162 void xlcd_filltriangle_screen(struct screen
* display
,
167 if(display
->pixel_format
==HORIZONTAL_PACKING
|| display
->depth
>=8)
168 xlcd_filltriangle_horizontal(display
, x1
, y1
, x2
, y2
, x3
, y3
);
170 xlcd_filltriangle_vertical(display
, x1
, y1
, x2
, y2
, x3
, y3
);
175 #ifdef HAVE_LCD_COLOR
176 static const fb_data graylut
[256] = {
177 #if LCD_PIXELFORMAT == RGB565
178 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0821, 0x0821, 0x0841,
179 0x0841, 0x0841, 0x0841, 0x0861, 0x0861, 0x1062, 0x1062, 0x1082,
180 0x1082, 0x1082, 0x1082, 0x10a2, 0x10a2, 0x18a3, 0x18a3, 0x18c3,
181 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x18e3, 0x20e4, 0x20e4, 0x2104,
182 0x2104, 0x2104, 0x2104, 0x2124, 0x2124, 0x2124, 0x2925, 0x2945,
183 0x2945, 0x2945, 0x2945, 0x2965, 0x2965, 0x2965, 0x3166, 0x3186,
184 0x3186, 0x3186, 0x3186, 0x31a6, 0x31a6, 0x31a6, 0x39a7, 0x39c7,
185 0x39c7, 0x39c7, 0x39c7, 0x39e7, 0x39e7, 0x39e7, 0x41e8, 0x4208,
186 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4a29, 0x4a49,
187 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a,
188 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5aab,
189 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0x62ec,
190 0x630c, 0x630c, 0x630c, 0x630c, 0x632c, 0x632c, 0x632c, 0x6b2d,
191 0x6b4d, 0x6b4d, 0x6b4d, 0x6b4d, 0x6b6d, 0x6b6d, 0x6b6d, 0x6b6d,
192 0x738e, 0x738e, 0x738e, 0x738e, 0x73ae, 0x73ae, 0x73ae, 0x73ae,
193 0x7bcf, 0x7bcf, 0x7bcf, 0x7bcf, 0x7bef, 0x7bef, 0x7bef, 0x7bef,
194 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8430, 0x8430, 0x8430,
195 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c71, 0x8c71, 0x8c71, 0x8c71,
196 0x9492, 0x9492, 0x9492, 0x9492, 0x94b2, 0x94b2, 0x94b2, 0x94b2,
197 0x94d2, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cf3, 0x9cf3, 0x9cf3, 0x9cf3,
198 0x9d13, 0xa514, 0xa514, 0xa514, 0xa534, 0xa534, 0xa534, 0xa534,
199 0xa554, 0xad55, 0xad55, 0xad55, 0xad55, 0xad75, 0xad75, 0xad75,
200 0xad75, 0xb596, 0xb596, 0xb596, 0xb596, 0xb5b6, 0xb5b6, 0xb5b6,
201 0xb5b6, 0xb5d6, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdf7, 0xbdf7, 0xbdf7,
202 0xbdf7, 0xbe17, 0xc618, 0xc618, 0xc618, 0xc638, 0xc638, 0xc638,
203 0xc638, 0xc658, 0xce59, 0xce59, 0xce59, 0xce79, 0xce79, 0xce79,
204 0xce79, 0xce99, 0xd69a, 0xd69a, 0xd69a, 0xd6ba, 0xd6ba, 0xd6ba,
205 0xd6ba, 0xd6da, 0xd6da, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb,
206 0xdefb, 0xdf1b, 0xdf1b, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c,
207 0xe73c, 0xe75c, 0xe75c, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d,
208 0xef7d, 0xef9d, 0xef9d, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be,
209 0xf7be, 0xf7de, 0xf7de, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff
210 #elif LCD_PIXELFORMAT == RGB565SWAPPED
211 0x0000, 0x0000, 0x0000, 0x2000, 0x2000, 0x2108, 0x2108, 0x4108,
212 0x4108, 0x4108, 0x4108, 0x6108, 0x6108, 0x6210, 0x6210, 0x8210,
213 0x8210, 0x8210, 0x8210, 0xa210, 0xa210, 0xa318, 0xa318, 0xc318,
214 0xc318, 0xc318, 0xc318, 0xe318, 0xe318, 0xe420, 0xe420, 0x0421,
215 0x0421, 0x0421, 0x0421, 0x2421, 0x2421, 0x2421, 0x2529, 0x4529,
216 0x4529, 0x4529, 0x4529, 0x6529, 0x6529, 0x6529, 0x6631, 0x8631,
217 0x8631, 0x8631, 0x8631, 0xa631, 0xa631, 0xa631, 0xa739, 0xc739,
218 0xc739, 0xc739, 0xc739, 0xe739, 0xe739, 0xe739, 0xe841, 0x0842,
219 0x0842, 0x0842, 0x0842, 0x2842, 0x2842, 0x2842, 0x294a, 0x494a,
220 0x494a, 0x494a, 0x494a, 0x694a, 0x694a, 0x694a, 0x694a, 0x8a52,
221 0x8a52, 0x8a52, 0x8a52, 0xaa52, 0xaa52, 0xaa52, 0xaa52, 0xab5a,
222 0xcb5a, 0xcb5a, 0xcb5a, 0xcb5a, 0xeb5a, 0xeb5a, 0xeb5a, 0xec62,
223 0x0c63, 0x0c63, 0x0c63, 0x0c63, 0x2c63, 0x2c63, 0x2c63, 0x2d6b,
224 0x4d6b, 0x4d6b, 0x4d6b, 0x4d6b, 0x6d6b, 0x6d6b, 0x6d6b, 0x6d6b,
225 0x8e73, 0x8e73, 0x8e73, 0x8e73, 0xae73, 0xae73, 0xae73, 0xae73,
226 0xcf7b, 0xcf7b, 0xcf7b, 0xcf7b, 0xef7b, 0xef7b, 0xef7b, 0xef7b,
227 0x1084, 0x1084, 0x1084, 0x1084, 0x3084, 0x3084, 0x3084, 0x3084,
228 0x518c, 0x518c, 0x518c, 0x518c, 0x718c, 0x718c, 0x718c, 0x718c,
229 0x9294, 0x9294, 0x9294, 0x9294, 0xb294, 0xb294, 0xb294, 0xb294,
230 0xd294, 0xd39c, 0xd39c, 0xd39c, 0xf39c, 0xf39c, 0xf39c, 0xf39c,
231 0x139d, 0x14a5, 0x14a5, 0x14a5, 0x34a5, 0x34a5, 0x34a5, 0x34a5,
232 0x54a5, 0x55ad, 0x55ad, 0x55ad, 0x55ad, 0x75ad, 0x75ad, 0x75ad,
233 0x75ad, 0x96b5, 0x96b5, 0x96b5, 0x96b5, 0xb6b5, 0xb6b5, 0xb6b5,
234 0xb6b5, 0xd6b5, 0xd7bd, 0xd7bd, 0xd7bd, 0xf7bd, 0xf7bd, 0xf7bd,
235 0xf7bd, 0x17be, 0x18c6, 0x18c6, 0x18c6, 0x38c6, 0x38c6, 0x38c6,
236 0x38c6, 0x58c6, 0x59ce, 0x59ce, 0x59ce, 0x79ce, 0x79ce, 0x79ce,
237 0x79ce, 0x99ce, 0x9ad6, 0x9ad6, 0x9ad6, 0xbad6, 0xbad6, 0xbad6,
238 0xbad6, 0xdad6, 0xdad6, 0xdbde, 0xdbde, 0xfbde, 0xfbde, 0xfbde,
239 0xfbde, 0x1bdf, 0x1bdf, 0x1ce7, 0x1ce7, 0x3ce7, 0x3ce7, 0x3ce7,
240 0x3ce7, 0x5ce7, 0x5ce7, 0x5def, 0x5def, 0x7def, 0x7def, 0x7def,
241 0x7def, 0x9def, 0x9def, 0x9ef7, 0x9ef7, 0xbef7, 0xbef7, 0xbef7,
242 0xbef7, 0xdef7, 0xdef7, 0xdfff, 0xdfff, 0xffff, 0xffff, 0xffff
243 #endif /* LCD_PIXELFORMAT */
245 #endif /* HAVE_LCD_COLOR */
247 /* Draw a partial greyscale bitmap, canonical 8 bit format */
248 void xlcd_gray_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
249 int stride
, int x
, int y
, int width
, int height
)
251 const unsigned char *src_end
;
254 /* nothing to draw? */
255 if ((width
<= 0) || (height
<= 0) || (x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
256 || (x
+ width
<= 0) || (y
+ height
<= 0))
272 if (x
+ width
> LCD_WIDTH
)
273 width
= LCD_WIDTH
- x
;
274 if (y
+ height
> LCD_HEIGHT
)
275 height
= LCD_HEIGHT
- y
;
277 src
+= stride
* src_y
+ src_x
; /* move starting point */
278 src_end
= src
+ stride
* height
;
279 dst
= rb
->lcd_framebuffer
+ LCD_WIDTH
* y
+ x
;
283 const unsigned char *src_row
= src
;
284 const unsigned char *row_end
= src_row
+ width
;
285 fb_data
*dst_row
= dst
;
287 #ifdef HAVE_LCD_COLOR
289 *dst_row
++ = graylut
[*src_row
++];
290 while (src_row
< row_end
);
296 while (src
< src_end
);
299 /* Draw a full greyscale bitmap, canonical 8 bit format */
300 void xlcd_gray_bitmap(const unsigned char *src
, int x
, int y
, int width
,
303 xlcd_gray_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
306 #ifdef HAVE_LCD_COLOR
307 /* Draw a partial colour bitmap, canonical 24 bit RGB format */
308 void xlcd_color_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
309 int stride
, int x
, int y
, int width
, int height
)
311 const unsigned char *src_end
;
314 /* nothing to draw? */
315 if ((width
<= 0) || (height
<= 0) || (x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
316 || (x
+ width
<= 0) || (y
+ height
<= 0))
332 if (x
+ width
> LCD_WIDTH
)
333 width
= LCD_WIDTH
- x
;
334 if (y
+ height
> LCD_HEIGHT
)
335 height
= LCD_HEIGHT
- y
;
337 src
+= 3 * (stride
* src_y
+ src_x
); /* move starting point */
338 src_end
= src
+ 3 * stride
* height
;
339 dst
= rb
->lcd_framebuffer
+ LCD_WIDTH
* y
+ x
;
343 const unsigned char *src_row
= src
;
344 const unsigned char *row_end
= src_row
+ 3 * width
;
345 fb_data
*dst_row
= dst
;
348 { /* only RGB565 and RGB565SWAPPED so far */
349 unsigned red
= 31 * (*src_row
++) + 127;
350 unsigned green
= 63 * (*src_row
++) + 127;
351 unsigned blue
= 31 * (*src_row
++) + 127;
353 red
= (red
+ (red
>> 8)) >> 8; /* approx red /= 255: */
354 green
= (green
+ (green
>> 8)) >> 8; /* approx green /= 255: */
355 blue
= (blue
+ (blue
>> 8)) >> 8; /* approx blue /= 255: */
357 #if LCD_PIXELFORMAT == RGB565
358 *dst_row
++ = (red
<< 11) | (green
<< 5) | blue
;
359 #elif LCD_PIXELFORMAT == RGB565SWAPPED
360 *dst_row
++ = swap16((red
<< 11) | (green
<< 5) | blue
);
363 while (src_row
< row_end
);
368 while (src
< src_end
);
371 /* Draw a full colour bitmap, canonical 24 bit RGB format */
372 void xlcd_color_bitmap(const unsigned char *src
, int x
, int y
, int width
,
375 xlcd_color_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
377 #endif /* HAVE_LCD_COLOR */
379 #endif /* LCD_DEPTH >= 8 */
381 #endif /* HAVE_LCD_BITMAP */