Grabbing the RGB components from the BufferedImage one at a time and converting the to a 24bpp RGB color manually is about 25% faster than using BufferedImage.getRGB().

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4821 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/java/com/tigervnc/rdr/InStream.java b/java/com/tigervnc/rdr/InStream.java
index a18ea4e..f998025 100644
--- a/java/com/tigervnc/rdr/InStream.java
+++ b/java/com/tigervnc/rdr/InStream.java
@@ -30,6 +30,7 @@
   // maximum of nItems).
 
   public int check(int itemSize, int nItems, boolean wait) {
+/*
     int available = end - ptr;
     if (itemSize * nItems > available) {
       if (itemSize > available)
@@ -38,6 +39,14 @@
       nItems = available / itemSize;
     }
     return nItems;
+*/
+    if (ptr + itemSize * nItems > end) {
+      if (ptr + itemSize > end)
+        return overrun(itemSize, nItems, wait);
+
+      nItems = (end - ptr) / itemSize;
+    }
+    return nItems;
   }
 
   public int check(int itemSize, int nItems) { return check(itemSize, nItems, true); }
@@ -111,14 +120,17 @@
   // no byte-ordering, we just use big-endian.
 
   public final int readOpaque8()  { return readU8(); }
-  public final int readOpaque16() { return readU16(); }
-  public final int readOpaque32() { return readU32(); }
-  public final int readOpaque24A() { check(3, 1, true); int b0 = b[ptr++];
-                                     int b1 = b[ptr++]; int b2 = b[ptr++];
-                                     return b0 << 24 | b1 << 16 | b2 << 8; }
-  public final int readOpaque24B() { check(3, 1, true); int b0 = b[ptr++];
-                                     int b1 = b[ptr++]; int b2 = b[ptr++];
-                                     return b0 << 16 | b1 << 8 | b2; }
+  public final int readOpaque16() { check(2); int r0 = b[ptr++];
+                                    int r1 = b[ptr++]; return r0 << 8 | r1; }
+  public final int readOpaque32() { check(4); int r0 = b[ptr++]; int r1 = b[ptr++]; 
+                                    int r2 = b[ptr++]; int r3 = b[ptr++]; 
+                                    return r0 << 24 | r1 << 16 | r2 << 8 | r3; }
+  public final int readOpaque24A() { check(3, 1, true); int r0 = b[ptr++];
+                                     int r1 = b[ptr++]; int r2 = b[ptr++];
+                                     return r0 << 24 | r1 << 16 | r2 << 8; }
+  public final int readOpaque24B() { check(3, 1, true); int r0 = b[ptr++];
+                                     int r1 = b[ptr++]; int r2 = b[ptr++];
+                                     return r0 << 16 | r1 << 8 | r2; }
 
   public final int readPixel(int bytesPerPixel, boolean bigEndian) {
     byte[] pix = new byte[4];
@@ -190,4 +202,5 @@
   protected byte[] b;
   protected int ptr;
   protected int end;
+  protected int start;
 }
diff --git a/java/com/tigervnc/rdr/JavaInStream.java b/java/com/tigervnc/rdr/JavaInStream.java
index faa968a..fb6ab8b 100644
--- a/java/com/tigervnc/rdr/JavaInStream.java
+++ b/java/com/tigervnc/rdr/JavaInStream.java
@@ -21,25 +21,37 @@
 //
 
 package com.tigervnc.rdr;
