diff options
author | Tom Wai-Hong Tam <waihong@google.com> | 2011-01-12 09:43:10 +0800 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2011-08-24 10:00:13 -0700 |
commit | 3f1cfde0688018ca3afc60596171b0f049885c5a (patch) | |
tree | 05d7822f81f1941be63bc2dc9c165eac89bb8653 /common/lcd.c | |
parent | b34a32df2631d506fbab8381d1a84fdb3a535d95 (diff) |
Speed up RLE8 bitmap decoding, each frame from 497ms to 87ms.
- Aggregate the same code into one.
- Sepearte critical code into functions, better locality.
- Loop unrolling.
BUG=chromium-os:10499
TEST=build, boot, and "bmp display BMP_ADDR" to render a RLE8 bitmap.
Change-Id: I2ebab4f29ac41048afdfccb6f9d69292f1150c54
Review URL: http://codereview.chromium.org/6189004
Diffstat (limited to 'common/lcd.c')
-rw-r--r-- | common/lcd.c | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/common/lcd.c b/common/lcd.c index 9e18e7c28ed..82995ef3fa5 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -822,6 +822,38 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) #define BMP_RLE8_EOBMP 1 #define BMP_RLE8_DELTA 2 +static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap, + int cnt) +{ + while (cnt > 0) { + *(*fbp)++ = cmap[*bmap++]; + cnt--; + } +} + +static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt) +{ + ushort *fb = *fbp; + int cnt_8copy = cnt >> 3; + cnt -= cnt_8copy << 3; + while (cnt_8copy > 0) { + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + cnt_8copy--; + } + while (cnt > 0) { + *fb++ = c; + cnt--; + } + (*fbp) = fb; +} + /* Do not call this function directly, must be called from * lcd_display_bitmap. */ @@ -830,7 +862,7 @@ static int lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb, { uchar *bmap; ulong width, height; - ushort i, cnt, runlen; + ulong cnt, runlen; int x, y; int decode = 1; @@ -875,12 +907,9 @@ static int lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb, cnt = width - x; else cnt = runlen; - for (i = 0; i < cnt; i++) { - *(ushort *)fb = - cmap[bmap[i]]; - /* move 2-byte */ - fb += 2; - } + draw_unencoded_bitmap( + (ushort **)&fb, + bmap, cmap, cnt); } x += runlen; } @@ -893,15 +922,19 @@ static int lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb, if (y < height) { runlen = bmap[0]; if (x < width) { + /* aggregate the same code */ + while (bmap[0] == 0xff && + bmap[2] != BMP_RLE8_ESCAPE && + bmap[1] == bmap[3]) { + runlen += bmap[2]; + bmap += 2; + } if (x + runlen > width) cnt = width - x; else cnt = runlen; - for (i = 0; i < cnt; i++) { - *(ushort *)fb = cmap[bmap[1]]; - /* move 2-byte */ - fb += 2; - } + draw_encoded_bitmap((ushort **)&fb, + cmap[bmap[1]], cnt); } x += runlen; } |