Functional version of IrixCLJpegCompressor. This commit includes modifications used to test this class without hardware compressors available via Irix CL.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2376 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/IrixCLJpegCompressor.cxx b/common/rfb/IrixCLJpegCompressor.cxx
index 636c333..3e33a0c 100644
--- a/common/rfb/IrixCLJpegCompressor.cxx
+++ b/common/rfb/IrixCLJpegCompressor.cxx
@@ -4,9 +4,12 @@
 #include <sys/poll.h>
 
 #include <rfb/IrixCLJpegCompressor.h>
+#include <rfb/LogWriter.h>
 
 using namespace rfb;
 
+static LogWriter vlog("IrixCLJpeg");
+
 const int IrixCLJpegCompressor::DEFAULT_QUALITY = 75;
 
 //
@@ -15,13 +18,54 @@
 
 IrixCLJpegCompressor::IrixCLJpegCompressor()
   : m_quality(DEFAULT_QUALITY),
+    m_clHandleValid(false),
+    m_srcBufferSize(0),
+    m_dstBufferSize(0),
+    m_sourceData(0),
     m_compressedData(0),
     m_compressedLength(0)
 {
+  int impactScheme = clQuerySchemeFromName(CL_ALG_VIDEO, "impact");
+  if (impactScheme < 0) {
+    vlog.error("Warning: No compression scheme named \"impact\"");
+  }
+
+  vlog.debug("Trying \"impact\" compression scheme (Octane Compression)");
+  int r = clOpenCompressor(impactScheme, &m_clHandle);
+  if (r == SUCCESS) {
+    vlog.debug("Using \"impact\" compression scheme");
+    m_clHandleValid = true;
+    return;
+  }
+  vlog.debug("Trying Cosmo Compress");
+  r = clOpenCompressor(CL_JPEG_COSMO, &m_clHandle);
+  if (r == SUCCESS) {
+    vlog.debug("Using Cosmo Compress");
+    m_clHandleValid = true;
+    return;
+  }
+
+  // DEBUG: Uncomment to test without hardware compressor.
+  /*
+  vlog.debug("Trying Irix software JPEG compressor (debug mode!)");
+  r = clOpenCompressor(CL_JPEG_SOFTWARE, &m_clHandle);
+  if (r == SUCCESS) {
+    vlog.debug("Using Irix software JPEG compressor (debug mode!)");
+    m_clHandleValid = true;
+    return;
+  }
+  */
+
+  vlog.error("Ho hardware JPEG available via Irix CL library");
 }
 
 IrixCLJpegCompressor::~IrixCLJpegCompressor()
 {
+  if (m_clHandleValid)
+    clCloseCompressor(m_clHandle);
+
+  if (m_sourceData)
+    delete[] m_sourceData;
   if (m_compressedData)
     delete[] m_compressedData;
 }
@@ -47,7 +91,7 @@
 // Perform JPEG compression.
 //
 // FIXME: This function assumes that pixel format is 32-bit XBGR
-//        (depth 24), compatible with IRIX Digital Media libraries.
+//        (depth 24), compatible with IRIX Compression Library.
 //
 
 void
@@ -56,12 +100,59 @@
                                int w, int h, int stride)
 {
   // Discard previous compression results.
-  if (m_compressedData) {
-    delete[] m_compressedData;
-    m_compressedData = 0;
-  }
   m_compressedLength = 0;
 
-  // FIXME: Do something.
+  // A sanity check.
+  if (!m_clHandleValid)
+    return;
+
+  // (Re)allocate the source buffer if necessary.
+  if (w * h > m_srcBufferSize) {
+    if (m_sourceData)
+      delete[] m_sourceData;
+    m_srcBufferSize = w * h;
+    m_sourceData = new rdr::U32[m_srcBufferSize];
+  }
+
+  // Copy source pixels
+  for (int y = 0; y < h; y++) {
+    memcpy(&m_sourceData[y * w], &buf[y * stride], w * sizeof(rdr::U32));
+  }
+
+  // Set image attributes and JPEG quality factor.
+  clSetParam(m_clHandle, CL_FORMAT, CL_FORMAT_XBGR);
+  clSetParam(m_clHandle, CL_IMAGE_WIDTH, w);
+  clSetParam(m_clHandle, CL_IMAGE_HEIGHT, h);
+  clSetParam(m_clHandle, CL_FRAME_BUFFER_SIZE, w * h * 4);
+  clSetParam(m_clHandle, CL_JPEG_QUALITY_FACTOR, m_quality);
+
+  // Determine buffer size required.
+  int newBufferSize = clGetParam(m_clHandle, CL_COMPRESSED_BUFFER_SIZE);
+
+  /* DEBUG:
+  int arr[200];
+  int nn = clQueryParams(m_clHandle, arr, 200);
+  vlog.debug("Params:");
+  for (int ii = 0; ii < nn; ii += 2) {
+    int id = clGetParamID(m_clHandle, (char *)arr[ii]);
+    vlog.debug("  %s = %d", (char*)arr[ii], clGetParam(m_clHandle, id));
+  }
+  */
+
+  // (Re)allocate destination buffer if necessary.
+  if (newBufferSize > m_dstBufferSize) {
+    if (m_compressedData)
+      delete[] m_compressedData;
+    m_dstBufferSize = newBufferSize;
+    m_compressedData = new char[m_dstBufferSize];
+  }
+
+  int newCompressedSize = newBufferSize;
+  int n = clCompress(m_clHandle, 1, m_sourceData,
+                     &newCompressedSize, m_compressedData);
+  if (n != 1)
+    return;
+
+  m_compressedLength = (size_t)newCompressedSize;
 }