+import java.io.InputStream;
+import java.io.DataInputStream;
 
 public class JavaInStream extends InStream {
 
   static final int defaultBufSize = 8192;
   static final int minBulkSize = 1024;
 
-  public JavaInStream(java.io.InputStream jis_, int bufSize_) {
-    jis = jis_;
+  public JavaInStream(InputStream jis_, int bufSize_) 
+  {
+    jis = new DataInputStream(jis_);
     bufSize = bufSize_;
     b = new byte[bufSize];
-    ptr = end = offset = 0;
+    ptr = end = offset = start = 0;
     timing = false;
     timeWaitedIn100us = 5;
     timedKbits = 0;
   }
 
-  public JavaInStream(java.io.InputStream jis_) { this(jis_, defaultBufSize); }
+  public JavaInStream(InputStream jis_) 
+  {
+    this(jis_, defaultBufSize);
+  }
 
-  public void readBytes(byte[] data, int dataPtr, int length) {
+  public int pos() 
+  {
+    return offset + ptr - start;
+  }
+
+  public void readBytes(byte[] data, int dataPtr, int length) 
+  {
     if (length < minBulkSize) {
       super.readBytes(data, dataPtr, length);
       return;
@@ -61,56 +73,32 @@
     }
   }
 
-  public int pos() { return offset + ptr; }
-
-  public void startTiming() {
-    timing = true;
-
-    // Carry over up to 1s worth of previous rate for smoothing.
-
-    if (timeWaitedIn100us > 10000) {
-      timedKbits = timedKbits * 10000 / timeWaitedIn100us;
-      timeWaitedIn100us = 10000;
-    }
-  }
-
-  public void stopTiming() {
-    timing = false; 
-    if (timeWaitedIn100us < timedKbits/2)
-      timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
-  }
-
-  public long kbitsPerSecond() {
-    return timedKbits * 10000 / timeWaitedIn100us;
-  }
-
-  public long timeWaited() { return timeWaitedIn100us; }
-
   protected int overrun(int itemSize, int nItems, boolean wait) {
     if (itemSize > bufSize)
       throw new Exception("JavaInStream overrun: max itemSize exceeded");
 
     if (end - ptr != 0)
-      System.arraycopy(b, ptr, b, 0, end - ptr);
+      System.arraycopy(b, ptr, b, start, end - ptr);
 
-    offset += ptr;
-    end -= ptr;
-    ptr = 0;
+    offset += ptr - start;
+    end -= ptr - start;
+    ptr = start;
 
-    while (end < itemSize) {
-      int bytes_to_read = bufSize - end;
+    int bytes_to_read;
+    while (end < start + itemSize) {
+      bytes_to_read = start + bufSize - end;
 
       if (!timing) {
         bytes_to_read = Math.min(bytes_to_read, Math.max(itemSize*nItems, 8));
       }
 
       int n = read(b, end, bytes_to_read, wait);
-
+      if (n == 0) return 0;
       end += n;
     }
 
-    if (itemSize * nItems > end)
-      nItems = end / itemSize;
+    if (itemSize * nItems > end - ptr)
+      nItems = (end - ptr) / itemSize;
 
     return nItems;
   }
@@ -122,7 +110,17 @@
 
       int n = -1;
       try {
-        n = jis.read(buf, bufPtr, len);
+        //System.out.println("available: "+jis.available());
+        //int available = jis.available();
+        //if (!wait && (available == 0))
+        //  return 0;
+        //if (available > 0 && available < len) {
+        //  n = jis.read(buf, bufPtr, available);
+        //} else {  
+          n = jis.read(buf, bufPtr, len);
+        //}
+      } catch (java.net.SocketTimeoutException e) {
+        return Math.max(n,0);
       } catch (java.io.IOException e) {
         throw new IOException(e);
       }
@@ -150,9 +148,34 @@
       return n;
 
   }
-  private int read(byte[] buf, int bufPtr, int len) { return read(buf, bufPtr, len, true); }
+  private int read(byte[] buf, int bufPtr, int len) { 
+    return read(buf, bufPtr, len, true); 
+  }
 
-  private java.io.InputStream jis;
+  public void startTiming() {
+    timing = true;
+
+    // Carry over up to 1s worth of previous rate for smoothing.
+
+    if (timeWaitedIn100us > 10000) {
+      timedKbits = timedKbits * 10000 / timeWaitedIn100us;
+      timeWaitedIn100us = 10000;
+    }
+  }
+
+  public void stopTiming() {
+    timing = false; 
+    if (timeWaitedIn100us < timedKbits/2)
+      timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
+  }
+
+  public long kbitsPerSecond() {
+    return timedKbits * 10000 / timeWaitedIn100us;
+  }
+
+  public long timeWaited() { return timeWaitedIn100us; }
+
+  private DataInputStream jis;
   private int offset;
   private int bufSize;
 
diff --git a/java/com/tigervnc/rdr/ZlibInStream.java b/java/com/tigervnc/rdr/ZlibInStream.java
index 46b1c50..44f4828 100644
--- a/java/com/tigervnc/rdr/ZlibInStream.java
+++ b/java/com/tigervnc/rdr/ZlibInStream.java
@@ -138,5 +138,4 @@
   private int offset;
   private com.jcraft.jzlib.ZStream zs;
   private int bytesIn;
-  private int start;
 }
diff --git a/java/com/tigervnc/rfb/PixelBuffer.java b/java/com/tigervnc/rfb/PixelBuffer.java
index f87fead..967d469 100644
--- a/java/com/tigervnc/rfb/PixelBuffer.java
+++ b/java/com/tigervnc/rfb/PixelBuffer.java
@@ -65,6 +65,11 @@
       System.arraycopy(pix, (w * j), data, width_ * (y + j) + x, w);
   }
 
+  public void imageRect(int x, int y, int w, int h, byte[] pix) {
+    for (int j = 0; j < h; j++)
+      System.arraycopy(pix, (w * j), data, width_ * (y + j) + x, w);
+  }
+
   public void copyRect(int x, int y, int w, int h, int srcX, int srcY) {
     int dest = (width_ * y) + x;
     int src = (width_ * srcY) + srcX;
diff --git a/java/com/tigervnc/rfb/TightDecoder.java b/java/com/tigervnc/rfb/TightDecoder.java
index c029d69..3e894c0 100644
--- a/java/com/tigervnc/rfb/TightDecoder.java
+++ b/java/com/tigervnc/rfb/TightDecoder.java
@@ -25,7 +25,6 @@
 import java.awt.image.BufferedImage;
 import java.io.ByteArrayInputStream;
 import javax.imageio.ImageIO;
-import com.sun.image.codec.jpeg.*;
 import java.io.InputStream;
 
 public class TightDecoder extends Decoder {
@@ -261,8 +260,14 @@
       e.printStackTrace();
     }
     int[] buf = reader.getImageBuf(w*h);
-    jpeg.getRGB(0, 0, w, h, buf, 0, w);
-    jpeg = null;
+    int[] pix = new int[3];
+    for (int y=0; y < h; y++) {
+      for (int x=0; x < w; x++) {
+        jpeg.getRaster().getPixel(x, y, pix);
+        buf[y*w+x] = (0xff << 24) | (pix[0] & 0xff) << 16 | (pix[1] & 0xff) << 8 | pix[2];
+      }
+    }
+    jpeg.flush();
     handler.imageRect(r, buf);
   }
 
diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java
index ae03b52..47868d6 100644
--- a/java/com/tigervnc/vncviewer/CConn.java
+++ b/java/com/tigervnc/vncviewer/CConn.java
@@ -181,6 +181,10 @@
     cp.compressLevel = viewer.compressLevel.getValue();
     cp.noJpeg = viewer.noJpeg.getValue();
     cp.qualityLevel = viewer.qualityLevel.getValue();
+    if (viewer.x509ca.getValue() != viewer.x509ca.getDefaultStr())
+      CSecurityTLS.x509ca.setParam(viewer.x509ca.getValue());
+    if (viewer.x509crl.getValue() != viewer.x509crl.getDefaultStr())
+      CSecurityTLS.x509crl.setParam(viewer.x509crl.getValue());
     initMenu();
 
     if (sock != null) {
diff --git a/java/com/tigervnc/vncviewer/DesktopWindow.java b/java/com/tigervnc/vncviewer/DesktopWindow.java
index 087b58f..4b9cd19 100644
--- a/java/com/tigervnc/vncviewer/DesktopWindow.java
+++ b/java/com/tigervnc/vncviewer/DesktopWindow.java
@@ -282,6 +282,17 @@
       showLocalCursor();
   }
 
+  final public void imageRect(int x, int y, int w, int h,
+                                           byte[] pix) {
+    if (overlapsCursor(x, y, w, h)) hideLocalCursor();
+    synchronized (im) {
+      im.imageRect(x, y, w, h, pix);
+    }
+    invalidate(x, y, w, h);
+    if (softCursor == null)
+      showLocalCursor();
+  }
+
   final public void copyRect(int x, int y, int w, int h,
                                           int srcX, int srcY) {
     if (overlapsCursor(x, y, w, h) || overlapsCursor(srcX, srcY, w, h))
diff --git a/java/com/tigervnc/vncviewer/OptionsDialog.java b/java/com/tigervnc/vncviewer/OptionsDialog.java
index 9a463fb..593effd 100644
--- a/java/com/tigervnc/vncviewer/OptionsDialog.java
+++ b/java/com/tigervnc/vncviewer/OptionsDialog.java
@@ -20,6 +20,7 @@
 
 import java.awt.*;
 import java.awt.event.*;
+import java.io.File;
 import javax.swing.*;
 import javax.swing.border.*;
 
diff --git a/java/com/tigervnc/vncviewer/PixelBufferImage.java b/java/com/tigervnc/vncviewer/PixelBufferImage.java
index 648e638..45688f4 100644
--- a/java/com/tigervnc/vncviewer/PixelBufferImage.java
+++ b/java/com/tigervnc/vncviewer/PixelBufferImage.java
@@ -62,6 +62,8 @@
 
     width_ = w;
     height_ = h;
+    //source = new MemoryImageSource(w,h,cm,data,0,w);
+    //source.setAnimated(true);
     image = desktop.createImage(this);
     image.setAccelerationPriority(1);
 
@@ -70,6 +72,9 @@
     for (int i = 0; i < rowsToCopy; i++)
       System.arraycopy(oldData, copyWidth * i,
                        data, width() * i, copyWidth);
+    //source.newPixels(data, cm, 0, w);
+    //source.newPixels(0, 0, w, h, true);
+    //source.setFullBufferUpdates(true);
   }
 
   public PixelFormat getNativePF() {
@@ -103,6 +108,7 @@
   public void put(int x, int y, int w, int h, Graphics g) {
     if (ic != null) {
       ic.setPixels(x, y, w, h, cm, data, width() * y + x, width());
+      //source.newPixels(x, y, w, h, true);
       g.setClip(x, y, w, h);
       ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
     }
@@ -116,6 +122,7 @@
     super.copyRect(x, y, w, h, srcX, srcY);
     if (ic == null) return;
     ic.setPixels(x, y, w, h, cm, data, width() * y + x, width());
+    //source.newPixels(x, y, w, h, true);
     g.setClip(x, y, w, h);
     ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
   }
@@ -171,6 +178,7 @@
   public void requestTopDownLeftRightResend(ImageConsumer c) {}
   public void startProduction(ImageConsumer c) { addConsumer(c); }
 
+  MemoryImageSource source;
   Image image;
   ImageConsumer ic;
 
diff --git a/java/com/tigervnc/vncviewer/VncViewer.java b/java/com/tigervnc/vncviewer/VncViewer.java
index 97b9427..0bf8db0 100644
--- a/java/com/tigervnc/vncviewer/VncViewer.java
+++ b/java/com/tigervnc/vncviewer/VncViewer.java
@@ -258,6 +258,12 @@
                           "Password file for VNC authentication", "");
   AliasParameter passwd
   = new AliasParameter("passwd", "Alias for PasswordFile", passwordFile);
+  StringParameter x509crl
+  = new StringParameter("X509crl",
+                          "Path to X509 CRL certificate file", "");
+  StringParameter x509ca
+  = new StringParameter("X509ca",
+                          "Path to X509 CA certificate file", "");
   BoolParameter autoSelect
   = new BoolParameter("AutoSelect",
                           "Auto select pixel format and encoding", true);