summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2004-05-15 22:01:30 +0000
committerJens Arnold <amiconn@rockbox.org>2004-05-15 22:01:30 +0000
commitbde77c047d4e6629cb43b600d070ed80ed6f94fa (patch)
treed1f2538bd3c80d737c40de013a52918aac4eb228
parent9580e3a577829f7162429629c0cc5d981e7f5e05 (diff)
downloadrockbox-bde77c047d4e6629cb43b600d070ed80ed6f94fa.tar.gz
rockbox-bde77c047d4e6629cb43b600d070ed80ed6f94fa.zip
Included improved grayscale framework
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4627 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/jpeg.c517
1 files changed, 392 insertions, 125 deletions
diff --git a/apps/plugins/jpeg.c b/apps/plugins/jpeg.c
index 5314ac6091..8f872bdab6 100644
--- a/apps/plugins/jpeg.c
+++ b/apps/plugins/jpeg.c
@@ -64,6 +64,9 @@ static struct plugin_api* rb;
64#define GRAY_RUNNING 0x0001 /* grayscale overlay is running */ 64#define GRAY_RUNNING 0x0001 /* grayscale overlay is running */
65#define GRAY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */ 65#define GRAY_DEFERRED_UPDATE 0x0002 /* lcd_update() requested */
66 66
67/* unsigned 16 bit multiplication (a single instruction on the SH) */
68#define MULU16(a, b) (((unsigned short) (a)) * ((unsigned short) (b)))
69
67typedef struct 70typedef struct
68{ 71{
69 int x; 72 int x;
@@ -81,19 +84,21 @@ typedef struct
81} tGraybuf; 84} tGraybuf;
82 85
83static tGraybuf *graybuf = NULL; 86static tGraybuf *graybuf = NULL;
87static short gray_random_buffer;
84 88
85/** prototypes **/ 89/** prototypes **/
86 90
87void timer_isr(void); 91void gray_timer_isr(void);
88void graypixel(int x, int y, unsigned long pattern); 92void graypixel(int x, int y, unsigned long pattern);
89void grayinvertmasked(int x, int yb, unsigned char mask); 93void grayblock(int x, int by, unsigned char* src, int stride);
94void grayinvertmasked(int x, int by, unsigned char mask);
90 95
91/** implementation **/ 96/** implementation **/
92 97
93/* timer interrupt handler: display next bitplane */ 98/* timer interrupt handler: display next bitplane */
94void timer_isr(void) 99void gray_timer_isr(void)
95{ 100{
96 rb->lcd_blit(graybuf->data + (graybuf->plane_size * graybuf->cur_plane), 101 rb->lcd_blit(graybuf->data + MULU16(graybuf->plane_size, graybuf->cur_plane),
97 graybuf->x, graybuf->by, graybuf->width, graybuf->bheight, 102 graybuf->x, graybuf->by, graybuf->width, graybuf->bheight,
98 graybuf->width); 103 graybuf->width);
99 104
@@ -127,7 +132,6 @@ void timer_isr(void)
127 * This is the fundamental graphics primitive, asm optimized */ 132 * This is the fundamental graphics primitive, asm optimized */
128void graypixel(int x, int y, unsigned long pattern) 133void graypixel(int x, int y, unsigned long pattern)
129{ 134{
130 static short random_buffer;
131 register long address, mask, random; 135 register long address, mask, random;
132 136
133 /* Some (pseudo-)random function must be used here to shift the bit 137 /* Some (pseudo-)random function must be used here to shift the bit
@@ -150,7 +154,7 @@ void graypixel(int x, int y, unsigned long pattern)
150 : /* outputs */ 154 : /* outputs */
151 /* %0 */ "=&r"(random) 155 /* %0 */ "=&r"(random)
152 : /* inputs */ 156 : /* inputs */
153 /* %1 */ "r"(&random_buffer), 157 /* %1 */ "r"(&gray_random_buffer),
154 /* %2 */ "r"(graybuf->randmask) 158 /* %2 */ "r"(graybuf->randmask)
155 : /* clobbers */ 159 : /* clobbers */
156 "r1","macl" 160 "r1","macl"
@@ -259,6 +263,141 @@ void graypixel(int x, int y, unsigned long pattern)
259 ); 263 );
260} 264}
261 265
266/* Set 8 pixels to specific gray values at once, asm optimized
267 * This greatly enhances performance of gray_fillrect() and gray_drawgraymap()
268 * for larger rectangles and graymaps */
269void grayblock(int x, int by, unsigned char* src, int stride)
270{
271 /* precalculate the bit patterns with random shifts (same RNG as graypixel,
272 * see there for an explanation) for all 8 pixels and put them on the
273 * stack (!) */
274 asm(
275 "mova .gb_reload,r0 \n" /* set default loopback address */
276 "tst %1,%1 \n" /* stride == 0 ? */
277 "bf .gb_needreload \n" /* no: keep that address */
278 "mova .gb_reuse,r0 \n" /* yes: set shortcut (no reload) */
279 ".gb_needreload: \n"
280 "mov r0,r2 \n" /* loopback address to r2 */
281 "mov #7,r3 \n" /* loop count in r3: 8 pixels */
282
283 ".align 2 \n" /** load pattern for pixel **/
284 ".gb_reload: \n"
285 "mov.b @%0,r0 \n" /* load src byte */
286 "extu.b r0,r0 \n" /* extend unsigned */
287 "mulu %2,r0 \n" /* macl = byte * depth; */
288 "add %1,%0 \n" /* src += stride; */
289 "sts macl,r4 \n" /* r4 = macl; */
290 "add r4,r0 \n" /* byte += r4; */
291 "shlr8 r0 \n" /* byte >>= 8; */
292 "shll2 r0 \n"
293 "mov.l @(r0,%3),r4 \n" /* r4 = bitpattern[byte]; */
294
295 ".align 2 \n" /** RNG **/
296 ".gb_reuse: \n"
297 "mov.w @%4,r1 \n" /* load last value */
298 "mov #75,r0 \n"
299 "mulu r0,r1 \n" /* multiply by 75 */
300 "sts macl,r1 \n"
301 "add #74,r1 \n" /* add another 74 */
302 "mov.w r1,@%4 \n" /* store new value */
303 /* Since the lower bits are not very random: */
304 "shlr8 r1 \n" /* get bits 8..15 (need max. 5) */
305 "and %5,r1 \n" /* mask out unneeded bits */
306
307 "cmp/hs %2,r1 \n" /* random >= depth ? */
308 "bf .gb_ntrim \n"
309 "sub %2,r1 \n" /* yes: random -= depth; */
310 ".gb_ntrim: \n"
311
312 "mov.l .ashlsi3,r0 \n" /** rotate pattern **/
313 "jsr @r0 \n" /* shift r4 left by r1 */
314 "mov r1,r5 \n"
315
316 "mov %2,r5 \n"
317 "sub r1,r5 \n" /* r5 = depth - r1 */
318 "mov r0,r1 \n" /* last result stored in r1 */
319 "mov.l .lshrsi3,r0 \n"
320 "jsr @r0 \n" /* shift r4 right by r5 */
321 "nop \n"
322
323 "or r1,r0 \n" /* rotated_pattern = r0 | r1 */
324 "mov.l r0,@-r15 \n" /* push pattern */
325
326 "cmp/pl r3 \n" /* loop count > 0? */
327 "bf .gb_patdone \n" /* no: done */
328
329 "jmp @r2 \n" /* yes: loop */
330 "add #-1,r3 \n" /* decrease loop count */
331
332 ".align 2 \n"
333 ".ashlsi3: \n" /* C library routine: */
334 ".long ___ashlsi3 \n" /* shift r4 left by r5, return in r0 */
335 ".lshrsi3: \n" /* C library routine: */
336 ".long ___lshrsi3 \n" /* shift r4 right by r5, return in r0 */
337 /* both routines preserve r4, destroy r5 and take ~16 cycles */
338
339 ".gb_patdone: \n"
340 : /* outputs */
341 : /* inputs */
342 /* %0 */ "r"(src),
343 /* %1 */ "r"(stride),
344 /* %2 */ "r"(graybuf->depth),
345 /* %3 */ "r"(graybuf->bitpattern),
346 /* %4 */ "r"(&gray_random_buffer),
347 /* %5 */ "r"(graybuf->randmask)
348 : /* clobbers */
349 "r0", "r1", "r2", "r3", "r4", "r5", "macl"
350 );
351
352 /* calculate start address in first bitplane and end address */
353 register unsigned char *address = graybuf->data + x
354 + MULU16(graybuf->width, by);
355 register unsigned char *end_addr = address
356 + MULU16(graybuf->depth, graybuf->plane_size);
357
358 /* set the bits for all 8 pixels in all bytes according to the
359 * precalculated patterns on the stack */
360 asm (
361 "mov.l @r15+,r1 \n" /* pop all 8 patterns */
362 "mov.l @r15+,r2 \n"
363 "mov.l @r15+,r3 \n"
364 "mov.l @r15+,r4 \n"
365 "mov.l @r15+,r5 \n"
366 "mov.l @r15+,r6 \n"
367 "mov.l @r15+,r7 \n"
368 "mov.l @r15+,r8 \n"
369
370 ".gb_loop: \n" /* loop for all bitplanes */
371 "shlr r1 \n" /* rotate lsb of pattern 1 to t bit */
372 "rotcl r0 \n" /* rotate t bit into r0 */
373 "shlr r2 \n"
374 "rotcl r0 \n"
375 "shlr r3 \n"
376 "rotcl r0 \n"
377 "shlr r4 \n"
378 "rotcl r0 \n"
379 "shlr r5 \n"
380 "rotcl r0 \n"
381 "shlr r6 \n"
382 "rotcl r0 \n"
383 "shlr r7 \n"
384 "rotcl r0 \n"
385 "shlr r8 \n"
386 "rotcl r0 \n"
387 "mov.b r0,@%0 \n" /* store byte to bitplane */
388 "add %2,%0 \n" /* advance to next bitplane */
389 "cmp/hi %0,%1 \n" /* last bitplane done? */
390 "bt .gb_loop \n" /* no: loop */
391 : /* outputs */
392 : /* inputs */
393 /* %0 */ "r"(address),
394 /* %1 */ "r"(end_addr),
395 /* %2 */ "r"(graybuf->plane_size)
396 : /* clobbers */
397 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"
398 );
399}
400
262/* Invert the bits for 1-8 pixels within the buffer */ 401/* Invert the bits for 1-8 pixels within the buffer */
263void grayinvertmasked(int x, int by, unsigned char mask) 402void grayinvertmasked(int x, int by, unsigned char mask)
264{ 403{
@@ -335,7 +474,9 @@ int gray_init_buffer(unsigned char *gbuf, int gbuf_size, int width,
335 int possible_depth, plane_size; 474 int possible_depth, plane_size;
336 int i, j; 475 int i, j;
337 476
338 if (width > LCD_WIDTH || bheight > (LCD_HEIGHT >> 3) || depth < 1) 477 if ((unsigned) width > LCD_WIDTH
478 || (unsigned) bheight > (LCD_HEIGHT >> 3)
479 || depth < 1)
339 return 0; 480 return 0;
340 481
341 while ((unsigned long)gbuf & 3) /* the buffer has to be long aligned */ 482 while ((unsigned long)gbuf & 3) /* the buffer has to be long aligned */
@@ -472,7 +613,7 @@ void gray_show_display(bool enable)
472 if (enable) 613 if (enable)
473 { 614 {
474 graybuf->flags |= GRAY_RUNNING; 615 graybuf->flags |= GRAY_RUNNING;
475 rb->plugin_register_timer(FREQ / 67, 1, timer_isr); 616 rb->plugin_register_timer(FREQ / 67, 1, gray_timer_isr);
476 } 617 }
477 else 618 else
478 { 619 {
@@ -532,7 +673,7 @@ void gray_clear_display(void)
532 if (graybuf == NULL) 673 if (graybuf == NULL)
533 return; 674 return;
534 675
535 rb->memset(graybuf->data, 0, graybuf->depth * graybuf->plane_size); 676 rb->memset(graybuf->data, 0, MULU16(graybuf->depth, graybuf->plane_size));
536} 677}
537 678
538/* Set the grayscale display to all black 679/* Set the grayscale display to all black
@@ -542,7 +683,7 @@ void gray_black_display(void)
542 if (graybuf == NULL) 683 if (graybuf == NULL)
543 return; 684 return;
544 685
545 rb->memset(graybuf->data, 0xFF, graybuf->depth * graybuf->plane_size); 686 rb->memset(graybuf->data, 0xFF, MULU16(graybuf->depth, graybuf->plane_size));
546} 687}
547 688
548/* Do a lcd_update() to show changes done by rb->lcd_xxx() functions (in areas 689/* Do a lcd_update() to show changes done by rb->lcd_xxx() functions (in areas
@@ -566,11 +707,11 @@ void gray_deferred_update(void)
566 */ 707 */
567void gray_scroll_left(int count, bool black_border) 708void gray_scroll_left(int count, bool black_border)
568{ 709{
569 int x, by, d; 710 int by, d;
570 unsigned char *src, *dest; 711 unsigned char *ptr;
571 unsigned char filler; 712 unsigned char filler;
572 713
573 if (graybuf == NULL || count >= graybuf->width) 714 if (graybuf == NULL || (unsigned) count >= (unsigned) graybuf->width)
574 return; 715 return;
575 716
576 if (black_border) 717 if (black_border)
@@ -581,17 +722,42 @@ void gray_scroll_left(int count, bool black_border)
581 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ 722 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */
582 for (by = 0; by < graybuf->bheight; by++) 723 for (by = 0; by < graybuf->bheight; by++)
583 { 724 {
725 ptr = graybuf->data + MULU16(graybuf->width, by);
584 for (d = 0; d < graybuf->depth; d++) 726 for (d = 0; d < graybuf->depth; d++)
585 { 727 {
586 dest = graybuf->data + graybuf->plane_size * d 728 if (count & 1) /* odd count: scroll byte-wise */
587 + graybuf->width * by; 729 asm volatile (
588 src = dest + count; 730 ".sl_loop1: \n"
589 731 "mov.b @%0+,r1 \n"
590 for (x = count; x < graybuf->width; x++) 732 "mov.b r1,@(%2,%0) \n"
591 *dest++ = *src++; 733 "cmp/hi %0,%1 \n"
592 734 "bt .sl_loop1 \n"
593 for (x = 0; x < count; x++) 735 : /* outputs */
594 *dest++ = filler; 736 : /* inputs */
737 /* %0 */ "r"(ptr + count),
738 /* %1 */ "r"(ptr + graybuf->width),
739 /* %2 */ "z"(-count - 1)
740 : /* clobbers */
741 "r1"
742 );
743 else /* even count: scroll word-wise */
744 asm volatile (
745 ".sl_loop2: \n"
746 "mov.w @%0+,r1 \n"
747 "mov.w r1,@(%2,%0) \n"
748 "cmp/hi %0,%1 \n"
749 "bt .sl_loop2 \n"
750 : /* outputs */
751 : /* inputs */
752 /* %0 */ "r"(ptr + count),
753 /* %1 */ "r"(ptr + graybuf->width),
754 /* %2 */ "z"(-count - 2)
755 : /* clobbers */
756 "r1"
757 );
758
759 rb->memset(ptr + graybuf->width - count, filler, count);
760 ptr += graybuf->plane_size;
595 } 761 }
596 } 762 }
597} 763}
@@ -603,11 +769,11 @@ void gray_scroll_left(int count, bool black_border)
603 */ 769 */
604void gray_scroll_right(int count, bool black_border) 770void gray_scroll_right(int count, bool black_border)
605{ 771{
606 int x, by, d; 772 int by, d;
607 unsigned char *src, *dest; 773 unsigned char *ptr;
608 unsigned char filler; 774 unsigned char filler;
609 775
610 if (graybuf == NULL || count >= graybuf->width) 776 if (graybuf == NULL || (unsigned) count >= (unsigned) graybuf->width)
611 return; 777 return;
612 778
613 if (black_border) 779 if (black_border)
@@ -618,17 +784,42 @@ void gray_scroll_right(int count, bool black_border)
618 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ 784 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */
619 for (by = 0; by < graybuf->bheight; by++) 785 for (by = 0; by < graybuf->bheight; by++)
620 { 786 {
787 ptr = graybuf->data + MULU16(graybuf->width, by);
621 for (d = 0; d < graybuf->depth; d++) 788 for (d = 0; d < graybuf->depth; d++)
622 { 789 {
623 dest = graybuf->data + graybuf->plane_size * d 790 if (count & 1) /* odd count: scroll byte-wise */
624 + graybuf->width * (by + 1) - 1; 791 asm volatile (
625 src = dest - count; 792 ".sr_loop1: \n"
626 793 "mov.b @(%2,%0),r1 \n"
627 for (x = count; x < graybuf->width; x++) 794 "mov.b r1,@-%0 \n"
628 *dest-- = *src--; 795 "cmp/hs %1,%0 \n"
629 796 "bt .sr_loop1 \n"
630 for (x = 0; x < count; x++) 797 : /* outputs */
631 *dest-- = filler; 798 : /* inputs */
799 /* %0 */ "r"(ptr + graybuf->width),
800 /* %1 */ "r"(ptr + count),
801 /* %2 */ "z"(-count - 1)
802 : /* clobbers */
803 "r1"
804 );
805 else /* even count: scroll word-wise */
806 asm volatile (
807 ".sr_loop2: \n"
808 "mov.w @(%2,%0),r1 \n"
809 "mov.w r1,@-%0 \n"
810 "cmp/hs %1,%0 \n"
811 "bt .sr_loop2 \n"
812 : /* outputs */
813 : /* inputs */
814 /* %0 */ "r"(ptr + graybuf->width),
815 /* %1 */ "r"(ptr + count),
816 /* %2 */ "z"(-count - 2)
817 : /* clobbers */
818 "r1"
819 );
820
821 rb->memset(ptr, filler, count);
822 ptr += graybuf->plane_size;
632 } 823 }
633 } 824 }
634} 825}
@@ -641,7 +832,7 @@ void gray_scroll_right(int count, bool black_border)
641void gray_scroll_up8(bool black_border) 832void gray_scroll_up8(bool black_border)
642{ 833{
643 int by, d; 834 int by, d;
644 unsigned char *src; 835 unsigned char *ptr;
645 unsigned char filler; 836 unsigned char filler;
646 837
647 if (graybuf == NULL) 838 if (graybuf == NULL)
@@ -655,18 +846,19 @@ void gray_scroll_up8(bool black_border)
655 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ 846 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */
656 for (by = 1; by < graybuf->bheight; by++) 847 for (by = 1; by < graybuf->bheight; by++)
657 { 848 {
849 ptr = graybuf->data + MULU16(graybuf->width, by);
658 for (d = 0; d < graybuf->depth; d++) 850 for (d = 0; d < graybuf->depth; d++)
659 { 851 {
660 src = graybuf->data + graybuf->plane_size * d 852 rb->memcpy(ptr - graybuf->width, ptr, graybuf->width);
661 + graybuf->width * by; 853 ptr += graybuf->plane_size;
662
663 rb->memcpy(src - graybuf->width, src, graybuf->width);
664 } 854 }
665 } 855 }
666 for (d = 0; d < graybuf->depth; d++) /* fill last row */ 856 /* fill last row */
857 ptr = graybuf->data + graybuf->plane_size - graybuf->width;
858 for (d = 0; d < graybuf->depth; d++)
667 { 859 {
668 rb->memset(graybuf->data + graybuf->plane_size * (d + 1) 860 rb->memset(ptr, filler, graybuf->width);
669 - graybuf->width, filler, graybuf->width); 861 ptr += graybuf->plane_size;
670 } 862 }
671} 863}
672 864
@@ -678,7 +870,7 @@ void gray_scroll_up8(bool black_border)
678void gray_scroll_down8(bool black_border) 870void gray_scroll_down8(bool black_border)
679{ 871{
680 int by, d; 872 int by, d;
681 unsigned char *dest; 873 unsigned char *ptr;
682 unsigned char filler; 874 unsigned char filler;
683 875
684 if (graybuf == NULL) 876 if (graybuf == NULL)
@@ -692,18 +884,19 @@ void gray_scroll_down8(bool black_border)
692 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */ 884 /* Scroll row by row to minimize flicker (byte rows = 8 pixels each) */
693 for (by = graybuf->bheight - 1; by > 0; by--) 885 for (by = graybuf->bheight - 1; by > 0; by--)
694 { 886 {
887 ptr = graybuf->data + MULU16(graybuf->width, by);
695 for (d = 0; d < graybuf->depth; d++) 888 for (d = 0; d < graybuf->depth; d++)
696 { 889 {
697 dest = graybuf->data + graybuf->plane_size * d 890 rb->memcpy(ptr, ptr - graybuf->width, graybuf->width);
698 + graybuf->width * by; 891 ptr += graybuf->plane_size;
699
700 rb->memcpy(dest, dest - graybuf->width, graybuf->width);
701 } 892 }
702 } 893 }
703 for (d = 0; d < graybuf->depth; d++) /* fill first row */ 894 /* fill first row */
895 ptr = graybuf->data;
896 for (d = 0; d < graybuf->depth; d++)
704 { 897 {
705 rb->memset(graybuf->data + graybuf->plane_size * d, filler, 898 rb->memset(ptr, filler, graybuf->width);
706 graybuf->width); 899 ptr += graybuf->plane_size;
707 } 900 }
708} 901}
709 902
@@ -851,12 +1044,14 @@ void gray_scroll_down1(bool black_border)
851 */ 1044 */
852void gray_drawpixel(int x, int y, int brightness) 1045void gray_drawpixel(int x, int y, int brightness)
853{ 1046{
854 if (graybuf == NULL || x >= graybuf->width || y >= graybuf->height 1047 if (graybuf == NULL
855 || brightness > 255) 1048 || (unsigned) x >= (unsigned) graybuf->width
1049 || (unsigned) y >= (unsigned) graybuf->height
1050 || (unsigned) brightness > 255)
856 return; 1051 return;
857 1052
858 graypixel(x, y, graybuf->bitpattern[(brightness 1053 graypixel(x, y, graybuf->bitpattern[MULU16(brightness,
859 * (graybuf->depth + 1)) >> 8]); 1054 graybuf->depth + 1) >> 8]);
860} 1055}
861 1056
862/* Invert a pixel 1057/* Invert a pixel
@@ -866,7 +1061,9 @@ void gray_drawpixel(int x, int y, int brightness)
866 */ 1061 */
867void gray_invertpixel(int x, int y) 1062void gray_invertpixel(int x, int y)
868{ 1063{
869 if (graybuf == NULL || x >= graybuf->width || y >= graybuf->height) 1064 if (graybuf == NULL
1065 || (unsigned) x >= (unsigned) graybuf->width
1066 || (unsigned) y >= (unsigned) graybuf->height)
870 return; 1067 return;
871 1068
872 grayinvertmasked(x, (y >> 3), 1 << (y & 7)); 1069 grayinvertmasked(x, (y >> 3), 1 << (y & 7));
@@ -886,14 +1083,20 @@ void gray_drawline(int x1, int y1, int x2, int y2, int brightness)
886 int y, yinc1, yinc2; 1083 int y, yinc1, yinc2;
887 unsigned long pattern; 1084 unsigned long pattern;
888 1085
889 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height 1086 if (graybuf == NULL
890 || x2 >= graybuf->width || y2 >= graybuf->height|| brightness > 255) 1087 || (unsigned) x1 >= (unsigned) graybuf->width
1088 || (unsigned) y1 >= (unsigned) graybuf->height
1089 || (unsigned) x2 >= (unsigned) graybuf->width
1090 || (unsigned) y2 >= (unsigned) graybuf->height
1091 || (unsigned) brightness > 255)
891 return; 1092 return;
892 1093
893 pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8]; 1094 pattern = graybuf->bitpattern[MULU16(brightness, graybuf->depth + 1) >> 8];
894 1095
895 deltax = abs(x2 - x1); 1096 deltax = abs(x2 - x1);
896 deltay = abs(y2 - y1); 1097 deltay = abs(y2 - y1);
1098 xinc2 = 1;
1099 yinc2 = 1;
897 1100
898 if (deltax >= deltay) 1101 if (deltax >= deltay)
899 { 1102 {
@@ -902,9 +1105,7 @@ void gray_drawline(int x1, int y1, int x2, int y2, int brightness)
902 dinc1 = deltay * 2; 1105 dinc1 = deltay * 2;
903 dinc2 = (deltay - deltax) * 2; 1106 dinc2 = (deltay - deltax) * 2;
904 xinc1 = 1; 1107 xinc1 = 1;
905 xinc2 = 1;
906 yinc1 = 0; 1108 yinc1 = 0;
907 yinc2 = 1;
908 } 1109 }
909 else 1110 else
910 { 1111 {
@@ -913,9 +1114,7 @@ void gray_drawline(int x1, int y1, int x2, int y2, int brightness)
913 dinc1 = deltax * 2; 1114 dinc1 = deltax * 2;
914 dinc2 = (deltax - deltay) * 2; 1115 dinc2 = (deltax - deltay) * 2;
915 xinc1 = 0; 1116 xinc1 = 0;
916 xinc2 = 1;
917 yinc1 = 1; 1117 yinc1 = 1;
918 yinc2 = 1;
919 } 1118 }
920 numpixels++; /* include endpoints */ 1119 numpixels++; /* include endpoints */
921 1120
@@ -967,12 +1166,17 @@ void gray_invertline(int x1, int y1, int x2, int y2)
967 int x, xinc1, xinc2; 1166 int x, xinc1, xinc2;
968 int y, yinc1, yinc2; 1167 int y, yinc1, yinc2;
969 1168
970 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height 1169 if (graybuf == NULL
971 || x2 >= graybuf->width || y2 >= graybuf->height) 1170 || (unsigned) x1 >= (unsigned) graybuf->width
1171 || (unsigned) y1 >= (unsigned) graybuf->height
1172 || (unsigned) x2 >= (unsigned) graybuf->width
1173 || (unsigned) y2 >= (unsigned) graybuf->height)
972 return; 1174 return;
973 1175
974 deltax = abs(x2 - x1); 1176 deltax = abs(x2 - x1);
975 deltay = abs(y2 - y1); 1177 deltay = abs(y2 - y1);
1178 xinc2 = 1;
1179 yinc2 = 1;
976 1180
977 if (deltax >= deltay) 1181 if (deltax >= deltay)
978 { 1182 {
@@ -981,9 +1185,7 @@ void gray_invertline(int x1, int y1, int x2, int y2)
981 dinc1 = deltay * 2; 1185 dinc1 = deltay * 2;
982 dinc2 = (deltay - deltax) * 2; 1186 dinc2 = (deltay - deltax) * 2;
983 xinc1 = 1; 1187 xinc1 = 1;
984 xinc2 = 1;
985 yinc1 = 0; 1188 yinc1 = 0;
986 yinc2 = 1;
987 } 1189 }
988 else 1190 else
989 { 1191 {
@@ -992,9 +1194,7 @@ void gray_invertline(int x1, int y1, int x2, int y2)
992 dinc1 = deltax * 2; 1194 dinc1 = deltax * 2;
993 dinc2 = (deltax - deltay) * 2; 1195 dinc2 = (deltax - deltay) * 2;
994 xinc1 = 0; 1196 xinc1 = 0;
995 xinc2 = 1;
996 yinc1 = 1; 1197 yinc1 = 1;
997 yinc2 = 1;
998 } 1198 }
999 numpixels++; /* include endpoints */ 1199 numpixels++; /* include endpoints */
1000 1200
@@ -1041,13 +1241,16 @@ void gray_drawrect(int x1, int y1, int x2, int y2, int brightness)
1041{ 1241{
1042 int x, y; 1242 int x, y;
1043 unsigned long pattern; 1243 unsigned long pattern;
1044 1244 unsigned char srcpixel;
1045 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height 1245
1046 || x2 >= graybuf->width || y2 >= graybuf->height|| brightness > 255) 1246 if (graybuf == NULL
1247 || (unsigned) x1 >= (unsigned) graybuf->width
1248 || (unsigned) y1 >= (unsigned) graybuf->height
1249 || (unsigned) x2 >= (unsigned) graybuf->width
1250 || (unsigned) y2 >= (unsigned) graybuf->height
1251 || (unsigned) brightness > 255)
1047 return; 1252 return;
1048 1253
1049 pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8];
1050
1051 if (y1 > y2) 1254 if (y1 > y2)
1052 { 1255 {
1053 y = y1; 1256 y = y1;
@@ -1061,15 +1264,30 @@ void gray_drawrect(int x1, int y1, int x2, int y2, int brightness)
1061 x2 = x; 1264 x2 = x;
1062 } 1265 }
1063 1266
1064 for (x = x1; x <= x2; x++) 1267 pattern = graybuf->bitpattern[MULU16(brightness, graybuf->depth + 1) >> 8];
1268 srcpixel = brightness;
1269
1270 for (x = x1 + 1; x < x2; x++)
1065 { 1271 {
1066 graypixel(x, y1, pattern); 1272 graypixel(x, y1, pattern);
1067 graypixel(x, y2, pattern); 1273 graypixel(x, y2, pattern);
1068 } 1274 }
1069 for (y = y1; y <= y2; y++) 1275 for (y = y1; y <= y2; )
1070 { 1276 {
1071 graypixel(x1, y, pattern); 1277 if (!(y & 7) && (y2 - y >= 7))
1072 graypixel(x2, y, pattern); 1278 /* current row byte aligned in fb & at least 8 rows left */
1279 {
1280 /* shortcut: draw all 8 rows at once: 2..3 times faster */
1281 grayblock(x1, y >> 3, &srcpixel, 0);
1282 grayblock(x2, y >> 3, &srcpixel, 0);
1283 y += 8;
1284 }
1285 else
1286 {
1287 graypixel(x1, y, pattern);
1288 graypixel(x2, y, pattern);
1289 y++;
1290 }
1073 } 1291 }
1074} 1292}
1075 1293
@@ -1082,9 +1300,14 @@ void gray_fillrect(int x1, int y1, int x2, int y2, int brightness)
1082{ 1300{
1083 int x, y; 1301 int x, y;
1084 unsigned long pattern; 1302 unsigned long pattern;
1085 1303 unsigned char srcpixel;
1086 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height 1304
1087 || x2 >= graybuf->width || y2 >= graybuf->height || brightness > 255) 1305 if (graybuf == NULL
1306 || (unsigned) x1 >= (unsigned) graybuf->width
1307 || (unsigned) y1 >= (unsigned) graybuf->height
1308 || (unsigned) x2 >= (unsigned) graybuf->width
1309 || (unsigned) y2 >= (unsigned) graybuf->height
1310 || (unsigned) brightness > 255)
1088 return; 1311 return;
1089 1312
1090 if (y1 > y2) 1313 if (y1 > y2)
@@ -1100,13 +1323,28 @@ void gray_fillrect(int x1, int y1, int x2, int y2, int brightness)
1100 x2 = x; 1323 x2 = x;
1101 } 1324 }
1102 1325
1103 pattern = graybuf->bitpattern[(brightness * (graybuf->depth + 1)) >> 8]; 1326 pattern = graybuf->bitpattern[MULU16(brightness, graybuf->depth + 1) >> 8];
1327 srcpixel = brightness;
1104 1328
1105 for (y = y1; y <= y2; y++) 1329 for (y = y1; y <= y2; )
1106 { 1330 {
1107 for (x = x1; x <= x2; x++) 1331 if (!(y & 7) && (y2 - y >= 7))
1332 /* current row byte aligned in fb & at least 8 rows left */
1108 { 1333 {
1109 graypixel(x, y, pattern); 1334 for (x = x1; x <= x2; x++)
1335 {
1336 /* shortcut: draw all 8 rows at once: 2..3 times faster */
1337 grayblock(x, y >> 3, &srcpixel, 0);
1338 }
1339 y += 8;
1340 }
1341 else
1342 {
1343 for (x = x1; x <= x2; x++)
1344 {
1345 graypixel(x, y, pattern);
1346 }
1347 y++;
1110 } 1348 }
1111 } 1349 }
1112} 1350}
@@ -1122,8 +1360,11 @@ void gray_invertrect(int x1, int y1, int x2, int y2)
1122 int x, yb, yb1, yb2; 1360 int x, yb, yb1, yb2;
1123 unsigned char mask; 1361 unsigned char mask;
1124 1362
1125 if (graybuf == NULL || x1 >= graybuf->width || y1 >= graybuf->height 1363 if (graybuf == NULL
1126 || x2 >= graybuf->width || y2 >= graybuf->height) 1364 || (unsigned) x1 >= (unsigned) graybuf->width
1365 || (unsigned) y1 >= (unsigned) graybuf->height
1366 || (unsigned) x2 >= (unsigned) graybuf->width
1367 || (unsigned) y2 >= (unsigned) graybuf->height)
1127 return; 1368 return;
1128 1369
1129 if (y1 > y2) 1370 if (y1 > y2)
@@ -1175,7 +1416,7 @@ void gray_invertrect(int x1, int y1, int x2, int y2)
1175 * A grayscale bitmap contains one byte for every pixel that defines the 1416 * A grayscale bitmap contains one byte for every pixel that defines the
1176 * brightness of the pixel (0..255). Bytes are read in row-major order. 1417 * brightness of the pixel (0..255). Bytes are read in row-major order.
1177 * The <stride> parameter is useful if you want to show only a part of a 1418 * The <stride> parameter is useful if you want to show only a part of a
1178 * bitmap. It should always be set to the "line length" of the bitmap, so 1419 * bitmap. It should always be set to the "row length" of the bitmap, so
1179 * for displaying the whole bitmap, nx == stride. 1420 * for displaying the whole bitmap, nx == stride.
1180 */ 1421 */
1181void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny, 1422void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny,
@@ -1184,7 +1425,9 @@ void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny,
1184 int xi, yi; 1425 int xi, yi;
1185 unsigned char *row; 1426 unsigned char *row;
1186 1427
1187 if (graybuf == NULL || x >= graybuf->width || y >= graybuf->height) 1428 if (graybuf == NULL
1429 || (unsigned) x >= (unsigned) graybuf->width
1430 || (unsigned) y >= (unsigned) graybuf->height)
1188 return; 1431 return;
1189 1432
1190 if ((y + ny) >= graybuf->height) /* clip bottom */ 1433 if ((y + ny) >= graybuf->height) /* clip bottom */
@@ -1193,28 +1436,49 @@ void gray_drawgraymap(unsigned char *src, int x, int y, int nx, int ny,
1193 if ((x + nx) >= graybuf->width) /* clip right */ 1436 if ((x + nx) >= graybuf->width) /* clip right */
1194 nx = graybuf->width - x; 1437 nx = graybuf->width - x;
1195 1438
1196 for (yi = y; yi < y + ny; yi++) 1439 for (yi = y; yi < y + ny; )
1197 { 1440 {
1198 row = src; 1441 row = src;
1199 src += stride; 1442
1200 for (xi = x; xi < x + nx; xi++) 1443 if (!(yi & 7) && (y + ny - yi > 7))
1444 /* current row byte aligned in fb & at least 8 rows left */
1445 {
1446 for (xi = x; xi < x + nx; xi++)
1447 {
1448 /* shortcut: draw all 8 rows at once: 2..3 times faster */
1449 grayblock(xi, yi >> 3, row++, stride);
1450 }
1451 yi += 8;
1452 src += stride << 3;
1453 }
1454 else
1201 { 1455 {
1202 graypixel(xi, yi, graybuf->bitpattern[((int)(*row++) 1456 for (xi = x; xi < x + nx; xi++)
1203 * (graybuf->depth + 1)) >> 8]); 1457 {
1458 graypixel(xi, yi, graybuf->bitpattern[MULU16(*row++,
1459 graybuf->depth + 1) >> 8]);
1460 }
1461 yi++;
1462 src += stride;
1204 } 1463 }
1205 } 1464 }
1206} 1465}
1207 1466
1208/* Display a bitmap with specific foreground and background gray values 1467/* Display a bitmap with specific foreground and background gray values
1209 * 1468 *
1469 * This (now) uses the same bitmap format as the core b&w graphics routines,
1470 * so you can use bmp2rb to generate bitmaps for use with this function as
1471 * well.
1472 *
1210 * A bitmap contains one bit for every pixel that defines if that pixel is 1473 * A bitmap contains one bit for every pixel that defines if that pixel is
1211 * foreground (1) or background (0). Bytes are read in row-major order, MSB 1474 * foreground (1) or background (0). Bits within a byte are arranged
1212 * first. A row consists of an integer number of bytes, extra bits past the 1475 * vertically, LSB at top.
1213 * right margin are ignored. 1476 * The bytes are stored in row-major order, with byte 0 being top left,
1477 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
1478 * 0..7, the second row defines pixel row 8..15 etc.
1479 *
1214 * The <stride> parameter is useful if you want to show only a part of a 1480 * The <stride> parameter is useful if you want to show only a part of a
1215 * bitmap. It should always be set to the "line length" of the bitmap. 1481 * bitmap. It should always be set to the "row length" of the bitmap.
1216 * Beware that this is counted in bytes, so nx == 8 * stride for the whole
1217 * bitmap.
1218 * 1482 *
1219 * If draw_bg is false, only foreground pixels are drawn, so the background 1483 * If draw_bg is false, only foreground pixels are drawn, so the background
1220 * is transparent. In this case bg_brightness is ignored. 1484 * is transparent. In this case bg_brightness is ignored.
@@ -1223,51 +1487,54 @@ void gray_drawbitmap(unsigned char *src, int x, int y, int nx, int ny,
1223 int stride, bool draw_bg, int fg_brightness, 1487 int stride, bool draw_bg, int fg_brightness,
1224 int bg_brightness) 1488 int bg_brightness)
1225{ 1489{
1226 int xi, yi, i; 1490 int xi, dy;
1491 int bits = 0; /* Have to initialize to prevent warning */
1227 unsigned long fg_pattern, bg_pattern; 1492 unsigned long fg_pattern, bg_pattern;
1228 unsigned long bits = 0; /* Have to initialize to prevent warning */ 1493 unsigned char *col;
1229 unsigned char *row;
1230 1494
1231 if (graybuf == NULL || x >= graybuf->width || y >= graybuf->height 1495 if (graybuf == NULL
1232 || fg_brightness > 255 || bg_brightness > 255) 1496 || (unsigned) x >= (unsigned) graybuf->width
1497 || (unsigned) y >= (unsigned) graybuf->height
1498 || (unsigned) fg_brightness > 255
1499 || (unsigned) bg_brightness > 255)
1233 return; 1500 return;
1234 1501
1235 if ((y + ny) >= graybuf->height) /* clip bottom */ 1502 if ((y + ny) >= graybuf->height) /* clip bottom */
1236 ny = graybuf->height - y; 1503 ny = graybuf->height - y;
1237 1504
1238 if ((x + nx) >= graybuf->width) /* clip right */ 1505 if ((x + nx) >= graybuf->width) /* clip right */
1239 nx = graybuf->width - x; 1506 nx = graybuf->width - x;
1240 1507
1241 fg_pattern = graybuf->bitpattern[(fg_brightness 1508 fg_pattern = graybuf->bitpattern[MULU16(fg_brightness,
1242 * (graybuf->depth + 1)) >> 8]; 1509 graybuf->depth + 1) >> 8];
1243 1510
1244 bg_pattern = graybuf->bitpattern[(bg_brightness 1511 bg_pattern = graybuf->bitpattern[MULU16(bg_brightness,
1245 * (graybuf->depth + 1)) >> 8]; 1512 graybuf->depth + 1) >> 8];
1246 1513
1247 for (yi = y; yi < y + ny; yi++) 1514 for (xi = x; xi < x + nx; xi++)
1248 { 1515 {
1249 i = 0; 1516 col = src++;
1250 row = src; 1517 for (dy = 0; dy < ny; dy++)
1251 src += stride;
1252 for (xi = x; xi < x + nx; xi++)
1253 { 1518 {
1254 if (i == 0) /* get next 8 bits */ 1519 if (!(dy & 7)) /* get next 8 bits */
1255 bits = (unsigned long)(*row++); 1520 {
1521 bits = (int)(*col);
1522 col += stride;
1523 }
1256 1524
1257 if (bits & 0x80) 1525 if (bits & 0x01)
1258 graypixel(xi, yi, fg_pattern); 1526 graypixel(xi, y + dy, fg_pattern);
1259 else 1527 else
1260 if (draw_bg) 1528 if (draw_bg)
1261 graypixel(xi, yi, bg_pattern); 1529 graypixel(xi, y + dy, bg_pattern);
1262 1530
1263 bits <<= 1; 1531 bits >>= 1;
1264 i++;
1265 i &= 7;
1266 } 1532 }
1267 } 1533 }
1268} 1534}
1269 1535
1270/**************** end grayscale framework ********************/ 1536/*********************** end grayscale framework ***************************/
1537
1271 1538
1272/* for portability of below JPEG code */ 1539/* for portability of below JPEG code */
1273#define MEMSET(p,v,c) rb->memset(p,v,c) 1540#define MEMSET(p,v,c) rb->memset(p,v,c)