diff options
author | David 'Digit' Turner <digit@android.com> | 2011-01-16 16:25:10 +0100 |
---|---|---|
committer | David 'Digit' Turner <digit@android.com> | 2011-01-18 20:53:34 +0100 |
commit | 122b335f58e2f52d542854dcddef8723a2b213a4 (patch) | |
tree | f801422c45756dfcdfa9562aefce1a4a7f728c4c | |
parent | 197e5f763ec8a6d514d59647c84ebd9b324eba97 (diff) | |
download | external_qemu-122b335f58e2f52d542854dcddef8723a2b213a4.zip external_qemu-122b335f58e2f52d542854dcddef8723a2b213a4.tar.gz external_qemu-122b335f58e2f52d542854dcddef8723a2b213a4.tar.bz2 |
Sligh speedup for pixel conversion routines with Duff's device.
Change-Id: If832bc5844945f7a2027b2f8d09393586545d8d5
-rw-r--r-- | android/skin/window.c | 59 | ||||
-rw-r--r-- | android/utils/duff.h | 71 | ||||
-rw-r--r-- | hw/goldfish_fb.c | 53 |
3 files changed, 135 insertions, 48 deletions
diff --git a/android/skin/window.c b/android/skin/window.c index 018c184..e32a51f 100644 --- a/android/skin/window.c +++ b/android/skin/window.c @@ -15,6 +15,7 @@ #include "android/charmap.h" #include "android/utils/debug.h" #include "android/utils/system.h" +#include "android/utils/duff.h" #include "android/ui-core-protocol.h" #include <SDL_syswm.h> #include "user-events.h" @@ -313,9 +314,9 @@ lcd_brightness_argb32( unsigned char* pixels, SkinRect* r, int pitch, int br for ( ; h > 0; h-- ) { unsigned* line = (unsigned*) pixels; - int nn; + int nn = 0; - for (nn = 0; nn < w; nn++) { + DUFF4(w, { unsigned c = line[nn]; unsigned ag = (c >> 8) & 0x00ff00ff; unsigned rb = (c) & 0x00ff00ff; @@ -324,7 +325,8 @@ lcd_brightness_argb32( unsigned char* pixels, SkinRect* r, int pitch, int br rb = ((rb*alpha) >> 8) & 0x00ff00ff; line[nn] = (unsigned)(ag | rb); - } + nn++; + }); pixels += pitch; } } @@ -339,9 +341,9 @@ lcd_brightness_argb32( unsigned char* pixels, SkinRect* r, int pitch, int br for ( ; h > 0; h-- ) { unsigned* line = (unsigned*) pixels; - int nn; + int nn = 0; - for (nn = 0; nn < w; nn++) { + DUFF4(w, { unsigned c = line[nn]; unsigned ag = (c >> 8) & 0x00ff00ff; unsigned rb = (c) & 0x00ff00ff; @@ -351,7 +353,8 @@ lcd_brightness_argb32( unsigned char* pixels, SkinRect* r, int pitch, int br rb = ((rb*ialpha + 0x00ff00ff*alpha) >> 8) & 0x00ff00ff; line[nn] = (unsigned)(ag | rb); - } + nn++; + }); pixels += pitch; } } @@ -399,9 +402,11 @@ display_redraw_rect16( ADisplay* disp, SkinRect* rect, SDL_Surface* surface) uint32_t* dst = (uint32_t*)dst_line; uint16_t* src = (uint16_t*)src_line; - for (xx = 0; xx < w; xx++) { + xx = 0; + DUFF4(w, { dst[xx] = rgb565_to_argb32(src[xx]); - } + xx++; + }); src_line += src_pitch; dst_line += dst_pitch; } @@ -415,12 +420,11 @@ display_redraw_rect16( ADisplay* disp, SkinRect* rect, SDL_Surface* surface) uint32_t* dst = (uint32_t*)dst_line; uint8_t* src = src_line; - for (xx = w; xx > 0; xx--) - { + DUFF4(w, { dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]); src -= src_pitch; dst += 1; - } + }); src_line += 2; dst_line += dst_pitch; } @@ -434,12 +438,11 @@ display_redraw_rect16( ADisplay* disp, SkinRect* rect, SDL_Surface* surface) uint16_t* src = (uint16_t*)src_line; uint32_t* dst = (uint32_t*)dst_line; - for (xx = w; xx > 0; xx--) { + DUFF4(w, { dst[0] = rgb565_to_argb32(src[0]); src -= 1; dst += 1; - } - + }); src_line -= src_pitch; dst_line += dst_pitch; } @@ -453,11 +456,11 @@ display_redraw_rect16( ADisplay* disp, SkinRect* rect, SDL_Surface* surface) uint32_t* dst = (uint32_t*)dst_line; uint8_t* src = src_line; - for (xx = w; xx > 0; xx--) { + DUFF4(w, { dst[0] = rgb565_to_argb32(((uint16_t*)src)[0]); dst += 1; src += src_pitch; - } + }); src_line -= 2; dst_line += dst_pitch; } @@ -477,7 +480,7 @@ display_redraw_rect32( ADisplay* disp, SkinRect* rect,SDL_Surface* surface) uint8_t* dst_line = (uint8_t*)surface->pixels + rect->pos.x*4 + rect->pos.y*dst_pitch; int src_pitch = disp->datasize.w*4; uint8_t* src_line = (uint8_t*)disp->data; - int yy, xx; + int yy; switch ( disp->rotation & 3 ) { @@ -488,9 +491,11 @@ display_redraw_rect32( ADisplay* disp, SkinRect* rect,SDL_Surface* surface) uint32_t* src = (uint32_t*)src_line; uint32_t* dst = (uint32_t*)dst_line; - for (xx = 0; xx < w; xx++) { - dst[xx] = xbgr_to_argb32(src[xx]); - } + DUFF4(w, { + dst[0] = xbgr_to_argb32(src[0]); + dst++; + src++; + }); src_line += src_pitch; dst_line += dst_pitch; } @@ -504,12 +509,11 @@ display_redraw_rect32( ADisplay* disp, SkinRect* rect,SDL_Surface* surface) uint32_t* dst = (uint32_t*)dst_line; uint8_t* src = src_line; - for (xx = w; xx > 0; xx--) - { + DUFF4(w, { dst[0] = xbgr_to_argb32(*(uint32_t*)src); src -= src_pitch; dst += 1; - } + }); src_line += 4; dst_line += dst_pitch; } @@ -523,12 +527,11 @@ display_redraw_rect32( ADisplay* disp, SkinRect* rect,SDL_Surface* surface) uint32_t* src = (uint32_t*)src_line; uint32_t* dst = (uint32_t*)dst_line; - for (xx = w; xx > 0; xx--) { + DUFF4(w, { dst[0] = xbgr_to_argb32(src[0]); src -= 1; dst += 1; - } - + }); src_line -= src_pitch; dst_line += dst_pitch; } @@ -542,11 +545,11 @@ display_redraw_rect32( ADisplay* disp, SkinRect* rect,SDL_Surface* surface) uint32_t* dst = (uint32_t*)dst_line; uint8_t* src = src_line; - for (xx = w; xx > 0; xx--) { + DUFF4(w, { dst[0] = xbgr_to_argb32(*(uint32_t*)src); dst += 1; src += src_pitch; - } + }); src_line -= 4; dst_line += dst_pitch; } diff --git a/android/utils/duff.h b/android/utils/duff.h new file mode 100644 index 0000000..a00768c --- /dev/null +++ b/android/utils/duff.h @@ -0,0 +1,71 @@ +/* Copyright (C) 2011 The Android Open Source Project +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +*/ +#ifndef ANDROID_UTILS_DUFF_H +#define ANDROID_UTILS_DUFF_H + +/********************************************************************* + ********************************************************************* + ***** + ***** DUFF'S DEVICES + ***** + *****/ + +#define DUFF1(_count,_stmnt) \ + do { \ + int __n = (_count); \ + do { \ + _stmnt; \ + } while (--__n > 0); \ + } while (0); + +#define DUFF2(_count,_stmnt) \ + ({ \ + int __count = (_count); \ + int __n = (__count +1)/2; \ + switch (__count & 1) { \ + case 0: do { _stmnt; \ + case 1: _stmnt; \ + } while (--__n > 0); \ + } \ + }) + +#define DUFF4(_count,_stmnt) \ + ({ \ + int __count = (_count); \ + int __n = (__count +3)/4; \ + switch (__count & 3) { \ + case 0: do { _stmnt; \ + case 3: _stmnt; \ + case 2: _stmnt; \ + case 1: _stmnt; \ + } while (--__n > 0); \ + } \ + }) + +#define DUFF8(_count,_stmnt) \ + ({ \ + int __count = (_count); \ + int __n = (__count+7)/8; \ + switch (__count & 7) { \ + case 0: do { _stmnt; \ + case 7: _stmnt; \ + case 6: _stmnt; \ + case 5: _stmnt; \ + case 4: _stmnt; \ + case 3: _stmnt; \ + case 2: _stmnt; \ + case 1: _stmnt; \ + } while (--__n > 0); \ + } \ + }) + +#endif /* ANDROID_UTILS_DUFF_H */ diff --git a/hw/goldfish_fb.c b/hw/goldfish_fb.c index 72352fa..d74d797 100644 --- a/hw/goldfish_fb.c +++ b/hw/goldfish_fb.c @@ -12,6 +12,7 @@ #include "qemu_file.h" #include "android/android.h" #include "android/utils/debug.h" +#include "android/utils/duff.h" #include "goldfish_device.h" #include "console.h" @@ -316,26 +317,29 @@ compute_fb_update_rect_linear(FbUpdateState* fbs, const uint16_t* src = (const uint16_t*) src_line; uint16_t* dst = (uint16_t*) dst_line; - for (xx1 = 0; xx1 < width; xx1++) { - if (src[xx1] != dst[xx1]) { + xx1 = 0; + DUFF4(width, { + if (src[xx1] != dst[xx1]) break; - } - } + xx1++; + }); if (xx1 == width) { break; } - for (xx2 = width-1; xx2 > xx1; xx2--) { - if (src[xx2] != dst[xx2]) { + xx2 = width-1; + DUFF4(xx2-xx1, { + if (src[xx2] != dst[xx2]) break; - } - } + xx2--; + }); #if HOST_WORDS_BIGENDIAN /* Convert the guest little-endian pixels into big-endian ones */ int xx = xx1; - for ( ; xx <= xx2; xx++ ) { + DUFF4(xx2-xx1+1,{ unsigned spix = src[xx]; dst[xx] = (uint16_t)((spix << 8) | (spix >> 8)); - } + xx++; + }); #else memcpy( dst+xx1, src+xx1, (xx2-xx1+1)*2 ); #endif @@ -344,25 +348,29 @@ compute_fb_update_rect_linear(FbUpdateState* fbs, case 3: { - for (xx1 = 0; xx1 < width; xx1 += 1) { + xx1 = 0; + DUFF4(width, { int xx = xx1*3; if (src_line[xx+0] != dst_line[xx+0] || src_line[xx+1] != dst_line[xx+1] || src_line[xx+2] != dst_line[xx+2]) { break; } - } + xx1 ++; + }); if (xx1 == width) { break; } - for (xx2 = width-1; xx2 > xx1; xx2--) { + xx2 = width-1; + DUFF4(xx2-xx1,{ int xx = xx2*3; if (src_line[xx+0] != dst_line[xx+0] || src_line[xx+1] != dst_line[xx+1] || src_line[xx+2] != dst_line[xx+2]) { break; } - } + xx2--; + }); memcpy( dst_line+xx1*3, src_line+xx1*3, (xx2-xx1+1)*3 ); break; } @@ -372,28 +380,33 @@ compute_fb_update_rect_linear(FbUpdateState* fbs, const uint32_t* src = (const uint32_t*) src_line; uint32_t* dst = (uint32_t*) dst_line; - for (xx1 = 0; xx1 < width; xx1++) { + xx1 = 0; + DUFF4(width, { if (src[xx1] != dst[xx1]) { break; } - } + xx1++; + }); if (xx1 == width) { break; } - for (xx2 = width-1; xx2 > xx1; xx2--) { + xx2 = width-1; + DUFF4(xx2-xx1,{ if (src[xx2] != dst[xx2]) { break; } - } + xx2--; + }); #if HOST_WORDS_BIGENDIAN /* Convert the guest little-endian pixels into big-endian ones */ int xx = xx1; - for ( ; xx <= xx2; xx++ ) { + DUFF4(xx2-xx1+1,{ uint32_t spix = src[xx]; spix = (spix << 16) | (spix >> 16); spix = ((spix << 8) & 0xff00ff00) | ((spix >> 8) & 0x00ff00ff); dst[xx] = spix; - } + xx++; + }) #else memcpy( dst+xx1, src+xx1, (xx2-xx1+1)*4 ); #endif |