diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES index 95ffb1c..92b6ab4 100644 --- a/apps/plugins/SOURCES +++ b/apps/plugins/SOURCES @@ -1,4 +1,5 @@ /* plugins common to all models */ +test_gfx.c chessclock.c credits.c cube.c diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 47407cc..2182975 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -592,6 +592,126 @@ static void draw_oriented_mono_bitmap_part(const unsigned char *src, while (src < src_end); } +/* draw alpha bitmap for anti-alias font */ +#define ALPHA_COLOR_FONT_DEPTH 2 +#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) +#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) +#define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) +#ifdef CPU_ARM +#define BLEND_INIT do {} while (0) +#define BLEND_START(acc, color, alpha) asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha)) +#define BLEND_CONT(acc, color, alpha) asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha)) +#define BLEND_OUT(acc) do {} while (0) +#elif defined(CPU_COLDFIRE) +#define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED) +#define BLEND_START(acc, color, alpha) asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha)) +#define BLEND_CONT BLEND_START +#define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc)) +#else +#define BLEND_INIT do {} while (0) +#define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha)) +#define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha)) +#define BLEND_OUT(acc) do {} while (0) +#endif + +/* Blend the given two colors */ +static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a) +{ + a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + c1 = swap16(c1); + c2 = swap16(c2); +#endif + unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f; + unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f; + unsigned p; + BLEND_START(p, c1l, a); + BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a); + BLEND_OUT(p); + p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; + p |= (p >> 16); +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + return swap16(p); +#else + return p; +#endif +} + +static void draw_oriented_alpha_bitmap_part(const unsigned char *src, + int src_x, int src_y, + int stride, int x, int y, + int width, int height) +{ + fb_data *dst, *dst_start; + unsigned fg_pattern, bg_pattern; + + if (x + width > SCREEN_WIDTH) + width = SCREEN_WIDTH - x; /* Clip right */ + if (x < 0) + width += x, x = 0; /* Clip left */ + if (width <= 0) + return; /* nothing left to do */ + + if (y + height > SCREEN_HEIGHT) + height = SCREEN_HEIGHT - y; /* Clip bottom */ + if (y < 0) + height += y, y = 0; /* Clip top */ + if (height <= 0) + return; /* nothing left to do */ + + /* initialize blending */ + BLEND_INIT; + + fg_pattern = rb->lcd_get_foreground(); + bg_pattern = rb->lcd_get_background(); + + dst_start = rb->lcd_framebuffer + (LCD_WIDTH - y - 1) + x*LCD_WIDTH; + + const char skip_start = src_y * stride + src_x; + const char skip_end = (stride - width); + int col, row = height; + unsigned char data, subcol; + + src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; + subcol = skip_start % ALPHA_COLOR_PIXEL_PER_BYTE; + data = *src; + data >>= subcol * ALPHA_COLOR_LOOKUP_SHIFT; + + do + { + col = width; + dst = dst_start--; + + do + { + *dst=blend_two_colors(*dst, fg_pattern, + data & ALPHA_COLOR_LOOKUP_SIZE ); + dst += LCD_WIDTH; +#if ALPHA_COLOR_PIXEL_PER_BYTE == 2 + if (subcol ^= 1) + data >>= ALPHA_COLOR_LOOKUP_SHIFT; + else + data = *(++src); +#else + if (subcol = (subcol + 1) % ALPHA_COLOR_PIXEL_PER_BYTE) + data >>= ALPHA_COLOR_LOOKUP_SHIFT; + else + data = *(++src); +#endif + } + while (--col); + subcol += skip_end; + if (subcol >= ALPHA_COLOR_PIXEL_PER_BYTE) + { + src += subcol / ALPHA_COLOR_PIXEL_PER_BYTE; + subcol %= ALPHA_COLOR_PIXEL_PER_BYTE; + data = *src; + data >>= subcol * ALPHA_COLOR_LOOKUP_SHIFT; + } else + data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; + } while (--row); +} + static void draw_putsxy_oriented(int x, int y, const char *str) { unsigned short ch; @@ -619,8 +739,12 @@ static void draw_putsxy_oriented(int x, int y, const char *str) bits = rb->font_get_bits(pf, ch); - draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, - width - ofs, pf->height); + if (pf->depth) + draw_oriented_alpha_bitmap_part(bits, ofs, 0, width, x, y, + width - ofs, pf->height); + else + draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, + width - ofs, pf->height); x += width - ofs; ofs = 0; diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c index 219f013..da98c45 100644 --- a/apps/plugins/rockpaint.c +++ b/apps/plugins/rockpaint.c @@ -486,6 +486,132 @@ static void buffer_mono_bitmap_part( } while( src < src_end ); } +/* draw alpha bitmap for anti-alias font */ +#define ALPHA_COLOR_FONT_DEPTH 2 +#define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) +#define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) +#define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) +#ifdef CPU_ARM +#define BLEND_INIT do {} while (0) +#define BLEND_START(acc, color, alpha) asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha)) +#define BLEND_CONT(acc, color, alpha) asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha)) +#define BLEND_OUT(acc) do {} while (0) +#elif defined(CPU_COLDFIRE) +#define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED) +#define BLEND_START(acc, color, alpha) asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha)) +#define BLEND_CONT BLEND_START +#define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc)) +#else +#define BLEND_INIT do {} while (0) +#define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha)) +#define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha)) +#define BLEND_OUT(acc) do {} while (0) +#endif + +/* Blend the given two colors */ +static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a) +{ + a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + c1 = swap16(c1); + c2 = swap16(c2); +#endif + unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f; + unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f; + unsigned p; + BLEND_START(p, c1l, a); + BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a); + BLEND_OUT(p); + p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; + p |= (p >> 16); +#if (LCD_PIXELFORMAT == RGB565SWAPPED) + return swap16(p); +#else + return p; +#endif +} + +static void buffer_alpha_bitmap_part( + fb_data *buf, int buf_width, int buf_height, + const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height ) +{ + fb_data *dst; + unsigned fg_pattern = rb->lcd_get_foreground(); + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= buf_width) || + (y >= buf_height) || (x + width <= 0) || (y + height <= 0)) + return; + + /* initialize blending */ + BLEND_INIT; + + /* clipping */ + if (x < 0) + { + width += x; + src_x -= x; + x = 0; + } + if (y < 0) + { + height += y; + src_y -= y; + y = 0; + } + if (x + width > buf_width) + width = buf_width - x; + if (y + height > buf_height) + height = buf_height - y; + + dst = buf + y*buf_width + x; + + const char skip_start = src_y * stride + src_x; + const char skip_end = (stride - width); + int col, row = height; + unsigned char data, subcol; + + src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; + subcol = skip_start % ALPHA_COLOR_PIXEL_PER_BYTE; + data = *src; + data >>= subcol * ALPHA_COLOR_LOOKUP_SHIFT; + + do + { + col = width; + + do + { + *dst=blend_two_colors(*dst, fg_pattern, + data & ALPHA_COLOR_LOOKUP_SIZE ); + dst++; +#if ALPHA_COLOR_PIXEL_PER_BYTE == 2 + if (subcol ^= 1) + data >>= ALPHA_COLOR_LOOKUP_SHIFT; + else + data = *(++src); +#else + if (subcol = (subcol + 1) % ALPHA_COLOR_PIXEL_PER_BYTE) + data >>= ALPHA_COLOR_LOOKUP_SHIFT; + else + data = *(++src); +#endif + } + while (--col); + subcol += skip_end; + if (subcol >= ALPHA_COLOR_PIXEL_PER_BYTE) + { + src += subcol / ALPHA_COLOR_PIXEL_PER_BYTE; + subcol %= ALPHA_COLOR_PIXEL_PER_BYTE; + data = *src; + data >>= subcol * ALPHA_COLOR_LOOKUP_SHIFT; + } else + data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; + dst += LCD_WIDTH - width; + } while (--row); +} + static void buffer_putsxyofs( fb_data *buf, int buf_width, int buf_height, int x, int y, int ofs, const unsigned char *str ) { @@ -513,8 +639,12 @@ static void buffer_putsxyofs( fb_data *buf, int buf_width, int buf_height, bits = rb->font_get_bits( pf, ch ); - buffer_mono_bitmap_part( buf, buf_width, buf_height, bits, ofs, 0, - width, x, y, width - ofs, pf->height); + if (pf->depth) + buffer_alpha_bitmap_part( buf, buf_width, buf_height, bits, ofs, 0, + width, x, y, width - ofs, pf->height); + else + buffer_mono_bitmap_part( buf, buf_width, buf_height, bits, ofs, 0, + width, x, y, width - ofs, pf->height); x += width - ofs; ofs = 0; diff --git a/apps/plugins/test_gfx.c b/apps/plugins/test_gfx.c index 728eb56..f653736 100644 --- a/apps/plugins/test_gfx.c +++ b/apps/plugins/test_gfx.c @@ -398,6 +398,60 @@ static void time_text(void) /* tests mono_bitmap performance */ count1, count2, count3, count4); } +static void time_text_user(void) /* tests mono_bitmap performance */ +{ + long time_start; /* start tickcount */ + long time_end; /* end tickcount */ + int count1, count2, count3, count4; + + rb->lcd_setfont(FONT_UI); + + /* Test 1: DRMODE_SOLID */ + MYLCD(set_drawmode)(DRMODE_SOLID); + count1 = 0; + rb->sleep(0); /* sync to tick */ + time_start = *rb->current_tick; + while((time_end = *rb->current_tick) - time_start < DURATION) + { + unsigned rnd = rand_table[count1++ & 0x3ff]; + MYLCD(putsxy)((rnd >> 8) & 0x3f, rnd & 0x3f, "Rockbox!"); + } + + /* Test 2: DRMODE_FG */ + MYLCD(set_drawmode)(DRMODE_FG); + count2 = 0; + rb->sleep(0); /* sync to tick */ + time_start = *rb->current_tick; + while((time_end = *rb->current_tick) - time_start < DURATION) + { + unsigned rnd = rand_table[count2++ & 0x3ff]; + MYLCD(putsxy)((rnd >> 8) & 0x3f, rnd & 0x3f, "Rockbox!"); + } + /* Test 3: DRMODE_BG */ + MYLCD(set_drawmode)(DRMODE_BG); + count3 = 0; + rb->sleep(0); /* sync to tick */ + time_start = *rb->current_tick; + while((time_end = *rb->current_tick) - time_start < DURATION) + { + unsigned rnd = rand_table[count3++ & 0x3ff]; + MYLCD(putsxy)((rnd >> 8) & 0x3f, rnd & 0x3f, "Rockbox!"); + } + /* Test 4: DRMODE_COMPLEMENT */ + MYLCD(set_drawmode)(DRMODE_COMPLEMENT); + count4 = 0; + rb->sleep(0); /* sync to tick */ + time_start = *rb->current_tick; + while((time_end = *rb->current_tick) - time_start < DURATION) + { + unsigned rnd = rand_table[count4++ & 0x3ff]; + MYLCD(putsxy)((rnd >> 8) & 0x3f, rnd & 0x3f, "Rockbox!"); + } + + rb->fdprintf(log_fd, "lcd_putsxy (strings/s): %d/%d/%d/%d\n", + count1, count2, count3, count4); +} + /* plugin entry point */ enum plugin_status plugin_start(const void* parameter) { @@ -456,6 +510,7 @@ enum plugin_status plugin_start(const void* parameter) time_vline(); time_fillrect(); time_text(); + time_text_user(); #ifndef SIMULATOR if (*rb->cpu_frequency != cpu_freq)