summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2009-06-01 21:28:03 +0000
committerJens Arnold <amiconn@rockbox.org>2009-06-01 21:28:03 +0000
commitc1d27d105c3333b5df67c97d88885efa2a49bc9a (patch)
tree143ea17a46fe2a4bc86386ffa381d9c9f8249029
parentaa7d43f7a61998080be228f94aa3d26b5c1dfbc5 (diff)
downloadrockbox-c1d27d105c3333b5df67c97d88885efa2a49bc9a.zip
rockbox-c1d27d105c3333b5df67c97d88885efa2a49bc9a.tar.gz
rockbox-c1d27d105c3333b5df67c97d88885efa2a49bc9a.tar.bz2
rockbox-c1d27d105c3333b5df67c97d88885efa2a49bc9a.tar.xz
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
-rw-r--r--apps/plugins/lib/grey_draw.c3
-rw-r--r--firmware/drivers/lcd-16bit.c3
-rw-r--r--firmware/drivers/lcd-2bit-horz.c148
3 files changed, 124 insertions, 30 deletions
diff --git a/apps/plugins/lib/grey_draw.c b/apps/plugins/lib/grey_draw.c
index c1e6376..3b81694 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 0aa62f6..ef0865f 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 4dc82de..70f7261 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);
}