summaryrefslogtreecommitdiff
path: root/apps/plugins/lib/gray_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lib/gray_core.c')
-rw-r--r--apps/plugins/lib/gray_core.c206
1 files changed, 154 insertions, 52 deletions
diff --git a/apps/plugins/lib/gray_core.c b/apps/plugins/lib/gray_core.c
index d151250e69..80ce984b29 100644
--- a/apps/plugins/lib/gray_core.c
+++ b/apps/plugins/lib/gray_core.c
@@ -10,10 +10,10 @@
10* Greyscale framework 10* Greyscale framework
11* Core & miscellaneous functions 11* Core & miscellaneous functions
12* 12*
13* This is a generic framework to use grayscale display within Rockbox 13* This is a generic framework to display up to 33 shades of grey
14* plugins. It obviously does not work for the player. 14* on low-depth bitmap LCDs (Archos b&w, Iriver 4-grey) within plugins.
15* 15*
16* Copyright (C) 2004-2005 Jens Arnold 16* Copyright (C) 2004-2006 Jens Arnold
17* 17*
18* All files in this archive are subject to the GNU General Public License. 18* All files in this archive are subject to the GNU General Public License.
19* See the file COPYING in the source tree root for full license agreement. 19* See the file COPYING in the source tree root for full license agreement.
@@ -23,21 +23,49 @@
23* 23*
24****************************************************************************/ 24****************************************************************************/
25 25
26#ifndef SIMULATOR /* not for simulator by now */
27#include "plugin.h" 26#include "plugin.h"
28 27
29#ifdef HAVE_LCD_BITMAP /* and also not for the Player */ 28#ifdef HAVE_LCD_BITMAP
30#include "gray.h" 29#include "gray.h"
31 30
32/* Global variables */ 31/* Global variables */
33struct plugin_api *_gray_rb = NULL; /* global api struct pointer */ 32struct plugin_api *_gray_rb = NULL; /* global api struct pointer */
34struct _gray_info _gray_info; /* global info structure */ 33struct _gray_info _gray_info; /* global info structure */
34#ifndef SIMULATOR
35short _gray_random_buffer; /* buffer for random number generator */ 35short _gray_random_buffer; /* buffer for random number generator */
36#endif
36 37
37/* Prototypes */ 38/* Prototypes */
39static inline void _deferred_update(void) __attribute__ ((always_inline));
40#ifdef SIMULATOR
41static unsigned long _gray_get_pixel(int x, int y);
42#else
38static void _timer_isr(void); 43static void _timer_isr(void);
44#endif
39static void gray_screendump_hook(int fd); 45static void gray_screendump_hook(int fd);
40 46
47/* Update LCD areas not covered by the greyscale overlay */
48static inline void _deferred_update(void)
49{
50 int x1 = MAX(_gray_info.x, 0);
51 int x2 = MIN(_gray_info.x + _gray_info.width, LCD_WIDTH);
52 int y1 = MAX(_gray_info.by << _PBLOCK_EXP, 0);
53 int y2 = MIN((_gray_info.by << _PBLOCK_EXP) + _gray_info.height, LCD_HEIGHT);
54
55 if (y1 > 0) /* refresh part above overlay, full width */
56 _gray_rb->lcd_update_rect(0, 0, LCD_WIDTH, y1);
57
58 if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */
59 _gray_rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2);
60
61 if (x1 > 0) /* refresh part to the left of overlay */
62 _gray_rb->lcd_update_rect(0, y1, x1, y2 - y1);
63
64 if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */
65 _gray_rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1);
66}
67
68#ifndef SIMULATOR
41/* Timer interrupt handler: display next bitplane */ 69/* Timer interrupt handler: display next bitplane */
42static void _timer_isr(void) 70static void _timer_isr(void)
43{ 71{
@@ -50,26 +78,11 @@ static void _timer_isr(void)
50 78
51 if (_gray_info.flags & _GRAY_DEFERRED_UPDATE) /* lcd_update() requested? */ 79 if (_gray_info.flags & _GRAY_DEFERRED_UPDATE) /* lcd_update() requested? */
52 { 80 {
53 int x1 = MAX(_gray_info.x, 0); 81 _deferred_update();
54 int x2 = MIN(_gray_info.x + _gray_info.width, LCD_WIDTH);
55 int y1 = MAX(_gray_info.by << _PBLOCK_EXP, 0);
56 int y2 = MIN((_gray_info.by << _PBLOCK_EXP) + _gray_info.height, LCD_HEIGHT);
57
58 if (y1 > 0) /* refresh part above overlay, full width */
59 _gray_rb->lcd_update_rect(0, 0, LCD_WIDTH, y1);
60
61 if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */
62 _gray_rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2);
63
64 if (x1 > 0) /* refresh part to the left of overlay */
65 _gray_rb->lcd_update_rect(0, y1, x1, y2 - y1);
66
67 if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */
68 _gray_rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1);
69
70 _gray_info.flags &= ~_GRAY_DEFERRED_UPDATE; /* clear request */ 82 _gray_info.flags &= ~_GRAY_DEFERRED_UPDATE; /* clear request */
71 } 83 }
72} 84}
85#endif /* !SIMULATOR */
73 86
74/* Initialise the framework and prepare the greyscale display buffer 87/* Initialise the framework and prepare the greyscale display buffer
75 88
@@ -108,13 +121,21 @@ static void _timer_isr(void)
108 + (width * bheight) * depth (bitplane data) 121 + (width * bheight) * depth (bitplane data)
109 + buffered ? (chunky front- & backbuffer) 122 + buffered ? (chunky front- & backbuffer)
110 (width * bheight * 8 * 2) : 0 123 (width * bheight * 8 * 2) : 0
111 + 0..3 (longword alignment) */ 124 + 0..3 (longword alignment)
125
126 The function tries to be as authentic as possible regarding memory usage on
127 the simulator, even if it doesn't use all of the allocated memory. There's
128 one situation where it will consume more memory on the sim than on the
129 target: if you're allocating a low depth (< 8) without buffering. */
112int gray_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size, 130int gray_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
113 bool buffered, int width, int bheight, int depth, long *buf_taken) 131 bool buffered, int width, int bheight, int depth, long *buf_taken)
114{ 132{
115 int possible_depth, i, j; 133 int possible_depth;
116 long plane_size, buftaken; 134 long plane_size, buftaken;
117 135#ifndef SIMULATOR
136 int i, j;
137#endif
138
118 _gray_rb = newrb; 139 _gray_rb = newrb;
119 140
120 if ((unsigned) width > LCD_WIDTH 141 if ((unsigned) width > LCD_WIDTH
@@ -152,19 +173,41 @@ int gray_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
152 depth = MIN(depth, 32); 173 depth = MIN(depth, 32);
153 depth = MIN(depth, possible_depth); 174 depth = MIN(depth, possible_depth);
154 175
176#ifdef SIMULATOR
177 if (!buffered)
178 {
179 long orig_size = depth * plane_size + (depth + 1) * sizeof(long);
180
181 plane_size = MULU16(width, bheight << _PBLOCK_EXP);
182 if (plane_size > orig_size)
183 {
184 buftaken += plane_size;
185 if (buftaken > gbuf_size)
186 return 0;
187 }
188 else
189 {
190 buftaken += orig_size;
191 }
192 _gray_info.cur_buffer = gbuf;
193 }
194 else
195#endif
196 buftaken += depth * plane_size + (depth + 1) * sizeof(long);
197
155 _gray_info.x = 0; 198 _gray_info.x = 0;
156 _gray_info.by = 0; 199 _gray_info.by = 0;
157 _gray_info.width = width; 200 _gray_info.width = width;
158 _gray_info.height = bheight << _PBLOCK_EXP; 201 _gray_info.height = bheight << _PBLOCK_EXP;
159 _gray_info.bheight = bheight; 202 _gray_info.bheight = bheight;
160 _gray_info.plane_size = plane_size;
161 _gray_info.depth = depth; 203 _gray_info.depth = depth;
162 _gray_info.cur_plane = 0;
163 _gray_info.flags = 0; 204 _gray_info.flags = 0;
205#ifndef SIMULATOR
206 _gray_info.cur_plane = 0;
207 _gray_info.plane_size = plane_size;
164 _gray_info.plane_data = gbuf; 208 _gray_info.plane_data = gbuf;
165 gbuf += depth * plane_size; 209 gbuf += depth * plane_size;
166 _gray_info.bitpattern = (unsigned long *)gbuf; 210 _gray_info.bitpattern = (unsigned long *)gbuf;
167 buftaken += depth * plane_size + (depth + 1) * sizeof(long);
168 211
169 i = depth - 1; 212 i = depth - 1;
170 j = 8; 213 j = 8;
@@ -195,6 +238,7 @@ int gray_init(struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
195 238
196 _gray_info.bitpattern[i] = pattern; 239 _gray_info.bitpattern[i] = pattern;
197 } 240 }
241#endif
198 242
199 _gray_info.fg_brightness = 0; 243 _gray_info.fg_brightness = 0;
200 _gray_info.bg_brightness = depth; 244 _gray_info.bg_brightness = depth;
@@ -229,6 +273,10 @@ void gray_show(bool enable)
229 if (enable && !(_gray_info.flags & _GRAY_RUNNING)) 273 if (enable && !(_gray_info.flags & _GRAY_RUNNING))
230 { 274 {
231 _gray_info.flags |= _GRAY_RUNNING; 275 _gray_info.flags |= _GRAY_RUNNING;
276#ifdef SIMULATOR
277 _gray_rb->sim_lcd_ex_init(_gray_info.depth + 1, _gray_get_pixel);
278 gray_update();
279#else /* !SIMULATOR */
232#if CONFIG_LCD == LCD_SSD1815 280#if CONFIG_LCD == LCD_SSD1815
233 _gray_rb->timer_register(1, NULL, CPU_FREQ / 67, 1, _timer_isr); 281 _gray_rb->timer_register(1, NULL, CPU_FREQ / 67, 1, _timer_isr);
234#elif CONFIG_LCD == LCD_S1D15E06 282#elif CONFIG_LCD == LCD_S1D15E06
@@ -236,18 +284,53 @@ void gray_show(bool enable)
236#elif CONFIG_LCD == LCD_IFP7XX 284#elif CONFIG_LCD == LCD_IFP7XX
237 /* TODO: implement for iFP */ 285 /* TODO: implement for iFP */
238 (void)_timer_isr; 286 (void)_timer_isr;
239#endif 287#endif /* CONFIG_LCD */
288#endif /* !SIMULATOR */
240 _gray_rb->screen_dump_set_hook(gray_screendump_hook); 289 _gray_rb->screen_dump_set_hook(gray_screendump_hook);
241 } 290 }
242 else if (!enable && (_gray_info.flags & _GRAY_RUNNING)) 291 else if (!enable && (_gray_info.flags & _GRAY_RUNNING))
243 { 292 {
293#ifdef SIMULATOR
294 _gray_rb->sim_lcd_ex_init(0, NULL);
295#else
244 _gray_rb->timer_unregister(); 296 _gray_rb->timer_unregister();
297#endif
245 _gray_info.flags &= ~_GRAY_RUNNING; 298 _gray_info.flags &= ~_GRAY_RUNNING;
246 _gray_rb->screen_dump_set_hook(NULL); 299 _gray_rb->screen_dump_set_hook(NULL);
247 _gray_rb->lcd_update(); /* restore whatever there was before */ 300 _gray_rb->lcd_update(); /* restore whatever there was before */
248 } 301 }
249} 302}
250 303
304#ifdef SIMULATOR
305/* Callback function for gray_update_rect() to read a pixel from the graybuffer.
306 Note that x and y are in LCD coordinates, not graybuffer coordinates! */
307static unsigned long _gray_get_pixel(int x, int y)
308{
309 return _gray_info.cur_buffer[MULU16(x - _gray_info.x, _gray_info.height)
310 + y - (_gray_info.by << _PBLOCK_EXP)]
311 + (1 << LCD_DEPTH);
312}
313
314/* Update a rectangular area of the greyscale overlay */
315void gray_update_rect(int x, int y, int width, int height)
316{
317 if (x + width > _gray_info.width)
318 width = _gray_info.width - x;
319 if (y + height > _gray_info.height)
320 height = _gray_info.height - y;
321
322 x += _gray_info.x;
323 y += _gray_info.by << _PBLOCK_EXP;
324
325 if (x + width > LCD_WIDTH)
326 width = LCD_WIDTH - x;
327 if (y + height > LCD_HEIGHT)
328 height = LCD_HEIGHT - y;
329
330 _gray_rb->sim_lcd_ex_update_rect(x, y, width, height);
331}
332
333#else /* !SIMULATOR */
251/* Update a rectangular area of the greyscale overlay */ 334/* Update a rectangular area of the greyscale overlay */
252void gray_update_rect(int x, int y, int width, int height) 335void gray_update_rect(int x, int y, int width, int height)
253{ 336{
@@ -647,7 +730,7 @@ void gray_update_rect(int x, int y, int width, int height)
647 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "a0", "a1" 730 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "a0", "a1"
648 ); 731 );
649 } 732 }
650#endif 733#endif /* CONFIG_CPU, LCD_DEPTH */
651 srcofs_row += _gray_info.height; 734 srcofs_row += _gray_info.height;
652 dst_row++; 735 dst_row++;
653 } 736 }
@@ -657,7 +740,6 @@ void gray_update_rect(int x, int y, int width, int height)
657 dst += _gray_info.width; 740 dst += _gray_info.width;
658 } 741 }
659} 742}
660
661#if CONFIG_CPU == SH7034 743#if CONFIG_CPU == SH7034
662/* References to C library routines used in gray_update_rect() */ 744/* References to C library routines used in gray_update_rect() */
663asm ( 745asm (
@@ -668,7 +750,9 @@ asm (
668 ".long ___lshrsi3 \n" /* shift r4 right by r5, return in r0 */ 750 ".long ___lshrsi3 \n" /* shift r4 right by r5, return in r0 */
669 /* both routines preserve r4, destroy r5 and take ~16 cycles */ 751 /* both routines preserve r4, destroy r5 and take ~16 cycles */
670); 752);
671#endif 753#endif /* CONFIG_CPU == SH7034 */
754
755#endif /* !SIMULATOR */
672 756
673/* Update the whole greyscale overlay */ 757/* Update the whole greyscale overlay */
674void gray_update(void) 758void gray_update(void)
@@ -681,7 +765,13 @@ void gray_update(void)
681void gray_deferred_lcd_update(void) 765void gray_deferred_lcd_update(void)
682{ 766{
683 if (_gray_info.flags & _GRAY_RUNNING) 767 if (_gray_info.flags & _GRAY_RUNNING)
768 {
769#ifdef SIMULATOR
770 _deferred_update();
771#else
684 _gray_info.flags |= _GRAY_DEFERRED_UPDATE; 772 _gray_info.flags |= _GRAY_DEFERRED_UPDATE;
773#endif
774 }
685 else 775 else
686 _gray_rb->lcd_update(); 776 _gray_rb->lcd_update();
687} 777}
@@ -745,17 +835,14 @@ static const unsigned char bmpheader[] =
745 content (b&w and greyscale overlay) to an 8-bit BMP file. */ 835 content (b&w and greyscale overlay) to an 8-bit BMP file. */
746static void gray_screendump_hook(int fd) 836static void gray_screendump_hook(int fd)
747{ 837{
748 int i, idx; 838 int i;
749 int x, y, by; 839 int x, y, by;
750 int gx, mask; 840 int gx, gy, mask;
751#if LCD_DEPTH == 1 841#if LCD_DEPTH == 2
752 int gby; 842 int shift;
753#elif LCD_DEPTH == 2
754 int shift, gy;
755#endif 843#endif
756 unsigned char *clut_entry; 844 unsigned char *clut_entry;
757 unsigned char *lcdptr; 845 unsigned char *lcdptr;
758 unsigned char *grayptr, *grayptr2;
759 unsigned char linebuf[MAX(4*BMP_VARCOLORS,BMP_LINESIZE)]; 846 unsigned char linebuf[MAX(4*BMP_VARCOLORS,BMP_LINESIZE)];
760 847
761 _gray_rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */ 848 _gray_rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */
@@ -778,16 +865,19 @@ static void gray_screendump_hook(int fd)
778 { 865 {
779 _gray_rb->memset(linebuf, 0, BMP_LINESIZE); 866 _gray_rb->memset(linebuf, 0, BMP_LINESIZE);
780 867
868 gy = y - (_gray_info.by << _PBLOCK_EXP);
781#if LCD_DEPTH == 1 869#if LCD_DEPTH == 1
782 mask = 1 << (y & (_PBLOCK-1)); 870 mask = 1 << (y & (_PBLOCK-1));
783 by = y >> _PBLOCK_EXP; 871 by = y >> _PBLOCK_EXP;
784 lcdptr = _gray_rb->lcd_framebuffer + MULU16(LCD_WIDTH, by); 872 lcdptr = _gray_rb->lcd_framebuffer + MULU16(LCD_WIDTH, by);
785 gby = by - _gray_info.by;
786 873
787 if ((unsigned) gby < (unsigned) _gray_info.bheight) 874 if ((unsigned) gy < (unsigned) _gray_info.height)
788 { 875 {
789 /* line contains greyscale (and maybe b&w) graphics */ 876 /* line contains greyscale (and maybe b&w) graphics */
790 grayptr = _gray_info.plane_data + MULU16(_gray_info.width, gby); 877#ifndef SIMULATOR
878 unsigned char *grayptr = _gray_info.plane_data
879 + MULU16(_gray_info.width, gy >> _PBLOCK_EXP);
880#endif
791 881
792 for (x = 0; x < LCD_WIDTH; x++) 882 for (x = 0; x < LCD_WIDTH; x++)
793 { 883 {
@@ -795,8 +885,12 @@ static void gray_screendump_hook(int fd)
795 885
796 if ((unsigned)gx < (unsigned)_gray_info.width) 886 if ((unsigned)gx < (unsigned)_gray_info.width)
797 { 887 {
798 idx = BMP_FIXEDCOLORS; 888#ifdef SIMULATOR
799 grayptr2 = grayptr + gx; 889 linebuf[x] = BMP_FIXEDCOLORS + _gray_info.depth
890 - _gray_info.cur_buffer[MULU16(gx, _gray_info.height) + gy];
891#else
892 int idx = BMP_FIXEDCOLORS;
893 unsigned char *grayptr2 = grayptr + gx;
800 894
801 for (i = _gray_info.depth; i > 0; i--) 895 for (i = _gray_info.depth; i > 0; i--)
802 { 896 {
@@ -805,6 +899,7 @@ static void gray_screendump_hook(int fd)
805 grayptr2 += _gray_info.plane_size; 899 grayptr2 += _gray_info.plane_size;
806 } 900 }
807 linebuf[x] = idx; 901 linebuf[x] = idx;
902#endif
808 } 903 }
809 else 904 else
810 { 905 {
@@ -823,14 +918,17 @@ static void gray_screendump_hook(int fd)
823 shift = 2 * (y & 3); 918 shift = 2 * (y & 3);
824 by = y >> 2; 919 by = y >> 2;
825 lcdptr = _gray_rb->lcd_framebuffer + MULU16(LCD_WIDTH, by); 920 lcdptr = _gray_rb->lcd_framebuffer + MULU16(LCD_WIDTH, by);
826 gy = y - (_gray_info.by << _PBLOCK_EXP); 921
827
828 if ((unsigned)gy < (unsigned)_gray_info.height) 922 if ((unsigned)gy < (unsigned)_gray_info.height)
829 { 923 {
830 /* line contains greyscale (and maybe b&w) graphics */ 924 /* line contains greyscale (and maybe b&w) graphics */
925#ifdef SIMULATOR
926 (void)mask;
927#else
928 unsigned char *grayptr = _gray_info.plane_data
929 + MULU16(_gray_info.width, gy >> _PBLOCK_EXP);
831 mask = 1 << (gy & (_PBLOCK-1)); 930 mask = 1 << (gy & (_PBLOCK-1));
832 grayptr = _gray_info.plane_data 931#endif
833 + MULU16(_gray_info.width, gy >> _PBLOCK_EXP);
834 932
835 for (x = 0; x < LCD_WIDTH; x++) 933 for (x = 0; x < LCD_WIDTH; x++)
836 { 934 {
@@ -838,8 +936,12 @@ static void gray_screendump_hook(int fd)
838 936
839 if ((unsigned)gx < (unsigned)_gray_info.width) 937 if ((unsigned)gx < (unsigned)_gray_info.width)
840 { 938 {
841 idx = BMP_FIXEDCOLORS; 939#ifdef SIMULATOR
842 grayptr2 = grayptr + gx; 940 linebuf[x] = BMP_FIXEDCOLORS + _gray_info.depth
941 - _gray_info.cur_buffer[MULU16(gx, _gray_info.height) + gy];
942#else
943 int idx = BMP_FIXEDCOLORS;
944 unsigned char *grayptr2 = grayptr + gx;
843 945
844 for (i = _gray_info.depth; i > 0; i--) 946 for (i = _gray_info.depth; i > 0; i--)
845 { 947 {
@@ -848,6 +950,7 @@ static void gray_screendump_hook(int fd)
848 grayptr2 += _gray_info.plane_size; 950 grayptr2 += _gray_info.plane_size;
849 } 951 }
850 linebuf[x] = idx; 952 linebuf[x] = idx;
953#endif
851 } 954 }
852 else 955 else
853 { 956 {
@@ -862,12 +965,11 @@ static void gray_screendump_hook(int fd)
862 for (x = 0; x < LCD_WIDTH; x++) 965 for (x = 0; x < LCD_WIDTH; x++)
863 linebuf[x] = (*lcdptr++ >> shift) & 3; 966 linebuf[x] = (*lcdptr++ >> shift) & 3;
864 } 967 }
865#endif 968#endif /* LCD_DEPTH */
866 969
867 _gray_rb->write(fd, linebuf, BMP_LINESIZE); 970 _gray_rb->write(fd, linebuf, BMP_LINESIZE);
868 } 971 }
869} 972}
870 973
871#endif /* HAVE_LCD_BITMAP */ 974#endif /* HAVE_LCD_BITMAP */
872#endif /* !SIMULATOR */
873 975