diff options
author | Jens Arnold <amiconn@rockbox.org> | 2004-05-15 21:55:15 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2004-05-15 21:55:15 +0000 |
commit | 9580e3a577829f7162429629c0cc5d981e7f5e05 (patch) | |
tree | 9904d5871f00a8e8173a89d75e449a90784d6bfb | |
parent | f77acfb982e1585d44881d763a119f5a0a032cff (diff) | |
download | rockbox-9580e3a577829f7162429629c0cc5d981e7f5e05.tar.gz rockbox-9580e3a577829f7162429629c0cc5d981e7f5e05.zip |
Vastly improved speed for gray_fillrect(), gray_drawgraymap(), left and right scrolling. Various other optimizations.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4626 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/plugins/grayscale.c | 395 |
1 files changed, 314 insertions, 81 deletions
diff --git a/apps/plugins/grayscale.c b/apps/plugins/grayscale.c index fe50a5226e..c429485f93 100644 --- a/apps/plugins/grayscale.c +++ b/apps/plugins/grayscale.c | |||
@@ -63,6 +63,9 @@ static unsigned int gbuf_size = 0; | |||
63 | #define GRAY_RUNNING 0x0001 /* grayscale overlay is running */ | 63 | #define GRAY_RUNNING 0x0001 /* grayscale overlay is running */ |
64 | #define GRAY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */ | 64 | #define GRAY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */ |
65 | 65 | ||
66 | /* unsigned 16 bit multiplication (a single instruction on the SH) */ | ||
67 | #define MULU16(a, b) (((unsigned short) (a)) * ((unsigned short) (b))) | ||
68 | |||
66 | typedef struct | 69 | typedef struct |
67 | { | 70 | { |
68 | int x; | 71 | int x; |
@@ -80,19 +83,21 @@ typedef struct | |||
80 | } tGraybuf; | 83 | } tGraybuf; |
81 | 84 | ||
82 | static tGraybuf *graybuf = NULL; | 85 | static tGraybuf *graybuf = NULL; |
86 | static short gray_random_buffer; | ||
83 | 87 | ||
84 | /** prototypes **/ | 88 | /** prototypes **/ |
85 | 89 | ||
86 | void timer_isr(void); | 90 | void gray_timer_isr(void); |
87 | void graypixel(int x, int y, unsigned long pattern); | 91 | void graypixel(int x, int y, unsigned long pattern); |
88 | void grayinvertmasked(int x, int yb, unsigned char mask); | 92 | void grayblock(int x, int by, unsigned char* src, int stride); |
93 | void grayinvertmasked(int x, int by, unsigned char mask); | ||
89 | 94 | ||
90 | /** implementation **/ | 95 | /** implementation **/ |
91 | 96 | ||
92 | /* timer interrupt handler: display next bitplane */ | 97 | /* timer interrupt handler: display next bitplane */ |
93 | void timer_isr(void) | 98 | void gray_timer_isr(void) |
94 | { | 99 | { |
95 | rb->lcd_blit(graybuf->data + (graybuf->plane_size * graybuf->cur_plane), | 100 | rb->lcd_blit(graybuf->data + MULU16(graybuf->plane_size, graybuf->cur_plane), |
96 | graybuf->x, graybuf->by, graybuf->width, graybuf->bheight, | 101 | graybuf->x, graybuf->by, graybuf->width, graybuf->bheight, |
97 | graybuf->width); | 102 | graybuf->width); |
98 | 103 | ||
@@ -126,7 +131,6 @@ void timer_isr(void) | |||
126 | * This is the fundamental graphics primitive, asm optimized */ | 131 | * This is the fundamental graphics primitive, asm optimized */ |
127 | void graypixel(int x, int y, unsigned long pattern) | 132 | void graypixel(int x, int y, unsigned long pattern) |
128 | { | 133 | { |
129 | static short random_buffer; | ||
130 | register long address, mask, random; | 134 | register long address, mask, random; |
131 | 135 | ||
132 | /* Some (pseudo-)random function must be used here to shift the bit | 136 | /* Some (pseudo-)random function must be used here to shift the bit |
@@ -149,7 +153,7 @@ void graypixel(int x, int y, unsigned long pattern) | |||
149 | : /* outputs */ | 153 | : /* outputs */ |
150 | /* %0 */ "=&r"(random) | 154 | /* %0 */ "=&r"(random) |
151 | : /* inputs */ | 155 | : /* inputs */ |
152 | /* %1 */ "r"(&random_buffer), | 156 | /* %1 */ "r"(&gray_random_buffer), |
153 | /* %2 */ "r"(graybuf->randmask) | 157 | /* %2 */ "r"(graybuf->randmask) |
154 | : /* clobbers */ | 158 | : /* clobbers */ |
155 | "r1","macl" | 159 | "r1","macl" |
@@ -258,6 +262,141 @@ void graypixel(int x, int y, unsigned long pattern) | |||
258 | ); | 262 | ); |
259 | } | 263 | } |
260 | 264 | ||
265 | /* Set 8 pixels to specific gray values at once, asm optimized | ||
266 | * This greatly enhances performance of gray_fillrect() and gray_drawgraymap() | ||
267 | * for larger rectangles and graymaps */ | ||
268 | void grayblock(int x, int by, unsigned char* src, int stride) | ||
269 | { | ||
270 | /* precalculate the bit patterns with random shifts (same RNG as graypixel, | ||
271 | * see there for an explanation) for all 8 pixels and put them on the | ||
272 | * stack (!) */ | ||
273 | asm( | ||
274 | "mova .gb_reload,r0 \n" /* set default loopback address */ | ||
275 | "tst %1,%1 \n" /* stride == 0 ? */ | ||
276 | "bf .gb_needreload \n" /* no: keep that address */ | ||
277 | "mova .gb_reuse,r0 \n" /* yes: set shortcut (no reload) */ | ||
278 | ".gb_needreload: \n" | ||
279 | "mov r0,r2 \n" /* loopback address to r2 */ | ||
280 | "mov #7,r3 \n" /* loop count in r3: 8 pixels */ | ||
281 | |||
282 | ".align 2 \n" /** load pattern for pixel **/ | ||
283 | ".gb_reload: \n" | ||
284 | "mov.b @%0,r0 \n" /* load src byte */ | ||
285 | "extu.b r0,r0 \n" /* extend unsigned */ | ||
286 | "mulu %2,r0 \n" /* macl = byte * depth; */ | ||
287 | "add %1,%0 \n" /* src += stride; */ | ||
288 | "sts macl,r4 \n" /* r4 = macl; */ | ||
289 | "add r4,r0 \n" /* byte += r4; */ | ||
290 | "shlr8 r0 \n" /* byte >>= 8; */ | ||
291 | "shll2 r0 \n" | ||
292 | "mov.l @(r0,%3),r4 \n" /* r4 = bitpattern[byte]; */ | ||
293 | |||
294 | ".align 2 \n" /** RNG **/ | ||
295 | ".gb_reuse: \n" | ||
296 | "mov.w @%4,r1 \n" /* load last value */ | ||
297 | "mov #75,r0 \n" | ||
298 | "mulu r0,r1 \n" /* multiply by 75 */ | ||
299 | "sts macl,r1 \n" | ||
300 | "add #74,r1 \n" /* add another 74 */ | ||
301 | "mov.w r1,@%4 \n" /* store new value */ | ||
302 | /* Since the lower bits are not very random: */ | ||
303 | "shlr8 r1 \n" /* get bits 8..15 (need max. 5) */ | ||
304 | "and %5,r1 \n" /* mask out unneeded bits */ | ||
305 | |||
306 | "cmp/hs %2,r1 \n" /* random >= depth ? */ | ||
307 | "bf .gb_ntrim \n" | ||
308 | "sub %2,r1 \n" /* yes: random -= depth; */ | ||
309 | ".gb_ntrim: \n" | ||
310 | |||
311 | "mov.l .ashlsi3,r0 \n" /** rotate pattern **/ | ||
312 | "jsr @r0 \n" /* shift r4 left by r1 */ | ||
313 | "mov r1,r5 \n" | ||
314 | |||
315 | "mov %2,r5 \n" | ||
316 | "sub r1,r5 \n" /* r5 = depth - r1 */ | ||
317 | "mov r0,r1 \n" /* last result stored in r1 */ | ||
318 | "mov.l .lshrsi3,r0 \n" | ||
319 | "jsr @r0 \n" /* shift r4 right by r5 */ | ||
320 | "nop \n" | ||
321 | |||
322 | "or r1,r0 \n" /* rotated_pattern = r0 | r1 */ | ||
323 | "mov.l r0,@-r15 \n" /* push pattern */ | ||
324 | |||
325 | "cmp/pl r3 \n" /* loop count > 0? */ | ||
326 | "bf .gb_patdone \n" /* no: done */ | ||
327 | |||
328 | "jmp @r2 \n" /* yes: loop */ | ||
329 | "add #-1,r3 \n" /* decrease loop count */ | ||
330 | |||
331 | ".align 2 \n" | ||
332 | ".ashlsi3: \n" /* C library routine: */ | ||
333 | ".long ___ashlsi3 \n" /* shift r4 left by r5, return in r0 */ | ||
334 | ".lshrsi3: \n" /* C library routine: */ | ||
335 | ".long ___lshrsi3 \n" /* shift r4 right by r5, return in r0 */ | ||
336 | /* both routines preserve r4, destroy r5 and take ~16 cycles */ | ||
337 | |||
338 | ".gb_patdone: \n" | ||
339 | : /* outputs */ | ||
340 | : /* inputs */ | ||
341 | /* %0 */ "r"(src), | ||
342 | /* %1 */ "r"(stride), | ||
343 | /* %2 */ "r"(graybuf->depth), | ||
344 | /* %3 */ "r"(graybuf->bitpattern), | ||
345 | /* %4 */ "r"(&gray_random_buffer), | ||
346 | /* %5 */ "r"(graybuf->randmask) | ||
347 | : /* clobbers */ | ||
348 | "r0", "r1", "r2", "r3", "r4", "r5", "macl" | ||
349 | ); | ||
350 | |||
351 | /* calculate start address in first bitplane and end address */ | ||
352 | register unsigned char *address = graybuf->data + x | ||
353 | + MULU16(graybuf->width, by); | ||
354 | register unsigned char *end_addr = address | ||
355 | + MULU16(graybuf->depth, graybuf->plane_size); | ||
356 | |||
357 | /* set the bits for all 8 pixels in all bytes according to the | ||
358 | * precalculated patterns on the stack */ | ||
359 | asm ( | ||
360 | "mov.l @r15+,r1 \n" /* pop all 8 patterns */ | ||
361 | "mov.l @r15+,r2 \n" | ||
362 | "mov.l @r15+,r3 \n" | ||
363 | "mov.l @r15+,r4 \n" | ||
364 | "mov.l @r15+,r5 \n" | ||
365 | "mov.l @r15+,r6 \n" | ||
366 | "mov.l @r15+,r7 \n" | ||
367 | "mov.l @r15+,r8 \n" | ||
368 | |||
369 | ".gb_loop: \n" /* loop for all bitplanes */ | ||
370 | "shlr r1 \n" /* rotate lsb of pattern 1 to t bit */ | ||
371 | "rotcl r0 \n" /* rotate t bit into r0 */ | ||
372 | "shlr r2 \n" | ||
373 | "rotcl r0 \n" | ||
374 | "shlr r3 \n" | ||
375 | "rotcl r0 \n" | ||
376 | "shlr r4 \n" | ||
377 | "rotcl r0 \n" | ||
378 | "shlr r5 \n" | ||
379 | "rotcl r0 \n" | ||
380 | "shlr r6 \n" | ||
381 | "rotcl r0 \n" | ||
382 | "shlr r7 \n" | ||
383 | "rotcl r0 \n" | ||
384 | "shlr r8 \n" | ||
385 | "rotcl r0 \n" | ||
386 | "mov.b r0,@%0 \n" /* store byte to bitplane */ | ||
387 | "add %2,%0 \n" /* advance to next bitplane */ | ||
388 | "cmp/hi %0,%1 \n" /* last bitplane done? */ | ||
389 | "bt .gb_loop \n" /* no: loop */ | ||
390 | : /* outputs */ | ||
391 | : /* inputs */ | ||
392 | /* %0 */ "r"(address), | ||
393 | /* %1 */ "r"(end_addr), | ||
394 | /* %2 */ "r"(graybuf->plane_size) | ||
395 | : /* clobbers */ | ||
396 | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" | ||
397 | ); | ||
398 | } | ||
399 | |||
261 | /* Invert the bits for 1-8 pixels within the buffer */ | 400 | /* Invert the bits for 1-8 pixels within the buffer */ |
262 | void grayinvertmasked(int x, int by, unsigned char mask) | 401 | void grayinvertmasked(int x, int by, unsigned char mask) |
263 | { | 402 | { |
@@ -473,7 +612,7 @@ void gray_show_display(bool enable) | |||
473 | if (enable) | 612 | if (enable) |
474 | { | 613 | { |
475 | graybuf->flags |= GRAY_RUNNING; | 614 | graybuf->flags |= GRAY_RUNNING; |
476 | rb->plugin_register_timer(FREQ / 67, 1, timer_isr); | 615 | rb->plugin_register_timer(FREQ / 67, 1, gray_timer_isr); |
477 | } | 616 | } |
478 | else | 617 | else |
479 | { | 618 | { |
@@ -533,7 +672,7 @@ void gray_clear_display(void) | |||
533 | if (graybuf == NULL) | 672 | if (graybuf == NULL) |
534 | return; | 673 | return; |
535 | 674 | ||
536 | rb->memset(graybuf->data, 0, graybuf->depth * graybuf->plane_size); | 675 | rb->memset(graybuf->data, 0, MULU16(graybuf->depth, graybuf->plane_size)); |
537 | } | 676 | } |
538 | 677 | ||
539 | /* Set the grayscale display to all black | 678 | /* Set the grayscale display to all black |
@@ -543,7 +682,7 @@ void gray_black_display(void) | |||
543 | if (graybuf == NULL) | 682 | if (graybuf == NULL) |
544 | return; | 683 | return; |
545 | 684 | ||
546 | rb->memset(graybuf->data, 0xFF, graybuf->depth * graybuf->plane_size); | 685 | rb->memset(graybuf->data, 0xFF, MULU16(graybuf->depth, graybuf->plane_size)); |
547 | } | 686 | } |
548 | 687 | ||
549 | /* Do a lcd_update() to show changes done by rb->lcd_xxx() functions (in areas | 688 | /* Do a lcd_update() to show changes done by rb->lcd_xxx() functions (in areas |
@@ -567,8 +706,8 @@ void gray_deferred_update(void) | |||
567 | */ | 706 | */ |
568 | void gray_scroll_left(int count, bool black_border) | 707 | void gray_scroll_left(int count, bool black_border) |
569 | { | 708 | { |
570 | int x, by, d; | 709 | int by, d; |
571 | unsigned char *src, *dest; | 710 | unsigned char *ptr; |
572 | unsigned char filler; | 711 | unsigned char filler; |
573 | 712 | ||
574 | if (graybuf == NULL || (unsigned) count >= (unsigned) graybuf->width) | 713 | if (graybuf == NULL || (unsigned) count >= (unsigned) graybuf->width) |
@@ -582,17 +721,42 @@ void gray_scroll_left(int count, bool black_border) | |||
582 | /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ | 721 | /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ |
583 | for (by = 0; by < graybuf->bheight; by++) | 722 | for (by = 0; by < graybuf->bheight; by++) |
584 | { | 723 | { |
724 | ptr = graybuf->data + MULU16(graybuf->width, by); | ||
585 | for (d = 0; d < graybuf->depth; d++) | 725 | for (d = 0; d < graybuf->depth; d++) |
586 | { | 726 | { |
587 | dest = graybuf->data + graybuf->plane_size * d | 727 | if (count & 1) /* odd count: scroll byte-wise */ |
588 | + graybuf->width * by; | 728 | asm volatile ( |
589 | src = dest + count; | 729 | ".sl_loop1: \n" |
590 | 730 | "mov.b @%0+,r1 \n" | |
591 | for (x = count; x < graybuf->width; x++) | 731 | "mov.b r1,@(%2,%0) \n" |
592 | *dest++ = *src++; | 732 | "cmp/hi %0,%1 \n" |
593 | 733 | "bt .sl_loop1 \n" | |
594 | for (x = 0; x < count; x++) | 734 | : /* outputs */ |
595 | *dest++ = filler; | 735 | : /* inputs */ |
736 | /* %0 */ "r"(ptr + count), | ||
737 | /* %1 */ "r"(ptr + graybuf->width), | ||
738 | /* %2 */ "z"(-count - 1) | ||
739 | : /* clobbers */ | ||
740 | "r1" | ||
741 | ); | ||
742 | else /* even count: scroll word-wise */ | ||
743 | asm volatile ( | ||
744 | ".sl_loop2: \n" | ||
745 | "mov.w @%0+,r1 \n" | ||
746 | "mov.w r1,@(%2,%0) \n" | ||
747 | "cmp/hi %0,%1 \n" | ||
748 | "bt .sl_loop2 \n" | ||
749 | : /* outputs */ | ||
750 | : /* inputs */ | ||
751 | /* %0 */ "r"(ptr + count), | ||
752 | /* %1 */ "r"(ptr + graybuf->width), | ||
753 | /* %2 */ "z"(-count - 2) | ||
754 | : /* clobbers */ | ||
755 | "r1" | ||
756 | ); | ||
757 | |||
758 | rb->memset(ptr + graybuf->width - count, filler, count); | ||
759 | ptr += graybuf->plane_size; | ||
596 | } | 760 | } |
597 | } | 761 | } |
598 | } | 762 | } |
@@ -604,8 +768,8 @@ void gray_scroll_left(int count, bool black_border) | |||
604 | */ | 768 | */ |
605 | void gray_scroll_right(int count, bool black_border) | 769 | void gray_scroll_right(int count, bool black_border) |
606 | { | 770 | { |
607 | int x, by, d; | 771 | int by, d; |
608 | unsigned char *src, *dest; | 772 | unsigned char *ptr; |
609 | unsigned char filler; | 773 | unsigned char filler; |
610 | 774 | ||
611 | if (graybuf == NULL || (unsigned) count >= (unsigned) graybuf->width) | 775 | if (graybuf == NULL || (unsigned) count >= (unsigned) graybuf->width) |
@@ -619,17 +783,42 @@ void gray_scroll_right(int count, bool black_border) | |||
619 | /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ | 783 | /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ |
620 | for (by = 0; by < graybuf->bheight; by++) | 784 | for (by = 0; by < graybuf->bheight; by++) |
621 | { | 785 | { |
786 | ptr = graybuf->data + MULU16(graybuf->width, by); | ||
622 | for (d = 0; d < graybuf->depth; d++) | 787 | for (d = 0; d < graybuf->depth; d++) |
623 | { | 788 | { |
624 | dest = graybuf->data + graybuf->plane_size * d | 789 | if (count & 1) /* odd count: scroll byte-wise */ |
625 | + graybuf->width * (by + 1) - 1; | 790 | asm volatile ( |
626 | src = dest - count; | 791 | ".sr_loop1: \n" |
627 | 792 | "mov.b @(%2,%0),r1 \n" | |
628 | for (x = count; x < graybuf->width; x++) | 793 | "mov.b r1,@-%0 \n" |
629 | *dest-- = *src--; | 794 | "cmp/hs %1,%0 \n" |
630 | 795 | "bt .sr_loop1 \n" | |
631 | for (x = 0; x < count; x++) | 796 | : /* outputs */ |
632 | *dest-- = filler; | 797 | : /* inputs */ |
798 | /* %0 */ "r"(ptr + graybuf->width), | ||
799 | /* %1 */ "r"(ptr + count), | ||
800 | /* %2 */ "z"(-count - 1) | ||
801 | : /* clobbers */ | ||
802 | "r1" | ||
803 | ); | ||
804 | else /* even count: scroll word-wise */ | ||
805 | asm volatile ( | ||
806 | ".sr_loop2: \n" | ||
807 | "mov.w @(%2,%0),r1 \n" | ||
808 | "mov.w r1,@-%0 \n" | ||
809 | "cmp/hs %1,%0 \n" | ||
810 | "bt .sr_loop2 \n" | ||
811 | : /* outputs */ | ||
812 | : /* inputs */ | ||
813 | /* %0 */ "r"(ptr + graybuf->width), | ||
814 | /* %1 */ "r"(ptr + count), | ||
815 | /* %2 */ "z"(-count - 2) | ||
816 | : /* clobbers */ | ||
817 | "r1" | ||
818 | ); | ||
819 | |||
820 | rb->memset(ptr, filler, count); | ||
821 | ptr += graybuf->plane_size; | ||
633 | } | 822 | } |
634 | } | 823 | } |
635 | } | 824 | } |
@@ -642,7 +831,7 @@ void gray_scroll_right(int count, bool black_border) | |||
642 | void gray_scroll_up8(bool black_border) | 831 | void gray_scroll_up8(bool black_border) |
643 | { | 832 | { |
644 | int by, d; | 833 | int by, d; |
645 | unsigned char *src; | 834 | unsigned char *ptr; |
646 | unsigned char filler; | 835 | unsigned char filler; |
647 | 836 | ||
648 | if (graybuf == NULL) | 837 | if (graybuf == NULL) |
@@ -656,18 +845,19 @@ void gray_scroll_up8(bool black_border) | |||
656 | /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ | 845 | /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ |
657 | for (by = 1; by < graybuf->bheight; by++) | 846 | for (by = 1; by < graybuf->bheight; by++) |
658 | { | 847 | { |
848 | ptr = graybuf->data + MULU16(graybuf->width, by); | ||
659 | for (d = 0; d < graybuf->depth; d++) | 849 | for (d = 0; d < graybuf->depth; d++) |
660 | { | 850 | { |
661 | src = graybuf->data + graybuf->plane_size * d | 851 | rb->memcpy(ptr - graybuf->width, ptr, graybuf->width); |
662 | + graybuf->width * by; | 852 | ptr += graybuf->plane_size; |
663 | |||
664 | rb->memcpy(src - graybuf->width, src, graybuf->width); | ||
665 | } | 853 | } |
666 | } | 854 | } |
667 | for (d = 0; d < graybuf->depth; d++) /* fill last row */ | 855 | /* fill last row */ |
856 | ptr = graybuf->data + graybuf->plane_size - graybuf->width; | ||
857 | for (d = 0; d < graybuf->depth; d++) | ||
668 | { | 858 | { |
669 | rb->memset(graybuf->data + graybuf->plane_size * (d + 1) | 859 | rb->memset(ptr, filler, graybuf->width); |
670 | - graybuf->width, filler, graybuf->width); | 860 | ptr += graybuf->plane_size; |
671 | } | 861 | } |
672 | } | 862 | } |
673 | 863 | ||
@@ -679,7 +869,7 @@ void gray_scroll_up8(bool black_border) | |||
679 | void gray_scroll_down8(bool black_border) | 869 | void gray_scroll_down8(bool black_border) |
680 | { | 870 | { |
681 | int by, d; | 871 | int by, d; |
682 | unsigned char *dest; | 872 | unsigned char *ptr; |
683 | unsigned char filler; | 873 | unsigned char filler; |
684 | 874 | ||
685 | if (graybuf == NULL) | 875 | if (graybuf == NULL) |
@@ -693,18 +883,19 @@ void gray_scroll_down8(bool black_border) | |||
693 | /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ | 883 | /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ |
694 | for (by = graybuf->bheight - 1; by > 0; by--) | 884 | for (by = graybuf->bheight - 1; by > 0; by--) |
695 | { | 885 | { |
886 | ptr = graybuf->data + MULU16(graybuf->width, by); | ||
696 | for (d = 0; d < graybuf->depth; d++) | 887 | for (d = 0; d < graybuf->depth; d++) |
697 | { | 888 | { |
698 | dest = graybuf->data + graybuf->plane_size * d | 889 | rb->memcpy(ptr, ptr - graybuf->width, graybuf->width); |
699 | + graybuf->width * by; | 890 | ptr += graybuf->plane_size; |
700 | |||
701 | rb->memcpy(dest, dest - graybuf->width, graybuf->width); | ||
702 | } | 891 | } |
703 | } | 892 | } |
704 | for (d = 0; d < graybuf->depth; d++) /* fill first row */ | 893 | /* fill first row */ |
894 | ptr = graybuf->data; | ||
895 | for (d = 0; d < graybuf->depth; d++) | ||
705 | { | 896 | { |
706 | rb->memset(graybuf->data + graybuf->plane_size * d, filler, | 897 | rb->memset(ptr, filler, graybuf->width); |
707 | graybuf->width); | 898 | ptr += graybuf->plane_size; |
708 | } | 899 | } |
709 | } | 900 | } |
710 | 901 | ||
@@ -858,8 +1049,8 @@ void gray_drawpixel(int x, int y, int brightness) | |||
858 | || (unsigned) brightness > 255) | 1049 | || (unsigned) brightness > 255) |
859 | return; | 1050 | return; |
860 | 1051 | ||
861 | graypixel(x, y, graybuf->bitpattern[(brightness | 1052 | graypixel(x, y, graybuf->bitpattern[MULU16(brightness, |
862 | * (graybuf->depth + 1)) >> 8]); | 1053 | graybuf->depth + 1) >> 8]); |
863 | } | 1054 | } |
864 | 1055 | ||
865 | /* Invert a pixel | 1056 | /* Invert a pixel |
@@ -899,10 +1090,12 @@ void gray_drawline(int x1, int y1, int x2, int y2, int brightness) | |||
899 | || (unsigned) brightness > 255) | 1090 | || (unsigned) brightness > 255) |
900 | return; | 1091 | return; |
901 | 1092 | ||
902 | pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8]; | 1093 | pattern = graybuf->bitpattern[MULU16(brightness, graybuf->depth + 1) >> 8]; |
903 | 1094 | ||
904 | deltax = abs(x2 - x1); | 1095 | deltax = abs(x2 - x1); |
905 | deltay = abs(y2 - y1); | 1096 | deltay = abs(y2 - y1); |
1097 | xinc2 = 1; | ||
1098 | yinc2 = 1; | ||
906 | 1099 | ||
907 | if (deltax >= deltay) | 1100 | if (deltax >= deltay) |
908 | { | 1101 | { |
@@ -911,9 +1104,7 @@ void gray_drawline(int x1, int y1, int x2, int y2, int brightness) | |||
911 | dinc1 = deltay * 2; | 1104 | dinc1 = deltay * 2; |
912 | dinc2 = (deltay - deltax) * 2; | 1105 | dinc2 = (deltay - deltax) * 2; |
913 | xinc1 = 1; | 1106 | xinc1 = 1; |
914 | xinc2 = 1; | ||
915 | yinc1 = 0; | 1107 | yinc1 = 0; |
916 | yinc2 = 1; | ||
917 | } | 1108 | } |
918 | else | 1109 | else |
919 | { | 1110 | { |
@@ -922,9 +1113,7 @@ void gray_drawline(int x1, int y1, int x2, int y2, int brightness) | |||
922 | dinc1 = deltax * 2; | 1113 | dinc1 = deltax * 2; |
923 | dinc2 = (deltax - deltay) * 2; | 1114 | dinc2 = (deltax - deltay) * 2; |
924 | xinc1 = 0; | 1115 | xinc1 = 0; |
925 | xinc2 = 1; | ||
926 | yinc1 = 1; | 1116 | yinc1 = 1; |
927 | yinc2 = 1; | ||
928 | } | 1117 | } |
929 | numpixels++; /* include endpoints */ | 1118 | numpixels++; /* include endpoints */ |
930 | 1119 | ||
@@ -985,6 +1174,8 @@ void gray_invertline(int x1, int y1, int x2, int y2) | |||
985 | 1174 | ||
986 | deltax = abs(x2 - x1); | 1175 | deltax = abs(x2 - x1); |
987 | deltay = abs(y2 - y1); | 1176 | deltay = abs(y2 - y1); |
1177 | xinc2 = 1; | ||
1178 | yinc2 = 1; | ||
988 | 1179 | ||
989 | if (deltax >= deltay) | 1180 | if (deltax >= deltay) |
990 | { | 1181 | { |
@@ -993,9 +1184,7 @@ void gray_invertline(int x1, int y1, int x2, int y2) | |||
993 | dinc1 = deltay * 2; | 1184 | dinc1 = deltay * 2; |
994 | dinc2 = (deltay - deltax) * 2; | 1185 | dinc2 = (deltay - deltax) * 2; |
995 | xinc1 = 1; | 1186 | xinc1 = 1; |
996 | xinc2 = 1; | ||
997 | yinc1 = 0; | 1187 | yinc1 = 0; |
998 | yinc2 = 1; | ||
999 | } | 1188 | } |
1000 | else | 1189 | else |
1001 | { | 1190 | { |
@@ -1004,9 +1193,7 @@ void gray_invertline(int x1, int y1, int x2, int y2) | |||
1004 | dinc1 = deltax * 2; | 1193 | dinc1 = deltax * 2; |
1005 | dinc2 = (deltax - deltay) * 2; | 1194 | dinc2 = (deltax - deltay) * 2; |
1006 | xinc1 = 0; | 1195 | xinc1 = 0; |
1007 | xinc2 = 1; | ||
1008 | yinc1 = 1; | 1196 | yinc1 = 1; |
1009 | yinc2 = 1; | ||
1010 | } | 1197 | } |
1011 | numpixels++; /* include endpoints */ | 1198 | numpixels++; /* include endpoints */ |
1012 | 1199 | ||
@@ -1053,6 +1240,7 @@ void gray_drawrect(int x1, int y1, int x2, int y2, int brightness) | |||
1053 | { | 1240 | { |
1054 | int x, y; | 1241 | int x, y; |
1055 | unsigned long pattern; | 1242 | unsigned long pattern; |
1243 | unsigned char srcpixel; | ||
1056 | 1244 | ||
1057 | if (graybuf == NULL | 1245 | if (graybuf == NULL |
1058 | || (unsigned) x1 >= (unsigned) graybuf->width | 1246 | || (unsigned) x1 >= (unsigned) graybuf->width |
@@ -1062,8 +1250,6 @@ void gray_drawrect(int x1, int y1, int x2, int y2, int brightness) | |||
1062 | || (unsigned) brightness > 255) | 1250 | || (unsigned) brightness > 255) |
1063 | return; | 1251 | return; |
1064 | 1252 | ||
1065 | pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8]; | ||
1066 | |||
1067 | if (y1 > y2) | 1253 | if (y1 > y2) |
1068 | { | 1254 | { |
1069 | y = y1; | 1255 | y = y1; |
@@ -1077,15 +1263,30 @@ void gray_drawrect(int x1, int y1, int x2, int y2, int brightness) | |||
1077 | x2 = x; | 1263 | x2 = x; |
1078 | } | 1264 | } |
1079 | 1265 | ||
1080 | for (x = x1; x <= x2; x++) | 1266 | pattern = graybuf->bitpattern[MULU16(brightness, graybuf->depth + 1) >> 8]; |
1267 | srcpixel = brightness; | ||
1268 | |||
1269 | for (x = x1 + 1; x < x2; x++) | ||
1081 | { | 1270 | { |
1082 | graypixel(x, y1, pattern); | 1271 | graypixel(x, y1, pattern); |
1083 | graypixel(x, y2, pattern); | 1272 | graypixel(x, y2, pattern); |
1084 | } | 1273 | } |
1085 | for (y = y1; y <= y2; y++) | 1274 | for (y = y1; y <= y2; ) |
1086 | { | 1275 | { |
1087 | graypixel(x1, y, pattern); | 1276 | if (!(y & 7) && (y2 - y >= 7)) |
1088 | graypixel(x2, y, pattern); | 1277 | /* current row byte aligned in fb & at least 8 rows left */ |
1278 | { | ||
1279 | /* shortcut: draw all 8 rows at once: 2..3 times faster */ | ||
1280 | grayblock(x1, y >> 3, &srcpixel, 0); | ||
1281 | grayblock(x2, y >> 3, &srcpixel, 0); | ||
1282 | y += 8; | ||
1283 | } | ||
1284 | else | ||
1285 | { | ||
1286 | graypixel(x1, y, pattern); | ||
1287 | graypixel(x2, y, pattern); | ||
1288 | y++; | ||
1289 | } | ||
1089 | } | 1290 | } |
1090 | } | 1291 | } |
1091 | 1292 | ||
@@ -1098,6 +1299,7 @@ void gray_fillrect(int x1, int y1, int x2, int y2, int brightness) | |||
1098 | { | 1299 | { |
1099 | int x, y; | 1300 | int x, y; |
1100 | unsigned long pattern; | 1301 | unsigned long pattern; |
1302 | unsigned char srcpixel; | ||
1101 | 1303 | ||
1102 | if (graybuf == NULL | 1304 | if (graybuf == NULL |
1103 | || (unsigned) x1 >= (unsigned) graybuf->width | 1305 | || (unsigned) x1 >= (unsigned) graybuf->width |
@@ -1120,13 +1322,28 @@ void gray_fillrect(int x1, int y1, int x2, int y2, int brightness) | |||
1120 | x2 = x; | 1322 | x2 = x; |
1121 | } | 1323 | } |
1122 | 1324 | ||
1123 | pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8]; | 1325 | pattern = graybuf->bitpattern[MULU16(brightness, graybuf->depth + 1) >> 8]; |
1326 | srcpixel = brightness; | ||
1124 | 1327 | ||
1125 | for (y = y1; y <= y2; y++) | 1328 | for (y = y1; y <= y2; ) |
1126 | { | 1329 | { |
1127 | for (x = x1; x <= x2; x++) | 1330 | if (!(y & 7) && (y2 - y >= 7)) |
1331 | /* current row byte aligned in fb & at least 8 rows left */ | ||
1332 | { | ||
1333 | for (x = x1; x <= x2; x++) | ||
1334 | { | ||
1335 | /* shortcut: draw all 8 rows at once: 2..3 times faster */ | ||
1336 | grayblock(x, y >> 3, &srcpixel, 0); | ||
1337 | } | ||
1338 | y += 8; | ||
1339 | } | ||
1340 | else | ||
1128 | { | 1341 | { |
1129 | graypixel(x, y, pattern); | 1342 | for (x = x1; x <= x2; x++) |
1343 | { | ||
1344 | graypixel(x, y, pattern); | ||
1345 | } | ||
1346 | y++; | ||
1130 | } | 1347 | } |
1131 | } | 1348 | } |
1132 | } | 1349 | } |
@@ -1218,14 +1435,30 @@ void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny, | |||
1218 | if ((x + nx) >= graybuf->width) /* clip right */ | 1435 | if ((x + nx) >= graybuf->width) /* clip right */ |
1219 | nx = graybuf->width - x; | 1436 | nx = graybuf->width - x; |
1220 | 1437 | ||
1221 | for (yi = y; yi < y + ny; yi++) | 1438 | for (yi = y; yi < y + ny; ) |
1222 | { | 1439 | { |
1223 | row = src; | 1440 | row = src; |
1224 | src += stride; | 1441 | |
1225 | for (xi = x; xi < x + nx; xi++) | 1442 | if (!(yi & 7) && (y + ny - yi > 7)) |
1443 | /* current row byte aligned in fb & at least 8 rows left */ | ||
1444 | { | ||
1445 | for (xi = x; xi < x + nx; xi++) | ||
1446 | { | ||
1447 | /* shortcut: draw all 8 rows at once: 2..3 times faster */ | ||
1448 | grayblock(xi, yi >> 3, row++, stride); | ||
1449 | } | ||
1450 | yi += 8; | ||
1451 | src += stride << 3; | ||
1452 | } | ||
1453 | else | ||
1226 | { | 1454 | { |
1227 | graypixel(xi, yi, graybuf->bitpattern[((int)(*row++) | 1455 | for (xi = x; xi < x + nx; xi++) |
1228 | * (graybuf->depth + 1)) >> 8]); | 1456 | { |
1457 | graypixel(xi, yi, graybuf->bitpattern[MULU16(*row++, | ||
1458 | graybuf->depth + 1) >> 8]); | ||
1459 | } | ||
1460 | yi++; | ||
1461 | src += stride; | ||
1229 | } | 1462 | } |
1230 | } | 1463 | } |
1231 | } | 1464 | } |
@@ -1258,7 +1491,7 @@ void gray_drawbitmap(unsigned char *src, int x, int y, int nx, int ny, | |||
1258 | unsigned long fg_pattern, bg_pattern; | 1491 | unsigned long fg_pattern, bg_pattern; |
1259 | unsigned char *col; | 1492 | unsigned char *col; |
1260 | 1493 | ||
1261 | if (graybuf == NULL | 1494 | if (graybuf == NULL |
1262 | || (unsigned) x >= (unsigned) graybuf->width | 1495 | || (unsigned) x >= (unsigned) graybuf->width |
1263 | || (unsigned) y >= (unsigned) graybuf->height | 1496 | || (unsigned) y >= (unsigned) graybuf->height |
1264 | || (unsigned) fg_brightness > 255 | 1497 | || (unsigned) fg_brightness > 255 |
@@ -1271,11 +1504,11 @@ void gray_drawbitmap(unsigned char *src, int x, int y, int nx, int ny, | |||
1271 | if ((x + nx) >= graybuf->width) /* clip right */ | 1504 | if ((x + nx) >= graybuf->width) /* clip right */ |
1272 | nx = graybuf->width - x; | 1505 | nx = graybuf->width - x; |
1273 | 1506 | ||
1274 | fg_pattern = graybuf->bitpattern[(fg_brightness | 1507 | fg_pattern = graybuf->bitpattern[MULU16(fg_brightness, |
1275 | * (graybuf->depth + 1)) >> 8]; | 1508 | graybuf->depth + 1) >> 8]; |
1276 | 1509 | ||
1277 | bg_pattern = graybuf->bitpattern[(bg_brightness | 1510 | bg_pattern = graybuf->bitpattern[MULU16(bg_brightness, |
1278 | * (graybuf->depth + 1)) >> 8]; | 1511 | graybuf->depth + 1) >> 8]; |
1279 | 1512 | ||
1280 | for (xi = x; xi < x + nx; xi++) | 1513 | for (xi = x; xi < x + nx; xi++) |
1281 | { | 1514 | { |
@@ -1410,7 +1643,7 @@ int main(void) | |||
1410 | 1643 | ||
1411 | gray_fillrect(0, 0, 111, 55, 150); /* fill everything with gray 150 */ | 1644 | gray_fillrect(0, 0, 111, 55, 150); /* fill everything with gray 150 */ |
1412 | 1645 | ||
1413 | /* draw a dark gray star background */ | 1646 | /* draw a dark gray line star background */ |
1414 | for (y = 0; y < 56; y += 8) /* horizontal part */ | 1647 | for (y = 0; y < 56; y += 8) /* horizontal part */ |
1415 | { | 1648 | { |
1416 | gray_drawline(0, y, 111, 55 - y, 80); /* gray lines */ | 1649 | gray_drawline(0, y, 111, 55 - y, 80); /* gray lines */ |
@@ -1466,7 +1699,7 @@ int main(void) | |||
1466 | black_border = true; | 1699 | black_border = true; |
1467 | 1700 | ||
1468 | if (button & BUTTON_REPEAT) | 1701 | if (button & BUTTON_REPEAT) |
1469 | scroll_amount = 3; | 1702 | scroll_amount = 4; |
1470 | 1703 | ||
1471 | switch(button & ~(BUTTON_ON | BUTTON_REPEAT)) | 1704 | switch(button & ~(BUTTON_ON | BUTTON_REPEAT)) |
1472 | { | 1705 | { |