]> source.dussan.org Git - tigervnc.git/commitdiff
Use lookup tables for pixel upconversion
authorPierre Ossman <ossman@cendio.se>
Tue, 8 Jul 2014 13:06:25 +0000 (15:06 +0200)
committerPierre Ossman <ossman@cendio.se>
Wed, 9 Jul 2014 12:17:53 +0000 (14:17 +0200)
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.

common/rfb/PixelFormat.cxx
common/rfb/PixelFormat.h
common/rfb/PixelFormat.inl

index 9e762d9d3368ff49656f028543e0837a906e4226..366c0a339f036d7792794652ed844c1dd705997b 100644 (file)
 
 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),
index c3db87835b88a5ae49db9bfbb24550cb83d4c905..db129883210c137505576e762ddc999228237342 100644 (file)
@@ -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;
   };
 }
 
index 4bc4a709b087b7ff89c5a904cccde7bcd0098441..f9fb1254034b34e857e385a9791f09bd0b0d51e9 100644 (file)
@@ -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];
 }