summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2009-03-08 17:22:17 +0000
committerJens Arnold <amiconn@rockbox.org>2009-03-08 17:22:17 +0000
commit9eeead922ad958cae62015eec8156e47ca47fc58 (patch)
treef920b48878aae27cf77f301396eb811d9e8a187a
parent87d1744e91e016b650a3c7826a93cd6afcaf0383 (diff)
downloadrockbox-9eeead922ad958cae62015eec8156e47ca47fc58.tar.gz
rockbox-9eeead922ad958cae62015eec8156e47ca47fc58.zip
Optimize hline, fillrect and mono bitmap drawing for chunky displays (16 bit colour and greylib). Speeds up text rendering by 20..45% on colour coldfire, by 30..50% on colour ARM, and is noticeable in archos pictureflow.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20242 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/lib/grey_draw.c160
-rw-r--r--firmware/drivers/lcd-16bit.c193
2 files changed, 246 insertions, 107 deletions
diff --git a/apps/plugins/lib/grey_draw.c b/apps/plugins/lib/grey_draw.c
index 286cae06a4..65f2211b7f 100644
--- a/apps/plugins/lib/grey_draw.c
+++ b/apps/plugins/lib/grey_draw.c
@@ -155,8 +155,7 @@ void grey_hline(int x1, int x2, int y)
155 int value = 0; 155 int value = 0;
156 unsigned char *dst; 156 unsigned char *dst;
157 bool fillopt = false; 157 bool fillopt = false;
158 void (*pfunc)(unsigned char *address); 158
159
160 /* direction flip */ 159 /* direction flip */
161 if (x2 < x1) 160 if (x2 < x1)
162 { 161 {
@@ -170,12 +169,7 @@ void grey_hline(int x1, int x2, int y)
170 || (x1 >= _grey_info.width) || (x2 < 0)) 169 || (x1 >= _grey_info.width) || (x2 < 0))
171 return; 170 return;
172 171
173 /* clipping */ 172 /* drawmode and optimisation */
174 if (x1 < 0)
175 x1 = 0;
176 if (x2 >= _grey_info.width)
177 x2 = _grey_info.width - 1;
178
179 if (_grey_info.drawmode & DRMODE_INVERSEVID) 173 if (_grey_info.drawmode & DRMODE_INVERSEVID)
180 { 174 {
181 if (_grey_info.drawmode & DRMODE_BG) 175 if (_grey_info.drawmode & DRMODE_BG)
@@ -192,17 +186,25 @@ void grey_hline(int x1, int x2, int y)
192 value = _grey_info.fg_brightness; 186 value = _grey_info.fg_brightness;
193 } 187 }
194 } 188 }
195 pfunc = _grey_pixelfuncs[_grey_info.drawmode]; 189 if (!fillopt && _grey_info.drawmode != DRMODE_COMPLEMENT)
190 return;
191
192 /* clipping */
193 if (x1 < 0)
194 x1 = 0;
195 if (x2 >= _grey_info.width)
196 x2 = _grey_info.width - 1;
197
196 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x1]; 198 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x1];
197 199
198 if (fillopt) 200 if (fillopt)
199 rb->memset(dst, value, x2 - x1 + 1); 201 rb->memset(dst, value, x2 - x1 + 1);
200 else 202 else /* DRMODE_COMPLEMENT */
201 { 203 {
202 unsigned char *dst_end = dst + x2 - x1; 204 unsigned char *dst_end = dst + x2 - x1;
203 do 205 do
204 pfunc(dst++); 206 *dst = ~(*dst);
205 while (dst <= dst_end); 207 while (++dst <= dst_end);
206 } 208 }
207} 209}
208 210
@@ -335,29 +337,13 @@ void grey_fillrect(int x, int y, int width, int height)
335 int value = 0; 337 int value = 0;
336 unsigned char *dst, *dst_end; 338 unsigned char *dst, *dst_end;
337 bool fillopt = false; 339 bool fillopt = false;
338 void (*pfunc)(unsigned char *address);
339 340
340 /* nothing to draw? */ 341 /* nothing to draw? */
341 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) 342 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
342 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0)) 343 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
343 return; 344 return;
344 345
345 /* clipping */ 346 /* drawmode and optimisation */
346 if (x < 0)
347 {
348 width += x;
349 x = 0;
350 }
351 if (y < 0)
352 {
353 height += y;
354 y = 0;
355 }
356 if (x + width > _grey_info.width)
357 width = _grey_info.width - x;
358 if (y + height > _grey_info.height)
359 height = _grey_info.height - y;
360
361 if (_grey_info.drawmode & DRMODE_INVERSEVID) 347 if (_grey_info.drawmode & DRMODE_INVERSEVID)
362 { 348 {
363 if (_grey_info.drawmode & DRMODE_BG) 349 if (_grey_info.drawmode & DRMODE_BG)
@@ -374,7 +360,25 @@ void grey_fillrect(int x, int y, int width, int height)
374 value = _grey_info.fg_brightness; 360 value = _grey_info.fg_brightness;
375 } 361 }
376 } 362 }
377 pfunc = _grey_pixelfuncs[_grey_info.drawmode]; 363 if (!fillopt && _grey_info.drawmode != DRMODE_COMPLEMENT)
364 return;
365
366 /* clipping */
367 if (x < 0)
368 {
369 width += x;
370 x = 0;
371 }
372 if (y < 0)
373 {
374 height += y;
375 y = 0;
376 }
377 if (x + width > _grey_info.width)
378 width = _grey_info.width - x;
379 if (y + height > _grey_info.height)
380 height = _grey_info.height - y;
381
378 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; 382 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x];
379 dst_end = dst + _GREY_MULUQ(_grey_info.width, height); 383 dst_end = dst + _GREY_MULUQ(_grey_info.width, height);
380 384
@@ -382,14 +386,14 @@ void grey_fillrect(int x, int y, int width, int height)
382 { 386 {
383 if (fillopt) 387 if (fillopt)
384 rb->memset(dst, value, width); 388 rb->memset(dst, value, width);
385 else 389 else /* DRMODE_COMPLEMENT */
386 { 390 {
387 unsigned char *dst_row = dst; 391 unsigned char *dst_row = dst;
388 unsigned char *row_end = dst_row + width; 392 unsigned char *row_end = dst_row + width;
389 393
390 do 394 do
391 pfunc(dst_row++); 395 *dst_row = ~(*dst_row);
392 while (dst_row < row_end); 396 while (++dst_row < row_end);
393 } 397 }
394 dst += _grey_info.width; 398 dst += _grey_info.width;
395 } 399 }
@@ -411,8 +415,9 @@ void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
411{ 415{
412 const unsigned char *src_end; 416 const unsigned char *src_end;
413 unsigned char *dst, *dst_end; 417 unsigned char *dst, *dst_end;
414 void (*fgfunc)(unsigned char *address); 418 unsigned dmask = 0x100; /* bit 8 == sentinel */
415 void (*bgfunc)(unsigned char *address); 419 int drmode = _grey_info.drawmode;
420 int dwidth;
416 421
417 /* nothing to draw? */ 422 /* nothing to draw? */
418 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) 423 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
@@ -440,37 +445,84 @@ void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
440 src += _GREY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */ 445 src += _GREY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */
441 src_y &= 7; 446 src_y &= 7;
442 src_end = src + width; 447 src_end = src + width;
448 dwidth = _grey_info.width;
449 dst = &_grey_info.buffer[_GREY_MULUQ(dwidth, y) + x];
443 450
444 fgfunc = _grey_pixelfuncs[_grey_info.drawmode]; 451 if (drmode & DRMODE_INVERSEVID)
445 bgfunc = _grey_pixelfuncs[_grey_info.drawmode ^ DRMODE_INVERSEVID]; 452 {
446 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; 453 dmask = 0x1ff; /* bit 8 == sentinel */
454 drmode &= DRMODE_SOLID; /* mask out inversevid */
455 }
447 456
448 do 457 do
449 { 458 {
450 const unsigned char *src_col = src++; 459 const unsigned char *src_col = src++;
451 unsigned char *dst_col = dst++; 460 unsigned char *dst_col = dst++;
452 unsigned data = *src_col >> src_y; 461 unsigned data = (*src_col ^ dmask) >> src_y;
453 int numbits = 8 - src_y; 462 int fg, bg;
463
464 dst_end = dst_col + _GREY_MULUQ(dwidth, height);
454 465
455 dst_end = dst_col + _GREY_MULUQ(_grey_info.width, height); 466#define UPDATE_SRC do { \
456 do 467 data >>= 1; \
468 if (data == 0x001) { \
469 src_col += stride; \
470 data = *src_col ^ dmask; \
471 } \
472 } while (0)
473
474 switch (drmode)
457 { 475 {
458 if (data & 0x01) 476 case DRMODE_COMPLEMENT:
459 fgfunc(dst_col); 477 do
460 else 478 {
461 bgfunc(dst_col); 479 if (data & 0x01)
480 *dst_col = ~(*dst_col);
462 481
463 dst_col += _grey_info.width; 482 dst_col += dwidth;
483 UPDATE_SRC;
484 }
485 while (dst_col < dst_end);
486 break;
464 487
465 data >>= 1; 488 case DRMODE_BG:
466 if (--numbits == 0) 489 bg = _grey_info.bg_brightness;
490 do
467 { 491 {
468 src_col += stride; 492 if (!(data & 0x01))
469 data = *src_col; 493 *dst_col = bg;
470 numbits = 8; 494
495 dst_col += dwidth;
496 UPDATE_SRC;
471 } 497 }
498 while (dst_col < dst_end);
499 break;
500
501 case DRMODE_FG:
502 fg = _grey_info.fg_brightness;
503 do
504 {
505 if (data & 0x01)
506 *dst_col = fg;
507
508 dst_col += dwidth;
509 UPDATE_SRC;
510 }
511 while (dst_col < dst_end);
512 break;
513
514 case DRMODE_SOLID:
515 fg = _grey_info.fg_brightness;
516 bg = _grey_info.bg_brightness;
517 do
518 {
519 *dst_col = (data & 0x01) ? fg : bg;
520 dst_col += dwidth;
521 UPDATE_SRC;
522 }
523 while (dst_col < dst_end);
524 break;
472 } 525 }
473 while (dst_col < dst_end);
474 } 526 }
475 while (src < src_end); 527 while (src < src_end);
476} 528}
@@ -491,7 +543,7 @@ void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
491 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width) 543 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
492 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0)) 544 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
493 return; 545 return;
494 546
495 /* clipping */ 547 /* clipping */
496 if (x < 0) 548 if (x < 0)
497 { 549 {
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index 9b700a0669..c3e076b392 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -428,7 +428,6 @@ void lcd_hline(int x1, int x2, int y)
428 unsigned bits = 0; 428 unsigned bits = 0;
429 enum fill_opt fillopt = OPT_NONE; 429 enum fill_opt fillopt = OPT_NONE;
430 fb_data *dst, *dst_end; 430 fb_data *dst, *dst_end;
431 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
432 431
433 /* direction flip */ 432 /* direction flip */
434 if (x2 < x1) 433 if (x2 < x1)
@@ -444,18 +443,7 @@ void lcd_hline(int x1, int x2, int y)
444 (x2 < 0)) 443 (x2 < 0))
445 return; 444 return;
446 445
447 /* clipping */ 446 /* drawmode and optimisation */
448 if (x1 < 0)
449 x1 = 0;
450 if (x2 >= current_vp->width)
451 x2 = current_vp->width-1;
452
453 width = x2 - x1 + 1;
454
455 /* Adjust x1 and y to viewport */
456 x1 += current_vp->x;
457 y += current_vp->y;
458
459 if (current_vp->drawmode & DRMODE_INVERSEVID) 447 if (current_vp->drawmode & DRMODE_INVERSEVID)
460 { 448 {
461 if (current_vp->drawmode & DRMODE_BG) 449 if (current_vp->drawmode & DRMODE_BG)
@@ -477,6 +465,21 @@ void lcd_hline(int x1, int x2, int y)
477 bits = current_vp->fg_pattern; 465 bits = current_vp->fg_pattern;
478 } 466 }
479 } 467 }
468 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
469 return;
470
471 /* clipping */
472 if (x1 < 0)
473 x1 = 0;
474 if (x2 >= current_vp->width)
475 x2 = current_vp->width-1;
476
477 width = x2 - x1 + 1;
478
479 /* Adjust x1 and y to viewport */
480 x1 += current_vp->x;
481 y += current_vp->y;
482
480 dst = LCDADDR(x1, y); 483 dst = LCDADDR(x1, y);
481 484
482 switch (fillopt) 485 switch (fillopt)
@@ -490,11 +493,11 @@ void lcd_hline(int x1, int x2, int y)
490 width * sizeof(fb_data)); 493 width * sizeof(fb_data));
491 break; 494 break;
492 495
493 case OPT_NONE: 496 case OPT_NONE: /* DRMODE_COMPLEMENT */
494 dst_end = dst + width; 497 dst_end = dst + width;
495 do 498 do
496 pfunc(dst++); 499 *dst = ~(*dst);
497 while (dst < dst_end); 500 while (++dst < dst_end);
498 break; 501 break;
499 } 502 }
500} 503}
@@ -558,29 +561,13 @@ void lcd_fillrect(int x, int y, int width, int height)
558 unsigned bits = 0; 561 unsigned bits = 0;
559 enum fill_opt fillopt = OPT_NONE; 562 enum fill_opt fillopt = OPT_NONE;
560 fb_data *dst, *dst_end; 563 fb_data *dst, *dst_end;
561 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
562 564
563 /* nothing to draw? */ 565 /* nothing to draw? */
564 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 566 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
565 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 567 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
566 return; 568 return;
567 569
568 /* clipping */ 570 /* drawmode and optimisation */
569 if (x < 0)
570 {
571 width += x;
572 x = 0;
573 }
574 if (y < 0)
575 {
576 height += y;
577 y = 0;
578 }
579 if (x + width > current_vp->width)
580 width = current_vp->width - x;
581 if (y + height > current_vp->height)
582 height = current_vp->height - y;
583
584 if (current_vp->drawmode & DRMODE_INVERSEVID) 571 if (current_vp->drawmode & DRMODE_INVERSEVID)
585 { 572 {
586 if (current_vp->drawmode & DRMODE_BG) 573 if (current_vp->drawmode & DRMODE_BG)
@@ -602,6 +589,25 @@ void lcd_fillrect(int x, int y, int width, int height)
602 bits = current_vp->fg_pattern; 589 bits = current_vp->fg_pattern;
603 } 590 }
604 } 591 }
592 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
593 return;
594
595 /* clipping */
596 if (x < 0)
597 {
598 width += x;
599 x = 0;
600 }
601 if (y < 0)
602 {
603 height += y;
604 y = 0;
605 }
606 if (x + width > current_vp->width)
607 width = current_vp->width - x;
608 if (y + height > current_vp->height)
609 height = current_vp->height - y;
610
605 dst = LCDADDR(current_vp->x + x, current_vp->y + y); 611 dst = LCDADDR(current_vp->x + x, current_vp->y + y);
606 dst_end = dst + height * LCD_WIDTH; 612 dst_end = dst + height * LCD_WIDTH;
607 613
@@ -620,12 +626,12 @@ void lcd_fillrect(int x, int y, int width, int height)
620 width * sizeof(fb_data)); 626 width * sizeof(fb_data));
621 break; 627 break;
622 628
623 case OPT_NONE: 629 case OPT_NONE: /* DRMODE_COMPLEMENT */
624 dst_row = dst; 630 dst_row = dst;
625 row_end = dst_row + width; 631 row_end = dst_row + width;
626 do 632 do
627 pfunc(dst_row++); 633 *dst_row = ~(*dst_row);
628 while (dst_row < row_end); 634 while (++dst_row < row_end);
629 break; 635 break;
630 } 636 }
631 dst += LCD_WIDTH; 637 dst += LCD_WIDTH;
@@ -717,7 +723,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
717{ 723{
718 const unsigned char *src_end; 724 const unsigned char *src_end;
719 fb_data *dst, *dst_end; 725 fb_data *dst, *dst_end;
720 lcd_fastpixelfunc_type *fgfunc, *bgfunc; 726 unsigned dmask = 0x100; /* bit 8 == sentinel */
727 int drmode = current_vp->drawmode;
721 728
722 /* nothing to draw? */ 729 /* nothing to draw? */
723 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 730 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
@@ -745,35 +752,115 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
745 src += stride * (src_y >> 3) + src_x; /* move starting point */ 752 src += stride * (src_y >> 3) + src_x; /* move starting point */
746 src_y &= 7; 753 src_y &= 7;
747 src_end = src + width; 754 src_end = src + width;
748
749 dst = LCDADDR(current_vp->x + x, current_vp->y + y); 755 dst = LCDADDR(current_vp->x + x, current_vp->y + y);
750 fgfunc = lcd_fastpixelfuncs[current_vp->drawmode]; 756
751 bgfunc = lcd_fastpixelfuncs[current_vp->drawmode ^ DRMODE_INVERSEVID]; 757 if (drmode & DRMODE_INVERSEVID)
758 {
759 dmask = 0x1ff; /* bit 8 == sentinel */
760 drmode &= DRMODE_SOLID; /* mask out inversevid */
761 }
762
752 do 763 do
753 { 764 {
754 const unsigned char *src_col = src++; 765 const unsigned char *src_col = src++;
755 unsigned data = *src_col >> src_y; 766 unsigned data = (*src_col ^ dmask) >> src_y;
756 fb_data *dst_col = dst++; 767 fb_data *dst_col = dst++;
757 int numbits = 8 - src_y; 768 int fg, bg;
769 long bo;
770
758 dst_end = dst_col + height * LCD_WIDTH; 771 dst_end = dst_col + height * LCD_WIDTH;
759 do 772
773#define UPDATE_SRC do { \
774 data >>= 1; \
775 if (data == 0x001) { \
776 src_col += stride; \
777 data = *src_col ^ dmask; \
778 } \
779 } while (0)
780
781 switch (drmode)
760 { 782 {
761 if (data & 0x01) 783 case DRMODE_COMPLEMENT:
762 fgfunc(dst_col); 784 do
785 {
786 if (data & 0x01)
787 *dst_col = ~(*dst_col);
788
789 dst_col += LCD_WIDTH;
790 UPDATE_SRC;
791 }
792 while (dst_col < dst_end);
793 break;
794
795 case DRMODE_BG:
796 if (lcd_backdrop)
797 {
798 bo = lcd_backdrop_offset;
799 do
800 {
801 if (!(data & 0x01))
802 *dst_col = *(fb_data *)((long)dst_col + bo);
803
804 dst_col += LCD_WIDTH;
805 UPDATE_SRC;
806 }
807 while (dst_col < dst_end);
808 }
763 else 809 else
764 bgfunc(dst_col); 810 {
811 bg = current_vp->bg_pattern;
812 do
813 {
814 if (!(data & 0x01))
815 *dst_col = bg;
816
817 dst_col += LCD_WIDTH;
818 UPDATE_SRC;
819 }
820 while (dst_col < dst_end);
821 }
822 break;
765 823
766 dst_col += LCD_WIDTH; 824 case DRMODE_FG:
825 fg = current_vp->fg_pattern;
826 do
827 {
828 if (data & 0x01)
829 *dst_col = fg;
767 830
768 data >>= 1; 831 dst_col += LCD_WIDTH;
769 if (--numbits == 0) 832 UPDATE_SRC;
833 }
834 while (dst_col < dst_end);
835 break;
836
837 case DRMODE_SOLID:
838 fg = current_vp->fg_pattern;
839 if (lcd_backdrop)
770 { 840 {
771 src_col += stride; 841 bo = lcd_backdrop_offset;
772 data = *src_col; 842 do
773 numbits = 8; 843 {
844 *dst_col = (data & 0x01) ? fg
845 : *(fb_data *)((long)dst_col + bo);
846 dst_col += LCD_WIDTH;
847 UPDATE_SRC;
848 }
849 while (dst_col < dst_end);
774 } 850 }
851 else
852 {
853 bg = current_vp->bg_pattern;
854 do
855 {
856 *dst_col = (data & 0x01) ? fg : bg;
857 dst_col += LCD_WIDTH;
858 UPDATE_SRC;
859 }
860 while (dst_col < dst_end);
861 }
862 break;
775 } 863 }
776 while (dst_col < dst_end);
777 } 864 }
778 while (src < src_end); 865 while (src < src_end);
779} 866}