From efcf278bdf8355448534b72ec52fe48a1e0fa636 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 24 May 2011 18:21:29 -0400 Subject: GRAPHICS: Optimize the convertYUV420ToRGB function a bit more A template is used to avoid a bytesPerPixel check on every pixel and less deferences are done --- graphics/yuv_to_rgb.cpp | 63 +++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 26 deletions(-) (limited to 'graphics/yuv_to_rgb.cpp') diff --git a/graphics/yuv_to_rgb.cpp b/graphics/yuv_to_rgb.cpp index 831736cd75..037ea9a007 100644 --- a/graphics/yuv_to_rgb.cpp +++ b/graphics/yuv_to_rgb.cpp @@ -196,52 +196,63 @@ DECLARE_SINGLETON(Graphics::YUVToRGBManager); namespace Graphics { #define PUT_PIXEL(s, d) \ - L = &lookup->_rgbToPix[(s)]; \ - if (dst->format.bytesPerPixel == 2) \ - *((uint16 *)(d)) = (L[cr_r] | L[crb_g] | L[cb_b]); \ - else \ - *((uint32 *)(d)) = (L[cr_r] | L[crb_g] | L[cb_b]) - -void convertYUV420ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { - // Sanity checks - assert(dst && dst->pixels); - assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); - assert(ySrc && uSrc && vSrc); - assert((yWidth & 1) == 0); - assert((yHeight & 1) == 0); - - const YUVToRGBLookup *lookup = YUVToRGBMan.getLookup(dst->format); - - byte *dstPtr = (byte *)dst->pixels; + L = &rgbToPix[(s)]; \ + *((PixelInt *)(d)) = (L[cr_r] | L[crb_g] | L[cb_b]) +template +void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { int halfHeight = yHeight >> 1; int halfWidth = yWidth >> 1; + // Keep the tables in pointers here to avoid a dereference on each pixel + const int16 *Cr_r_tab = lookup->_colorTab; + const int16 *Cr_g_tab = Cr_r_tab + 256; + const int16 *Cb_g_tab = Cr_g_tab + 256; + const int16 *Cb_b_tab = Cb_g_tab + 256; + const uint32 *rgbToPix = lookup->_rgbToPix; + for (int h = 0; h < halfHeight; h++) { for (int w = 0; w < halfWidth; w++) { - register uint32 *L; + register const uint32 *L; - int16 cr_r = lookup->_colorTab[*vSrc + 0 * 256]; - int16 crb_g = lookup->_colorTab[*vSrc + 1 * 256] + lookup->_colorTab[*uSrc + 2 * 256]; - int16 cb_b = lookup->_colorTab[*uSrc + 3 * 256]; + int16 cr_r = Cr_r_tab[*vSrc]; + int16 crb_g = Cr_g_tab[*vSrc] + Cb_g_tab[*uSrc]; + int16 cb_b = Cb_b_tab[*uSrc]; ++uSrc; ++vSrc; PUT_PIXEL(*ySrc, dstPtr); - PUT_PIXEL(*(ySrc + yPitch), dstPtr + dst->pitch); + PUT_PIXEL(*(ySrc + yPitch), dstPtr + dstPitch); ySrc++; - dstPtr += dst->format.bytesPerPixel; + dstPtr += sizeof(PixelInt); PUT_PIXEL(*ySrc, dstPtr); - PUT_PIXEL(*(ySrc + yPitch), dstPtr + dst->pitch); + PUT_PIXEL(*(ySrc + yPitch), dstPtr + dstPitch); ySrc++; - dstPtr += dst->format.bytesPerPixel; + dstPtr += sizeof(PixelInt); } - dstPtr += dst->pitch; + dstPtr += dstPitch; ySrc += (yPitch << 1) - yWidth; uSrc += uvPitch - halfWidth; vSrc += uvPitch - halfWidth; } } +void convertYUV420ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { + // Sanity checks + assert(dst && dst->pixels); + assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); + assert(ySrc && uSrc && vSrc); + assert((yWidth & 1) == 0); + assert((yHeight & 1) == 0); + + const YUVToRGBLookup *lookup = YUVToRGBMan.getLookup(dst->format); + + // Use a templated function to avoid an if check on every pixel + if (dst->format.bytesPerPixel == 2) + convertYUV420ToRGB((byte *)dst->pixels, dst->pitch, lookup, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); + else + convertYUV420ToRGB((byte *)dst->pixels, dst->pitch, lookup, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); +} + } // End of namespace Graphics -- cgit v1.2.3