diff options
author | Jens Arnold <amiconn@rockbox.org> | 2005-11-28 10:05:45 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2005-11-28 10:05:45 +0000 |
commit | 1d6eeea1e196b6d7beefab70a6ee664340ab7bef (patch) | |
tree | af9accecfd30ea4fab25e56c11ec243922229ba1 /firmware | |
parent | ee76cc3716267720025bab498aa9b8a136f89218 (diff) | |
download | rockbox-1d6eeea1e196b6d7beefab70a6ee664340ab7bef.tar.gz rockbox-1d6eeea1e196b6d7beefab70a6ee664340ab7bef.zip |
16bit LCD driver: faster drawing routines.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8098 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 123 | ||||
-rw-r--r-- | firmware/export/lcd.h | 6 |
2 files changed, 82 insertions, 47 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 7629c889e9..a4ae6cd553 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -145,32 +145,33 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h) | |||
145 | 145 | ||
146 | /*** low-level drawing functions ***/ | 146 | /*** low-level drawing functions ***/ |
147 | 147 | ||
148 | static void setpixel(int x, int y) ICODE_ATTR; | 148 | #define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)]) |
149 | static void setpixel(int x, int y) | 149 | |
150 | static void setpixel(fb_data *address) ICODE_ATTR; | ||
151 | static void setpixel(fb_data *address) | ||
150 | { | 152 | { |
151 | lcd_framebuffer[y][x] = fg_pattern; | 153 | *address = fg_pattern; |
152 | } | 154 | } |
153 | 155 | ||
154 | static void clearpixel(int x, int y) ICODE_ATTR; | 156 | static void clearpixel(fb_data *address) ICODE_ATTR; |
155 | static void clearpixel(int x, int y) | 157 | static void clearpixel(fb_data *address) |
156 | { | 158 | { |
157 | lcd_framebuffer[y][x] = bg_pattern; | 159 | *address = bg_pattern; |
158 | } | 160 | } |
159 | 161 | ||
160 | static void flippixel(int x, int y) ICODE_ATTR; | 162 | static void flippixel(fb_data *address) ICODE_ATTR; |
161 | static void flippixel(int x, int y) | 163 | static void flippixel(fb_data *address) |
162 | { | 164 | { |
163 | lcd_framebuffer[y][x] = ~lcd_framebuffer[y][x]; | 165 | *address = ~(*address); |
164 | } | 166 | } |
165 | 167 | ||
166 | static void nopixel(int x, int y) ICODE_ATTR; | 168 | static void nopixel(fb_data *address) ICODE_ATTR; |
167 | static void nopixel(int x, int y) | 169 | static void nopixel(fb_data *address) |
168 | { | 170 | { |
169 | (void)x; | 171 | (void)address; |
170 | (void)y; | ||
171 | } | 172 | } |
172 | 173 | ||
173 | lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { | 174 | lcd_fastpixelfunc_type* const lcd_fastpixelfuncs[8] = { |
174 | flippixel, nopixel, setpixel, setpixel, | 175 | flippixel, nopixel, setpixel, setpixel, |
175 | nopixel, clearpixel, nopixel, clearpixel | 176 | nopixel, clearpixel, nopixel, clearpixel |
176 | }; | 177 | }; |
@@ -181,7 +182,7 @@ lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { | |||
181 | void lcd_clear_display(void) | 182 | void lcd_clear_display(void) |
182 | { | 183 | { |
183 | fb_data bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; | 184 | fb_data bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; |
184 | fb_data *dst = &lcd_framebuffer[0][0]; | 185 | fb_data *dst = LCDADDR(0, 0); |
185 | fb_data *dst_end = dst + LCD_HEIGHT*LCD_WIDTH; | 186 | fb_data *dst_end = dst + LCD_HEIGHT*LCD_WIDTH; |
186 | 187 | ||
187 | do | 188 | do |
@@ -194,7 +195,7 @@ void lcd_clear_display(void) | |||
194 | void lcd_drawpixel(int x, int y) | 195 | void lcd_drawpixel(int x, int y) |
195 | { | 196 | { |
196 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 197 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) |
197 | lcd_pixelfuncs[drawmode](x, y); | 198 | lcd_fastpixelfuncs[drawmode](LCDADDR(x, y)); |
198 | } | 199 | } |
199 | 200 | ||
200 | /* Draw a line */ | 201 | /* Draw a line */ |
@@ -206,7 +207,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
206 | int d, dinc1, dinc2; | 207 | int d, dinc1, dinc2; |
207 | int x, xinc1, xinc2; | 208 | int x, xinc1, xinc2; |
208 | int y, yinc1, yinc2; | 209 | int y, yinc1, yinc2; |
209 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; | 210 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[drawmode]; |
210 | 211 | ||
211 | deltax = abs(x2 - x1); | 212 | deltax = abs(x2 - x1); |
212 | deltay = abs(y2 - y1); | 213 | deltay = abs(y2 - y1); |
@@ -251,7 +252,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
251 | for (i = 0; i < numpixels; i++) | 252 | for (i = 0; i < numpixels; i++) |
252 | { | 253 | { |
253 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 254 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) |
254 | pfunc(x, y); | 255 | pfunc(LCDADDR(x, y)); |
255 | 256 | ||
256 | if (d < 0) | 257 | if (d < 0) |
257 | { | 258 | { |
@@ -272,7 +273,8 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
272 | void lcd_hline(int x1, int x2, int y) | 273 | void lcd_hline(int x1, int x2, int y) |
273 | { | 274 | { |
274 | int x; | 275 | int x; |
275 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; | 276 | fb_data *dst, *dst_end; |
277 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[drawmode]; | ||
276 | 278 | ||
277 | /* direction flip */ | 279 | /* direction flip */ |
278 | if (x2 < x1) | 280 | if (x2 < x1) |
@@ -292,16 +294,20 @@ void lcd_hline(int x1, int x2, int y) | |||
292 | if (x2 >= LCD_WIDTH) | 294 | if (x2 >= LCD_WIDTH) |
293 | x2 = LCD_WIDTH-1; | 295 | x2 = LCD_WIDTH-1; |
294 | 296 | ||
297 | dst = LCDADDR(x1, y); | ||
298 | dst_end = dst + x2 - x1; | ||
299 | |||
295 | do | 300 | do |
296 | pfunc(x1++, y); | 301 | pfunc(dst++); |
297 | while (x1 <= x2); | 302 | while (dst <= dst_end); |
298 | } | 303 | } |
299 | 304 | ||
300 | /* Draw a vertical line (optimised) */ | 305 | /* Draw a vertical line (optimised) */ |
301 | void lcd_vline(int x, int y1, int y2) | 306 | void lcd_vline(int x, int y1, int y2) |
302 | { | 307 | { |
303 | int y; | 308 | int y; |
304 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; | 309 | fb_data *dst, *dst_end; |
310 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[drawmode]; | ||
305 | 311 | ||
306 | /* direction flip */ | 312 | /* direction flip */ |
307 | if (y2 < y1) | 313 | if (y2 < y1) |
@@ -321,10 +327,15 @@ void lcd_vline(int x, int y1, int y2) | |||
321 | if (y2 >= LCD_HEIGHT) | 327 | if (y2 >= LCD_HEIGHT) |
322 | y2 = LCD_HEIGHT-1; | 328 | y2 = LCD_HEIGHT-1; |
323 | 329 | ||
330 | dst = LCDADDR(x, y1); | ||
331 | dst_end = dst + (y2 - y1) * LCD_WIDTH; | ||
324 | 332 | ||
325 | do | 333 | do |
326 | pfunc(x, y1++); | 334 | { |
327 | while (y1 <= y2); | 335 | pfunc(dst); |
336 | dst += LCD_WIDTH; | ||
337 | } | ||
338 | while (dst <= dst_end); | ||
328 | } | 339 | } |
329 | 340 | ||
330 | /* Draw a rectangular box */ | 341 | /* Draw a rectangular box */ |
@@ -345,8 +356,8 @@ void lcd_drawrect(int x, int y, int width, int height) | |||
345 | /* Fill a rectangular area */ | 356 | /* Fill a rectangular area */ |
346 | void lcd_fillrect(int x, int y, int width, int height) | 357 | void lcd_fillrect(int x, int y, int width, int height) |
347 | { | 358 | { |
348 | int xe, ye, xc; | 359 | fb_data *dst, *dst_end; |
349 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; | 360 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[drawmode]; |
350 | 361 | ||
351 | /* nothing to draw? */ | 362 | /* nothing to draw? */ |
352 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 363 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
@@ -368,14 +379,22 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
368 | width = LCD_WIDTH - x; | 379 | width = LCD_WIDTH - x; |
369 | if (y + height > LCD_HEIGHT) | 380 | if (y + height > LCD_HEIGHT) |
370 | height = LCD_HEIGHT - y; | 381 | height = LCD_HEIGHT - y; |
382 | |||
383 | dst = LCDADDR(x, y); | ||
384 | dst_end = dst + height * LCD_WIDTH; | ||
371 | 385 | ||
372 | ye = y + height; | 386 | do |
373 | xe = x + width; | ||
374 | for(; y < ye; y++) | ||
375 | { | 387 | { |
376 | for(xc = x; xc < xe; xc++) | 388 | fb_data *dst_row = dst; |
377 | pfunc(xc, y); | 389 | fb_data *row_end = dst_row + width; |
390 | |||
391 | do | ||
392 | pfunc(dst_row++); | ||
393 | while (dst_row < row_end); | ||
394 | |||
395 | dst += LCD_WIDTH; | ||
378 | } | 396 | } |
397 | while (dst < dst_end); | ||
379 | } | 398 | } |
380 | 399 | ||
381 | /* About Rockbox' internal monochrome bitmap format: | 400 | /* About Rockbox' internal monochrome bitmap format: |
@@ -397,9 +416,10 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
397 | void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | 416 | void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, |
398 | int stride, int x, int y, int width, int height) | 417 | int stride, int x, int y, int width, int height) |
399 | { | 418 | { |
400 | int xe, ye, yc; | 419 | const unsigned char *src_end; |
401 | lcd_pixelfunc_type *fgfunc; | 420 | fb_data *dst, *dst_end; |
402 | lcd_pixelfunc_type *bgfunc; | 421 | lcd_fastpixelfunc_type *fgfunc; |
422 | lcd_fastpixelfunc_type *bgfunc; | ||
403 | 423 | ||
404 | /* nothing to draw? */ | 424 | /* nothing to draw? */ |
405 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 425 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
@@ -426,24 +446,28 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
426 | 446 | ||
427 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 447 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
428 | src_y &= 7; | 448 | src_y &= 7; |
449 | src_end = src + width; | ||
429 | 450 | ||
430 | xe = x + width; | 451 | dst = LCDADDR(x, y); |
431 | ye = y + height; | 452 | fgfunc = lcd_fastpixelfuncs[drawmode]; |
432 | fgfunc = lcd_pixelfuncs[drawmode]; | 453 | bgfunc = lcd_fastpixelfuncs[drawmode ^ DRMODE_INVERSEVID]; |
433 | bgfunc = lcd_pixelfuncs[drawmode ^ DRMODE_INVERSEVID]; | ||
434 | 454 | ||
435 | for (; x < xe; x++) | 455 | do |
436 | { | 456 | { |
437 | const unsigned char *src_col = src++; | 457 | const unsigned char *src_col = src++; |
438 | unsigned char data = *src_col >> src_y; | 458 | unsigned data = *src_col >> src_y; |
459 | fb_data *dst_col = dst++; | ||
439 | int numbits = 8 - src_y; | 460 | int numbits = 8 - src_y; |
440 | 461 | ||
441 | for (yc = y; yc < ye; yc++) | 462 | dst_end = dst_col + height * LCD_WIDTH; |
463 | do | ||
442 | { | 464 | { |
443 | if (data & 0x01) | 465 | if (data & 0x01) |
444 | fgfunc(x, yc); | 466 | fgfunc(dst_col); |
445 | else | 467 | else |
446 | bgfunc(x, yc); | 468 | bgfunc(dst_col); |
469 | |||
470 | dst_col += LCD_WIDTH; | ||
447 | 471 | ||
448 | data >>= 1; | 472 | data >>= 1; |
449 | if (--numbits == 0) | 473 | if (--numbits == 0) |
@@ -453,7 +477,9 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
453 | numbits = 8; | 477 | numbits = 8; |
454 | } | 478 | } |
455 | } | 479 | } |
480 | while (dst_col < dst_end); | ||
456 | } | 481 | } |
482 | while (src < src_end); | ||
457 | } | 483 | } |
458 | 484 | ||
459 | /* Draw a full monochrome bitmap */ | 485 | /* Draw a full monochrome bitmap */ |
@@ -469,7 +495,7 @@ void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
469 | void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | 495 | void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, |
470 | int stride, int x, int y, int width, int height) | 496 | int stride, int x, int y, int width, int height) |
471 | { | 497 | { |
472 | int ye; | 498 | fb_data *dst, *dst_end; |
473 | 499 | ||
474 | /* nothing to draw? */ | 500 | /* nothing to draw? */ |
475 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 501 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
@@ -495,13 +521,16 @@ void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
495 | height = LCD_HEIGHT - y; | 521 | height = LCD_HEIGHT - y; |
496 | 522 | ||
497 | src += stride * src_y + src_x; /* move starting point */ | 523 | src += stride * src_y + src_x; /* move starting point */ |
498 | ye = y + height; | 524 | dst = LCDADDR(x, y); |
525 | dst_end = dst + height * LCD_WIDTH; | ||
499 | 526 | ||
500 | for (; y < ye; y++) | 527 | do |
501 | { | 528 | { |
502 | memcpy(&lcd_framebuffer[y][x], src, width * sizeof(fb_data)); | 529 | memcpy(dst, src, width * sizeof(fb_data)); |
503 | src += stride; | 530 | src += stride; |
531 | dst += LCD_WIDTH; | ||
504 | } | 532 | } |
533 | while (dst < dst_end); | ||
505 | } | 534 | } |
506 | 535 | ||
507 | /* Draw a full native bitmap */ | 536 | /* Draw a full native bitmap */ |
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index bd9c49fee7..46f33d522a 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -135,6 +135,9 @@ extern void lcd_jump_scroll_delay(int ms); | |||
135 | /* Low-level drawing function types */ | 135 | /* Low-level drawing function types */ |
136 | typedef void lcd_pixelfunc_type(int x, int y); | 136 | typedef void lcd_pixelfunc_type(int x, int y); |
137 | typedef void lcd_blockfunc_type(unsigned char *address, unsigned mask, unsigned bits); | 137 | typedef void lcd_blockfunc_type(unsigned char *address, unsigned mask, unsigned bits); |
138 | #if LCD_DEPTH >= 8 | ||
139 | typedef void lcd_fastpixelfunc_type(fb_data *address); | ||
140 | #endif | ||
138 | 141 | ||
139 | #ifdef HAVE_LCD_BITMAP | 142 | #ifdef HAVE_LCD_BITMAP |
140 | 143 | ||
@@ -199,6 +202,9 @@ extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); | |||
199 | /* low level drawing function pointer arrays */ | 202 | /* low level drawing function pointer arrays */ |
200 | extern lcd_pixelfunc_type* const lcd_pixelfuncs[8]; | 203 | extern lcd_pixelfunc_type* const lcd_pixelfuncs[8]; |
201 | extern lcd_blockfunc_type* const lcd_blockfuncs[8]; | 204 | extern lcd_blockfunc_type* const lcd_blockfuncs[8]; |
205 | #if LCD_DEPTH >= 8 | ||
206 | extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs[8]; | ||
207 | #endif | ||
202 | 208 | ||
203 | extern void lcd_drawpixel(int x, int y); | 209 | extern void lcd_drawpixel(int x, int y); |
204 | extern void lcd_drawline(int x1, int y1, int x2, int y2); | 210 | extern void lcd_drawline(int x1, int y1, int x2, int y2); |