From e49cade42d00e8b1f6836f9e9c436cda67cf6437 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Sun, 5 Feb 2006 12:59:10 +0000 Subject: Colour targets: Adapted mandelbrot plugin. The plugin library now contains scrolling routines for >= 8 bpp displays. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8578 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/lib/xlcd.c | 114 ++++++++++++++++++++++++++++++++ apps/plugins/lib/xlcd.h | 5 ++ apps/plugins/mandelbrot.c | 164 +++++++++++++++++++++++++++++++++++----------- 3 files changed, 245 insertions(+), 38 deletions(-) (limited to 'apps/plugins') diff --git a/apps/plugins/lib/xlcd.c b/apps/plugins/lib/xlcd.c index a0dcc2ac3e..33d807f2f3 100644 --- a/apps/plugins/lib/xlcd.c +++ b/apps/plugins/lib/xlcd.c @@ -105,5 +105,119 @@ void xlcd_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3) } } +#if LCD_DEPTH >= 8 +/* FIXME: intermediate solution until we have properly optimised memmove() */ +static void *my_memmove(void *dst0, const void *src0, size_t len0) +{ + char *dst = (char *) dst0; + char *src = (char *) src0; + + if (dst <= src) + { + while (len0--) + *dst++ = *src++; + } + else + { + dst += len0; + src += len0; + + while (len0--) + *(--dst) = *(--src); + } + + return dst0; +} + +void xlcd_scroll_left(int count) +{ + fb_data *data, *data_end; + int length, oldmode; + + if ((unsigned)count >= LCD_WIDTH) + return; + + data = local_rb->lcd_framebuffer; + data_end = data + LCD_WIDTH*LCD_HEIGHT; + length = LCD_WIDTH - count; + + do + { + my_memmove(data, data + count, length * sizeof(fb_data)); + data += LCD_WIDTH; + } + while (data < data_end); + + oldmode = local_rb->lcd_get_drawmode(); + local_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + local_rb->lcd_fillrect(length, 0, count, LCD_HEIGHT); + local_rb->lcd_set_drawmode(oldmode); +} + +void xlcd_scroll_right(int count) +{ + fb_data *data, *data_end; + int length, oldmode; + + if ((unsigned)count >= LCD_WIDTH) + return; + + data = local_rb->lcd_framebuffer; + data_end = data + LCD_WIDTH*LCD_HEIGHT; + length = LCD_WIDTH - count; + + do + { + my_memmove(data + count, data, length * sizeof(fb_data)); + data += LCD_WIDTH; + } + while (data < data_end); + + oldmode = local_rb->lcd_get_drawmode(); + local_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + local_rb->lcd_fillrect(0, 0, count, LCD_HEIGHT); + local_rb->lcd_set_drawmode(oldmode); +} + +void xlcd_scroll_up(int count) +{ + long length, oldmode; + + if ((unsigned)count >= LCD_HEIGHT) + return; + + length = LCD_HEIGHT - count; + + my_memmove(local_rb->lcd_framebuffer, + local_rb->lcd_framebuffer + count * LCD_WIDTH, + length * LCD_WIDTH * sizeof(fb_data)); + + oldmode = local_rb->lcd_get_drawmode(); + local_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + local_rb->lcd_fillrect(0, length, LCD_WIDTH, count); + local_rb->lcd_set_drawmode(oldmode); +} + +void xlcd_scroll_down(int count) +{ + long length, oldmode; + + if ((unsigned)count >= LCD_HEIGHT) + return; + + length = LCD_HEIGHT - count; + + my_memmove(local_rb->lcd_framebuffer + count * LCD_WIDTH, + local_rb->lcd_framebuffer, + length * LCD_WIDTH * sizeof(fb_data)); + + oldmode = local_rb->lcd_get_drawmode(); + local_rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + local_rb->lcd_fillrect(0, 0, LCD_WIDTH, count); + local_rb->lcd_set_drawmode(oldmode); +} + +#endif /* LCD_DEPTH >= 8 */ + #endif /* HAVE_LCD_BITMAP */ diff --git a/apps/plugins/lib/xlcd.h b/apps/plugins/lib/xlcd.h index 3f54643ec9..2eaa05cd0d 100644 --- a/apps/plugins/lib/xlcd.h +++ b/apps/plugins/lib/xlcd.h @@ -29,6 +29,11 @@ void xlcd_init(struct plugin_api* newrb); void xlcd_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3); +void xlcd_scroll_left(int count); +void xlcd_scroll_right(int count); +void xlcd_scroll_up(int count); +void xlcd_scroll_down(int count); + #endif /* HAVE_LCD_BITMAP */ #endif /* __XLCD_H__ */ diff --git a/apps/plugins/mandelbrot.c b/apps/plugins/mandelbrot.c index 1d2b48cb8b..db478d5e25 100644 --- a/apps/plugins/mandelbrot.c +++ b/apps/plugins/mandelbrot.c @@ -18,17 +18,21 @@ * KIND, either express or implied. * ****************************************************************************/ -#ifndef SIMULATOR #include "plugin.h" -#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) +#if defined(HAVE_LCD_BITMAP) && ((LCD_DEPTH >= 8) || !defined(SIMULATOR)) #include "gray.h" +#include "xlcd.h" PLUGIN_HEADER /* variable button definitions */ #if CONFIG_KEYPAD == RECORDER_PAD #define MANDELBROT_QUIT BUTTON_OFF +#define MANDELBROT_UP BUTTON_UP +#define MANDELBROT_DOWN BUTTON_DOWN +#define MANDELBROT_LEFT BUTTON_LEFT +#define MANDELBROT_RIGHT BUTTON_RIGHT #define MANDELBROT_ZOOM_IN BUTTON_PLAY #define MANDELBROT_ZOOM_OUT BUTTON_ON #define MANDELBROT_MAXITER_INC BUTTON_F2 @@ -37,6 +41,10 @@ PLUGIN_HEADER #elif CONFIG_KEYPAD == ONDIO_PAD #define MANDELBROT_QUIT BUTTON_OFF +#define MANDELBROT_UP BUTTON_UP +#define MANDELBROT_DOWN BUTTON_DOWN +#define MANDELBROT_LEFT BUTTON_LEFT +#define MANDELBROT_RIGHT BUTTON_RIGHT #define MANDELBROT_ZOOM_IN_PRE BUTTON_MENU #define MANDELBROT_ZOOM_IN (BUTTON_MENU | BUTTON_REL) #define MANDELBROT_ZOOM_IN2 (BUTTON_MENU | BUTTON_UP) @@ -45,17 +53,57 @@ PLUGIN_HEADER #define MANDELBROT_MAXITER_DEC (BUTTON_MENU | BUTTON_LEFT) #define MANDELBROT_RESET (BUTTON_MENU | BUTTON_OFF) -#elif CONFIG_KEYPAD == IRIVER_H100_PAD +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) #define MANDELBROT_QUIT BUTTON_OFF +#define MANDELBROT_UP BUTTON_UP +#define MANDELBROT_DOWN BUTTON_DOWN +#define MANDELBROT_LEFT BUTTON_LEFT +#define MANDELBROT_RIGHT BUTTON_RIGHT #define MANDELBROT_ZOOM_IN BUTTON_SELECT #define MANDELBROT_ZOOM_OUT BUTTON_MODE #define MANDELBROT_MAXITER_INC (BUTTON_ON | BUTTON_RIGHT) #define MANDELBROT_MAXITER_DEC (BUTTON_ON | BUTTON_LEFT) #define MANDELBROT_RESET BUTTON_REC + +#elif CONFIG_KEYPAD == IPOD_4G_PAD +#define MANDELBROT_QUIT (BUTTON_SELECT | BUTTON_MENU) +#define MANDELBROT_UP BUTTON_MENU +#define MANDELBROT_DOWN BUTTON_PLAY +#define MANDELBROT_LEFT BUTTON_LEFT +#define MANDELBROT_RIGHT BUTTON_RIGHT +#define MANDELBROT_ZOOM_IN BUTTON_SCROLL_FWD +#define MANDELBROT_ZOOM_OUT BUTTON_SCROLL_BACK +#define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT) +#define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT) +#define MANDELBROT_RESET (BUTTON_SELECT | BUTTON_PLAY) + +#elif CONFIG_KEYPAD == IAUDIO_X5_PAD +#define MANDELBROT_QUIT BUTTON_POWER +#define MANDELBROT_UP BUTTON_UP +#define MANDELBROT_DOWN BUTTON_DOWN +#define MANDELBROT_LEFT BUTTON_LEFT +#define MANDELBROT_RIGHT BUTTON_RIGHT +#define MANDELBROT_ZOOM_IN_PRE BUTTON_MENU +#define MANDELBROT_ZOOM_IN (BUTTON_MENU | BUTTON_REL) +#define MANDELBROT_ZOOM_OUT (BUTTON_MENU | BUTTON_REPEAT) +#define MANDELBROT_MAXITER_INC (BUTTON_PLAY | BUTTON_RIGHT) +#define MANDELBROT_MAXITER_DEC (BUTTON_PLAY | BUTTON_LEFT) +#define MANDELBROT_RESET BUTTON_REC +#endif + +#if LCD_DEPTH < 8 +#define USEGSLIB +#define MYLCD(fn) gray_ub_ ## fn +#define MYLCD_UPDATE() +#define MYXLCD(fn) gray_ub_ ## fn +#else +#define MYLCD(fn) rb->lcd_ ## fn +#define MYLCD_UPDATE() rb->lcd_update(); +#define MYXLCD(fn) xlcd_ ## fn #endif static struct plugin_api* rb; -static char buff[32]; /* Fixed point format: 6 bits integer part incl. sign, 26 bits fractional part */ static long x_min; @@ -75,9 +123,26 @@ static int py_max = LCD_HEIGHT; static int step_log2; static unsigned max_iter; +#ifdef USEGSLIB static unsigned char *gbuf; static unsigned int gbuf_size = 0; -static unsigned char graybuffer[LCD_HEIGHT]; +static unsigned char imgbuffer[LCD_HEIGHT]; +#else +static fb_data imgbuffer[LCD_HEIGHT]; +#endif + +/* 8 entries cyclical, last entry is black (convergence) */ +#ifdef HAVE_LCD_COLOR +static const fb_data color[9] = { + LCD_RGBPACK(255, 0, 159), LCD_RGBPACK(159, 0, 255), LCD_RGBPACK(0, 0, 255), + LCD_RGBPACK(0, 159, 255), LCD_RGBPACK(0, 255, 128), LCD_RGBPACK(128, 255, 0), + LCD_RGBPACK(255, 191, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 0, 0) +}; +#else /* greyscale */ +static const fb_data color[9] = { + 255, 223, 191, 159, 128, 96, 64, 32, 0 +}; +#endif #if CONFIG_CPU == SH7034 @@ -244,7 +309,7 @@ void init_mandelbrot_set(void) #if CONFIG_LCD == LCD_SSD1815 /* Recorder, Ondio. */ x_min = -38L<<22; // -2.375<<26 x_max = 15L<<22; // 0.9375<<26 -#else /* Iriver H1x0 */ +#else /* all others (square pixels) */ x_min = -36L<<22; // -2.25<<26 x_max = 12L<<22; // 0.75<<26 #endif @@ -260,7 +325,6 @@ void calc_mandelbrot_low_prec(void) long a32, b32; short x, x2, y, y2, a, b; int p_x, p_y; - int brightness; start_tick = last_yield = *rb->current_tick; @@ -286,13 +350,11 @@ void calc_mandelbrot_low_prec(void) x = x2 - y2 + a; } - // "coloring" - if (n_iter > max_iter){ - brightness = 0; // black - } else { - brightness = 255 - (32 * (n_iter & 7)); - } - graybuffer[p_y] = brightness; + if (n_iter > max_iter) + imgbuffer[p_y] = color[8]; + else + imgbuffer[p_y] = color[n_iter & 7]; + /* be nice to other threads: * if at least one tick has passed, yield */ if (*rb->current_tick > last_yield) { @@ -300,8 +362,14 @@ void calc_mandelbrot_low_prec(void) last_yield = *rb->current_tick; } } - gray_ub_gray_bitmap_part(graybuffer, 0, py_min, 1, +#ifdef USEGSLIB + gray_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1, p_x, py_min, 1, py_max-py_min); +#else + rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1, + p_x, py_min, 1, py_max-py_min); + rb->lcd_update_rect(p_x, py_min, 1, py_max-py_min); +#endif } } @@ -311,8 +379,7 @@ void calc_mandelbrot_high_prec(void) unsigned n_iter; long x, x2, y, y2, a, b; int p_x, p_y; - int brightness; - + MULS32_INIT(); start_tick = last_yield = *rb->current_tick; @@ -336,13 +403,11 @@ void calc_mandelbrot_high_prec(void) x = x2 - y2 + a; } - // "coloring" - if (n_iter > max_iter){ - brightness = 0; // black - } else { - brightness = 255 - (32 * (n_iter & 7)); - } - graybuffer[p_y] = brightness; + if (n_iter > max_iter) + imgbuffer[p_y] = color[8]; + else + imgbuffer[p_y] = color[n_iter & 7]; + /* be nice to other threads: * if at least one tick has passed, yield */ if (*rb->current_tick > last_yield) { @@ -350,16 +415,23 @@ void calc_mandelbrot_high_prec(void) last_yield = *rb->current_tick; } } - gray_ub_gray_bitmap_part(graybuffer, 0, py_min, 1, +#ifdef USEGSLIB + gray_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1, p_x, py_min, 1, py_max-py_min); +#else + rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1, + p_x, py_min, 1, py_max-py_min); + rb->lcd_update_rect(p_x, py_min, 1, py_max-py_min); +#endif } } void cleanup(void *parameter) { (void)parameter; - +#ifdef USEGSLIB gray_release(); +#endif } #define REDRAW_NONE 0 @@ -370,12 +442,16 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { int button; int lastbutton = BUTTON_NONE; - int grayscales; int redraw = REDRAW_FULL; +#ifdef USEGSLIB + int grayscales; + char buff[32]; +#endif rb = api; (void)parameter; +#ifdef USEGSLIB /* get the remainder of the plugin buffer */ gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); @@ -392,6 +468,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) } gray_show(true); /* switch on grayscale overlay */ +#else + xlcd_init(rb); +#endif init_mandelbrot_set(); @@ -401,8 +480,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) #if !defined(SIMULATOR) && defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(true); #endif - if (redraw == REDRAW_FULL) - gray_ub_clear_display(); + if (redraw == REDRAW_FULL) { + MYLCD(clear_display)(); + MYLCD_UPDATE(); + } if (step_log2 <= -10) /* select precision */ calc_mandelbrot_high_prec(); @@ -422,7 +503,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) button = rb->button_get(true); switch (button) { case MANDELBROT_QUIT: +#ifdef USEGSLIB gray_release(); +#endif return PLUGIN_OK; case MANDELBROT_ZOOM_OUT: @@ -451,34 +534,38 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) redraw = REDRAW_FULL; break; - case BUTTON_UP: + case MANDELBROT_UP: y_min += y_delta; y_max += y_delta; - gray_ub_scroll_down(LCD_HEIGHT/8); + MYXLCD(scroll_down)(LCD_HEIGHT/8); + MYLCD_UPDATE(); py_max = (LCD_HEIGHT/8); redraw = REDRAW_PARTIAL; break; - case BUTTON_DOWN: + case MANDELBROT_DOWN: y_min -= y_delta; y_max -= y_delta; - gray_ub_scroll_up(LCD_HEIGHT/8); + MYXLCD(scroll_up)(LCD_HEIGHT/8); + MYLCD_UPDATE(); py_min = (LCD_HEIGHT-LCD_HEIGHT/8); redraw = REDRAW_PARTIAL; break; - case BUTTON_LEFT: + case MANDELBROT_LEFT: x_min -= x_delta; x_max -= x_delta; - gray_ub_scroll_right(LCD_WIDTH/8); + MYXLCD(scroll_right)(LCD_WIDTH/8); + MYLCD_UPDATE(); px_max = (LCD_WIDTH/8); redraw = REDRAW_PARTIAL; break; - case BUTTON_RIGHT: + case MANDELBROT_RIGHT: x_min += x_delta; x_max += x_delta; - gray_ub_scroll_left(LCD_WIDTH/8); + MYXLCD(scroll_left)(LCD_WIDTH/8); + MYLCD_UPDATE(); px_min = (LCD_WIDTH-LCD_WIDTH/8); redraw = REDRAW_PARTIAL; break; @@ -509,8 +596,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) if (button != BUTTON_NONE) lastbutton = button; } +#ifdef USEGSLIB gray_release(); +#endif return PLUGIN_OK; } #endif -#endif -- cgit v1.2.3