Optimise the common pixel format conversion RGB24 to RGB32.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3730 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx
index e8cb1a2..b00bc82 100644
--- a/common/rfb/PixelFormat.cxx
+++ b/common/rfb/PixelFormat.cxx
@@ -180,6 +180,44 @@
 }
 
 
+void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
+                                int pixels, ColourMap* cm) const
+{
+  if (is888()) {
+    // Optimised common case
+    rdr::U8 *r, *g, *b;
+
+    r = dst + redShift/8;
+    g = dst + greenShift/8;
+    b = dst + blueShift/8;
+
+    while (pixels--) {
+      *r = *(src++);
+      *g = *(src++);
+      *b = *(src++);
+      r += 4;
+      g += 4;
+      b += 4;
+    }
+  } else {
+    // Generic code
+    Pixel p;
+    rdr::U8 r, g, b;
+
+    while (pixels--) {
+      r = *(src++);
+      g = *(src++);
+      b = *(src++);
+
+      p = pixelFromRGB(r, g, b, cm);
+
+      bufferFromPixel(dst, p);
+      dst += bpp/8;
+    }
+  }
+}
+
+
 void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, Colour* rgb) const
 {
   rdr::U16 r, g, b;
diff --git a/common/rfb/PixelFormat.h b/common/rfb/PixelFormat.h
index 7daa6e7..8adbf91 100644
--- a/common/rfb/PixelFormat.h
+++ b/common/rfb/PixelFormat.h
@@ -46,10 +46,13 @@
     bool isLittleEndian(void) const;
 
     inline Pixel pixelFromBuffer(const rdr::U8* buffer) const;
+    inline void bufferFromPixel(rdr::U8* buffer, Pixel pixel) const;
 
     Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, ColourMap* cm=0) const;
     Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm=0) const;
 
+    void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels, ColourMap* cm=0) const;
+
     void rgbFromPixel(Pixel pix, ColourMap* cm, Colour* rgb) const;
     inline void rgbFromPixel(Pixel pix, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const;
     inline void rgbFromPixel(Pixel pix, ColourMap* cm, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const;
diff --git a/common/rfb/PixelFormat.inl b/common/rfb/PixelFormat.inl
index d5edfa5..90d8e6d 100644
--- a/common/rfb/PixelFormat.inl
+++ b/common/rfb/PixelFormat.inl
@@ -50,6 +50,31 @@
 }
 
 
+inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const
+{
+  if (bigEndian) {
+    switch (bpp) {
+    case 32:
+      *(buffer++) = (p >> 24) & 0xff;
+      *(buffer++) = (p >> 16) & 0xff;
+    case 16:
+      *(buffer++) = (p >>  8) & 0xff;
+    case 8:
+      *(buffer++) = (p >>  0) & 0xff;
+    }
+  } else {
+    buffer[0] = (p >>  0) & 0xff;
+    if (bpp >= 16) {
+      buffer[1] = (p >>  8) & 0xff;
+      if (bpp == 32) {
+        buffer[2] = (p >> 16) & 0xff;
+        buffer[3] = (p >> 24) & 0xff;
+      }
+    }
+  }
+}
+
+
 inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const
 {
   if (trueColour) {
diff --git a/common/rfb/tightDecode.h b/common/rfb/tightDecode.h
index 9cf234d..9679dd7 100644
--- a/common/rfb/tightDecode.h
+++ b/common/rfb/tightDecode.h
@@ -267,10 +267,8 @@
       break;
     }
 
-    for (int dx = 0; dx < r.width(); dx++) {
-      *pixelPtr++ = 
-	myFormat.pixelFromRGB(scanline[dx*3], scanline[dx*3+1], scanline[dx*3+2]);
-    }
+    myFormat.bufferFromRGB((rdr::U8*)pixelPtr, (const rdr::U8*)scanline, r.width());
+    pixelPtr += r.width();
   }
 
   IMAGE_RECT(r, buf);