]> source.dussan.org Git - tigervnc.git/commitdiff
Improve performance of Java viewer by using buffered image as drawing surface. Simpli...
authorBrian Hinz <bphinz@users.sourceforge.net>
Mon, 5 Mar 2012 23:57:05 +0000 (23:57 +0000)
committerBrian Hinz <bphinz@users.sourceforge.net>
Mon, 5 Mar 2012 23:57:05 +0000 (23:57 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4860 3789f03b-4d11-0410-bbf8-ca57d06f2519

java/com/tigervnc/rfb/CMsgHandler.java
java/com/tigervnc/rfb/TightDecoder.java
java/com/tigervnc/vncviewer/CConn.java
java/com/tigervnc/vncviewer/DesktopWindow.java
java/com/tigervnc/vncviewer/PixelBufferImage.java

index 533bfbc2aec037287393d828c2f14e85771f22a7..731362d7a45d7d488c5cfee8ed2d6d38927a024b 100644 (file)
@@ -89,7 +89,7 @@ abstract public class CMsgHandler {
   public void serverCutText(String str, int len) {}
 
   public void fillRect(Rect r, int pix) {}
-  public void imageRect(Rect r, int[] pixels) {}
+  public void imageRect(Rect r, Object pixels) {}
   public void copyRect(Rect r, int srcX, int srcY) {}
 
   abstract public PixelFormat getPreferredPF();
index cfc259e54f47745e67382cf1299d61f4437b7e2d..742445726f22969979bfb6b51c941aa860d602d2 100644 (file)
@@ -23,7 +23,7 @@ import com.tigervnc.rdr.InStream;
 import com.tigervnc.rdr.ZlibInStream;
 import java.util.ArrayList;
 import java.io.InputStream;
-import java.awt.image.PixelGrabber;
+import java.awt.image.*;
 import java.awt.*;
 
 public class TightDecoder extends Decoder {
@@ -249,20 +249,18 @@ public class TightDecoder extends Decoder {
 
     // Create an Image object from the JPEG data.
     Image jpeg = tk.createImage(netbuf);
-        
-    int w = r.width();
-    int h = r.height();
-
-    int[] buf = reader.getImageBuf(w*h);
-    PixelGrabber pg = new PixelGrabber(jpeg, 0, 0, w, h, buf, 0, w);
-         try {
-           pg.grabPixels(0);
-         } catch (InterruptedException e) {
-           System.out.println("Tight Decoding: Wrong JPEG data received.");
-         }
-
+    tk.prepareImage(jpeg, -1, -1, null); 
+    synchronized(this) { 
+      while ((tk.checkImage(jpeg, -1, -1, null) & ImageObserver.ALLBITS) == 0) {
+        try {
+          this.wait(1);
+        } catch (InterruptedException e) {
+          throw new Exception("Error decoding JPEG data");
+        }
+      }
+    }
+    handler.imageRect(r, jpeg);
     jpeg.flush();
-    handler.imageRect(r, buf);
   }
 
   final private void FilterGradient24(byte[] netbuf, int[] buf, int stride, 
index b20b82eaba08debfb03deee3916a7936207e5af6..e74cad565394cd81aaa456dff341325c83634086 100644 (file)
@@ -514,7 +514,7 @@ public class CConn extends CConnection
     desktop.fillRect(r.tl.x, r.tl.y, r.width(), r.height(), p);
   }
 
-  public void imageRect(Rect r, int[] p) {
+  public void imageRect(Rect r, Object p) {
     desktop.imageRect(r.tl.x, r.tl.y, r.width(), r.height(), p);
   }
 
index 814b9d067c2e5293c2d818f5805a22da683f40fc..aa0196255f2bc83604ae7ad7b6f8c322dd56517e 100644 (file)
@@ -86,7 +86,7 @@ class DesktopWindow extends JPanel implements
   // to work.
 
   synchronized public void initGraphics() { 
-    graphics = this.getGraphics();
+    graphics = im.image.getGraphics();
     prepareImage(im.image, scaledWidth, scaledHeight, this);
   }
 
@@ -131,20 +131,16 @@ class DesktopWindow extends JPanel implements
     cursor.data = new int[cursor.width() * cursor.height()];
     cursor.mask = new byte[cursor.maskLen()];
 
-    // set the masked pixels of the cursor transparent by using an extra bit in
-    // the colormap.  We'll OR this into the data based on the values in the mask.
-    if (cursor.getPF().bpp == 8) {
-      cursor.cm = new DirectColorModel(9, 7, (7 << 3), (3 << 6), (1 << 8));
-    }
-
     int maskBytesPerRow = (w + 7) / 8;
     for (int y = 0; y < h; y++) {
       for (int x = 0; x < w; x++) {
         int byte_ = y * maskBytesPerRow + x / 8;
         int bit = 7 - x % 8;
         if ((mask[byte_] & (1 << bit)) > 0) {
-          cursor.data[y * cursor.width() + x] = (cursor.getPF().bpp == 8) ?
-            data[y * w + x] | (1 << 8) : data[y * w + x];
+          cursor.data[y * cursor.width() + x] = (0xff << 24) |
+            (im.cm.getRed(data[y * w + x]) << 16) |
+            (im.cm.getGreen(data[y * w + x]) << 8) |
+            (im.cm.getBlue(data[y * w + x]));
         }
       }
       System.arraycopy(mask, y * maskBytesPerRow, cursor.mask, 
@@ -152,7 +148,7 @@ class DesktopWindow extends JPanel implements
     }
 
     MemoryImageSource bitmap = 
-      new MemoryImageSource(cursor.width(), cursor.height(), cursor.cm,
+      new MemoryImageSource(cursor.width(), cursor.height(), ColorModel.getRGBdefault(),
                             cursor.data, 0, cursor.width());
     int cw = (int)Math.floor((float)cursor.width() * scaleWidthRatio);
     int ch = (int)Math.floor((float)cursor.height() * scaleHeightRatio);
@@ -198,7 +194,6 @@ class DesktopWindow extends JPanel implements
     im.setColourMapEntries(firstColour, nColours, rgbs);
     if (nColours <= 256) {
       im.updateColourMap();
-      im.put(0, 0, im.width(), im.height(), graphics);
     } else {
       if (setColourMapEntriesTimerThread == null) {
         setColourMapEntriesTimerThread = new Thread(this);
@@ -233,7 +228,9 @@ class DesktopWindow extends JPanel implements
     invalidRect = false;
 
     synchronized (im) {
-      im.put(x, y, w, h, graphics);
+      graphics.setClip(x, y, w, h);
+      repaint(x, y, w, h);
+      graphics.setClip(0, 0, im.width(), im.height());
     }
   }
 
@@ -268,7 +265,7 @@ class DesktopWindow extends JPanel implements
   }
 
   final public void imageRect(int x, int y, int w, int h,
-                                           int[] pix) {
+                                           Object pix) {
     if (overlapsCursor(x, y, w, h)) hideLocalCursor();
     synchronized (im) {
       im.imageRect(x, y, w, h, pix);
@@ -283,11 +280,9 @@ class DesktopWindow extends JPanel implements
     if (overlapsCursor(x, y, w, h) || overlapsCursor(srcX, srcY, w, h))
       hideLocalCursor();
     synchronized (im) {
-      im.copyRect(x, y, w, h, srcX, srcY, graphics);
-    }
-    if (!cc.viewer.fastCopyRect.getValue()) {
-      invalidate(x, y, w, h);
+      im.copyRect(x, y, w, h, srcX, srcY);
     }
+    invalidate(x, y, w, h);
   }
 
 
@@ -480,8 +475,6 @@ class DesktopWindow extends JPanel implements
       cursorVisible = false;
       im.imageRect(cursorBackingX, cursorBackingY, cursorBacking.width(),
                    cursorBacking.height(), cursorBacking.data);
-      im.put(cursorBackingX, cursorBackingY, cursorBacking.width(),
-             cursorBacking.height(), graphics);
     }
   }
 
@@ -516,7 +509,6 @@ class DesktopWindow extends JPanel implements
 
       im.maskRect(cursorLeft, cursorTop, cursor.width(), cursor.height(),
                   cursor.data, cursor.mask);
-      im.put(x, y, w, h, graphics);
     }
   }
 
@@ -528,7 +520,6 @@ class DesktopWindow extends JPanel implements
       Thread.sleep(100);
     } catch (InterruptedException e) {}
     im.updateColourMap();
-    im.put(0, 0, im.width(), im.height(), graphics);
     setColourMapEntriesTimerThread = null;
   }
 
index 0efc3c1dca589664160261f2ac6f621e84ed4e74..5f666487f5d9ff1af97bdc0e6a2aba563d2b9bba 100644 (file)
@@ -30,7 +30,7 @@ import java.nio.ByteOrder;
 
 import com.tigervnc.rfb.*;
 
-public class PixelBufferImage extends PixelBuffer implements ImageProducer
+public class PixelBufferImage extends PixelBuffer
 {
   public PixelBufferImage(int w, int h, CConn cc_, DesktopWindow desktop_) {
     cc = cc_;
@@ -48,25 +48,31 @@ public class PixelBufferImage extends PixelBuffer implements ImageProducer
   public void resize(int w, int h) {
     if (w == width() && h == height()) return;
 
-    int rowsToCopy = h < height() ? h : height();
-    int copyWidth = w < width() ? w : width();
-    int[] oldData = data;
-
     width_ = w;
     height_ = h;
-    image = desktop.createImage(this);
+    switch (format.depth) {
+    case  3: 
+      // Fall-through to depth 8
+    case  6: 
+      // Fall-through to depth 8
+    case 8:
+      image = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED);
+      break;
+    default:
+      GraphicsEnvironment ge =
+        GraphicsEnvironment.getLocalGraphicsEnvironment();
+      GraphicsDevice gd = ge.getDefaultScreenDevice();
+      GraphicsConfiguration gc = gd.getDefaultConfiguration();
+      image = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
+      break;
+    }
     image.setAccelerationPriority(1);
-
-    data = new int[width() * height()];
-
-    for (int i = 0; i < rowsToCopy; i++)
-      System.arraycopy(oldData, copyWidth * i,
-                       data, width() * i, copyWidth);
+    graphics = image.createGraphics();
   }
 
   public PixelFormat getNativePF() {
     PixelFormat pf;
-    cm = java.awt.Toolkit.getDefaultToolkit().getColorModel();
+    cm = tk.getColorModel();
     if (cm.getColorSpace().getType() == java.awt.color.ColorSpace.TYPE_RGB) {
       int depth = cm.getPixelSize();
       int bpp = (depth > 16 ? 32 : (depth > 8 ? 16 : 8));
@@ -90,24 +96,33 @@ public class PixelBufferImage extends PixelBuffer implements ImageProducer
     return pf;
   }
 
-  // put() causes the given rectangle to be drawn using the given graphics
-  // context.
-  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());
-      desktop.repaint(x, y, w, h);
+  public void fillRect(int x, int y, int w, int h, int pix) {
+    switch (format.depth) {
+    case 24:
+      graphics.setColor(new Color(pix)); 
+      graphics.fillRect(x, y, w, h); 
+      break;
+    default:
+      Color color = new Color((0xff << 24) | (cm.getRed(pix) << 16) |
+                              (cm.getGreen(pix) << 8) | (cm.getBlue(pix)));
+      graphics.setColor(color); 
+      graphics.fillRect(x, y, w, h); 
+      break;
     }
   }
 
-  // fillRect(), imageRect(), maskRect() are inherited from PixelBuffer.  For
-  // copyRect() we also need to tell the ImageConsumer that the pixels have
-  // changed (this is done in the put() call for the others).
+  public void imageRect(int x, int y, int w, int h, Object pix) {
+    if (pix instanceof java.awt.Image) {
+      graphics.drawImage((Image)pix, x, y, w, h, null); 
+    } else {
+      Image img = tk.createImage(new MemoryImageSource(w, h, cm, (int[])pix, 0, w));
+      graphics.drawImage(img, x, y, w, h, null); 
+      img.flush();
+    }
+  }
 
-  public void copyRect(int x, int y, int w, int h, int srcX, int srcY, Graphics g) {
-    super.copyRect(x, y, w, h, srcX, srcY);
-    if (ic == null) return;
-    ic.setPixels(x, y, w, h, cm, data, width() * y + x, width());
-    desktop.repaint(x, y, w, h);
+  public void copyRect(int x, int y, int w, int h, int srcX, int srcY) {
+    graphics.copyArea(srcX, srcY, w, h, x - srcX, y - srcY);
   }
 
   // setColourMapEntries() changes some of the entries in the colourmap.
@@ -128,40 +143,14 @@ public class PixelBufferImage extends PixelBuffer implements ImageProducer
     }
   }
 
-  // ImageProducer methods
-
   public void updateColourMap() {
     cm = new IndexColorModel(8, nColours, reds, greens, blues);
   }
 
-  public void addConsumer(ImageConsumer c) {
-    if (ic == c) return;
-    
-    vlog.debug("adding consumer "+c);
-    
-    if (ic != null)
-      vlog.error("Only one ImageConsumer allowed - discarding old one");
-    
-    ic = c;
-    ic.setDimensions(width(), height());
-    ic.setHints(ImageConsumer.RANDOMPIXELORDER);
-    // Calling ic.setColorModel(cm) seemed to help in some earlier versions of
-    // the JDK, but it shouldn't be necessary because we pass the ColorModel
-    // with each setPixels() call.
-    ic.setPixels(0, 0, width(), height(), cm, data, 0, width());
-    ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
-  }
-
-  public void removeConsumer(ImageConsumer c) {
-    System.err.println("removeConsumer "+c);
-    if (ic == c) ic = null;
-  }
-
-  public boolean isConsumer(ImageConsumer c) { return ic == c; }
-  public void requestTopDownLeftRightResend(ImageConsumer c) {}
-  public void startProduction(ImageConsumer c) { addConsumer(c); }
+  private static Toolkit tk = java.awt.Toolkit.getDefaultToolkit();
 
-  Image image;
+  Graphics2D graphics;
+  BufferedImage image;
   ImageConsumer ic;
 
   int nColours;