diff options
author | Pierre Ossman <ossman@cendio.se> | 2014-07-08 15:06:25 +0200 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2014-07-09 14:17:53 +0200 |
commit | 2fe68da9e3e7a68102e144464ebcd09f226a446c (patch) | |
tree | cae1f42391cde7f63c7f39c669a7084326a56d69 /common | |
parent | 00bed5c5954a4a809c3a15554a8931ba18879c4e (diff) | |
download | tigervnc-2fe68da9e3e7a68102e144464ebcd09f226a446c.tar.gz tigervnc-2fe68da9e3e7a68102e144464ebcd09f226a446c.zip |
Use lookup tables for pixel upconversion
You have to loop many times when converting e.g. 2 bits to 8,
so have a couple of lookup tables to speed things up. We still
use bit replication to get from 8 bits to 16 bits though.
Diffstat (limited to 'common')
-rw-r--r-- | common/rfb/PixelFormat.cxx | 36 | ||||
-rw-r--r-- | common/rfb/PixelFormat.h | 6 | ||||
-rw-r--r-- | common/rfb/PixelFormat.inl | 66 |
3 files changed, 64 insertions, 44 deletions
diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx index 9e762d9d..366c0a33 100644 --- a/common/rfb/PixelFormat.cxx +++ b/common/rfb/PixelFormat.cxx @@ -32,6 +32,42 @@ using namespace rfb; +rdr::U8 PixelFormat::upconvTable[256*8]; + +class PixelFormat::Init { +public: + Init(); +}; + +PixelFormat::Init PixelFormat::_init; + + +PixelFormat::Init::Init() +{ + int bits; + + // Bit replication is almost perfect, but not quite. And + // a lookup table is still quicker when there is a large + // difference between the source and destination depth. + + for (bits = 1;bits <= 8;bits++) { + int i, maxVal; + rdr::U8 *subTable; + + maxVal = (1 << bits) - 1; + subTable = &upconvTable[(bits-1)*256]; + + for (i = 0;i <= maxVal;i++) + subTable[i] = i * 255 / maxVal; + + // Duplicate the table so that we don't have to care about + // the upper bits when doing a lookup + for (;i < 256;i += maxVal+1) + memcpy(&subTable[i], &subTable[0], maxVal+1); + } +} + + PixelFormat::PixelFormat(int b, int d, bool e, bool t, int rm, int gm, int bm, int rs, int gs, int bs) : bpp(b), depth(d), trueColour(t), bigEndian(e), diff --git a/common/rfb/PixelFormat.h b/common/rfb/PixelFormat.h index c3db8783..db129883 100644 --- a/common/rfb/PixelFormat.h +++ b/common/rfb/PixelFormat.h @@ -105,6 +105,12 @@ namespace rfb { int redBits, greenBits, blueBits; int maxBits, minBits; bool endianMismatch; + + static rdr::U8 upconvTable[256*8]; + + class Init; + friend class Init; + static Init _init; }; } diff --git a/common/rfb/PixelFormat.inl b/common/rfb/PixelFormat.inl index 4bc4a709..f9fb1254 100644 --- a/common/rfb/PixelFormat.inl +++ b/common/rfb/PixelFormat.inl @@ -102,55 +102,33 @@ inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const { - int mb, rb, gb, bb; - - /* Bit replication is much cheaper than multiplication and division */ - - mb = minBits; - rb = redBits; - gb = greenBits; - bb = blueBits; - - *r = (p >> redShift) << (16 - rb); - *g = (p >> greenShift) << (16 - gb); - *b = (p >> blueShift) << (16 - bb); - - while (mb < 16) { - *r = *r | (*r >> rb); - *g = *g | (*g >> gb); - *b = *b | (*b >> bb); - mb <<= 1; - rb <<= 1; - gb <<= 1; - bb <<= 1; - } + rdr::U8 _r, _g, _b; + + _r = p >> redShift; + _g = p >> greenShift; + _b = p >> blueShift; + + _r = upconvTable[(redBits-1)*256 + _r]; + _g = upconvTable[(greenBits-1)*256 + _g]; + _b = upconvTable[(blueBits-1)*256 + _b]; + + *r = _r << 8 | _r; + *g = _g << 8 | _g; + *b = _b << 8 | _b; } inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const { - int mb, rb, gb, bb; - - /* Bit replication is much cheaper than multiplication and division */ - - mb = minBits; - rb = redBits; - gb = greenBits; - bb = blueBits; - - *r = (p >> redShift) << (8 - rb); - *g = (p >> greenShift) << (8 - gb); - *b = (p >> blueShift) << (8 - bb); - - while (mb < 8) { - *r = *r | (*r >> rb); - *g = *g | (*g >> gb); - *b = *b | (*b >> bb); - mb <<= 1; - rb <<= 1; - gb <<= 1; - bb <<= 1; - } + rdr::U8 _r, _g, _b; + + _r = p >> redShift; + _g = p >> greenShift; + _b = p >> blueShift; + + *r = upconvTable[(redBits-1)*256 + _r]; + *g = upconvTable[(greenBits-1)*256 + _g]; + *b = upconvTable[(blueBits-1)*256 + _b]; } |