From c1d27d105c3333b5df67c97d88885efa2a49bc9a Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Mon, 1 Jun 2009 21:28:03 +0000 Subject: Speed up mono bitmap drawing on horizontally packed greyscale targets (greyscale iPods). Average speedup is 80% on PP5002, and 55% on PP502x. * Simplify mono bitmap drawing in the 16 bit driver and the greylib a bit, also giving a slight speedup (3% on PP502x, 1.5% on coldfire). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21163 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/lib/grey_draw.c | 3 +- firmware/drivers/lcd-16bit.c | 3 +- firmware/drivers/lcd-2bit-horz.c | 148 ++++++++++++++++++++++++++++++++------- 3 files changed, 124 insertions(+), 30 deletions(-) diff --git a/apps/plugins/lib/grey_draw.c b/apps/plugins/lib/grey_draw.c index c1e6376cfe..3b81694426 100644 --- a/apps/plugins/lib/grey_draw.c +++ b/apps/plugins/lib/grey_draw.c @@ -447,6 +447,7 @@ void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, src_end = src + width; dwidth = _grey_info.width; dst = &_grey_info.buffer[_GREY_MULUQ(dwidth, y) + x]; + dst_end = dst + _GREY_MULUQ(dwidth, height); if (drmode & DRMODE_INVERSEVID) { @@ -461,8 +462,6 @@ void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, unsigned data = (*src_col ^ dmask) >> src_y; int fg, bg; - dst_end = dst_col + _GREY_MULUQ(dwidth, height); - #define UPDATE_SRC do { \ data >>= 1; \ if (data == 0x001) { \ diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 0aa62f66b4..ef0865fc8c 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c @@ -752,6 +752,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y &= 7; src_end = src + width; dst = LCDADDR(current_vp->x + x, current_vp->y + y); + dst_end = dst + height * LCD_WIDTH; if (drmode & DRMODE_INVERSEVID) { @@ -767,8 +768,6 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, int fg, bg; long bo; - dst_end = dst_col + height * LCD_WIDTH; - #define UPDATE_SRC do { \ data >>= 1; \ if (data == 0x001) { \ diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c index 4dc82deae0..70f7261e35 100644 --- a/firmware/drivers/lcd-2bit-horz.c +++ b/firmware/drivers/lcd-2bit-horz.c @@ -690,10 +690,11 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, int stride, int x, int y, int width, int height) { - int ny, nx, ymax; - const unsigned char * src_end; - lcd_pixelfunc_type* fgfunc; - lcd_pixelfunc_type* bgfunc; + const unsigned char *src_end; + fb_data *dst, *dst_end; + unsigned dmask = 0x100; /* bit 8 == sentinel */ + unsigned dst_mask; + int drmode = current_vp->drawmode; /* nothing to draw? */ if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || @@ -718,42 +719,137 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, if (y + height > current_vp->height) height = current_vp->height - y; - /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; - src += stride * (src_y >> 3) + src_x; /* move starting point */ src_y &= 7; src_end = src + width; + x += current_vp->x; /* adjust for viewport */ + dst = &lcd_framebuffer[current_vp->y + y][x >> 2]; + dst_end = dst + height * LCD_FBWIDTH; + dst_mask = pixmask[x & 3]; + + if (drmode & DRMODE_INVERSEVID) + { + dmask = 0x1ff; /* bit 8 == sentinel */ + drmode &= DRMODE_SOLID; /* mask out inversevid */ + } - fgfunc = lcd_pixelfuncs[current_vp->drawmode]; - bgfunc = lcd_pixelfuncs[current_vp->drawmode ^ DRMODE_INVERSEVID]; - nx = x; do { const unsigned char *src_col = src++; - unsigned data = (*src_col | 0x100) >> src_y; /* bit 8 == sentinel */ - - ymax = y + height; - ny = y; - do + unsigned data = (*src_col ^ dmask) >> src_y; + fb_data *dst_col = dst; + int fg, bg; + long bo; + +#define UPDATE_SRC do { \ + data >>= 1; \ + if (data == 0x001) { \ + src_col += stride; \ + data = *src_col ^ dmask; \ + } \ + } while (0) + + switch (drmode) { - if (data & 0x01) - fgfunc(nx,ny); + case DRMODE_COMPLEMENT: + do + { + if (data & 0x01) + *dst_col ^= dst_mask; + + dst_col += LCD_FBWIDTH; + UPDATE_SRC; + } + while (dst_col < dst_end); + break; + + case DRMODE_BG: + if (lcd_backdrop) + { + bo = lcd_backdrop_offset; + do + { + if (!(data & 0x01)) + { + unsigned block = *dst_col; + *dst_col = block + ^ ((block ^ *(dst_col + bo)) & dst_mask); + } + dst_col += LCD_FBWIDTH; + UPDATE_SRC; + } + while (dst_col < dst_end); + } else - bgfunc(nx,ny); + { + bg = bg_pattern; + do + { + if (!(data & 0x01)) + { + unsigned block = *dst_col; + *dst_col = block ^ ((block ^ bg) & dst_mask); + } + dst_col += LCD_FBWIDTH; + UPDATE_SRC; + } + while (dst_col < dst_end); + } + break; - ny++; + case DRMODE_FG: + fg = fg_pattern; + do + { + if (data & 0x01) + { + unsigned block = *dst_col; + *dst_col = block ^ ((block ^ fg) & dst_mask); + } + dst_col += LCD_FBWIDTH; + UPDATE_SRC; + } + while (dst_col < dst_end); + break; - data >>= 1; - if (data == 0x001) + case DRMODE_SOLID: + fg = fg_pattern; + if (lcd_backdrop) + { + bo = lcd_backdrop_offset; + do + { + unsigned block = *dst_col; + *dst_col = block ^ ((block ^ ((data & 0x01) ? + fg : *(dst_col + bo))) & dst_mask); + + dst_col += LCD_FBWIDTH; + UPDATE_SRC; + } + while (dst_col < dst_end); + } + else { - src_col += stride; - data = *src_col | 0x100; + bg = bg_pattern; + do + { + unsigned block = *dst_col; + *dst_col = block ^ ((block ^ ((data & 0x01) ? + fg : bg)) & dst_mask); + + dst_col += LCD_FBWIDTH; + UPDATE_SRC; + } + while (dst_col < dst_end); } + break; + } + dst_mask >>= 2; + if (dst_mask == 0) + { + dst++; + dst_mask = 0xC0; } - while (ny < ymax); - nx++; } while (src < src_end); } -- cgit v1.2.3