Revision: 4880
          http://tigervnc.svn.sourceforge.net/tigervnc/?rev=4880&view=rev
Author:   bphinz
Date:     2012-04-05 02:08:49 +0000 (Thu, 05 Apr 2012)
Log Message:
-----------
BufferedImage performance is poor on Microsoft Windows platforms, so fallback 
to the 1.2 implementation if the BI cannot be HW accelerated.  Also streamline 
some of the code by removing synchronized statements and making the method 
calls themselves synchronized.  Modification to the selector implementation to 
make it behave more like a unix selector

Modified Paths:
--------------
    trunk/java/com/tigervnc/network/SocketDescriptor.java
    trunk/java/com/tigervnc/rfb/CMsgWriter.java
    trunk/java/com/tigervnc/rfb/CMsgWriterV3.java
    trunk/java/com/tigervnc/rfb/TightDecoder.java
    trunk/java/com/tigervnc/vncviewer/CConn.java
    trunk/java/com/tigervnc/vncviewer/DesktopWindow.java

Added Paths:
-----------
    trunk/java/com/tigervnc/vncviewer/AWTPixelBuffer.java
    trunk/java/com/tigervnc/vncviewer/BIPixelBuffer.java
    trunk/java/com/tigervnc/vncviewer/PlatformPixelBuffer.java

Removed Paths:
-------------
    trunk/java/com/tigervnc/vncviewer/PixelBufferImage.java

Modified: trunk/java/com/tigervnc/network/SocketDescriptor.java
===================================================================
--- trunk/java/com/tigervnc/network/SocketDescriptor.java       2012-03-27 
13:03:22 UTC (rev 4879)
+++ trunk/java/com/tigervnc/network/SocketDescriptor.java       2012-04-05 
02:08:49 UTC (rev 4880)
@@ -38,12 +38,14 @@
     try {
       channel = SocketChannel.open();
       channel.configureBlocking(false);
-      selector = Selector.open();
+      writeSelector = Selector.open();
+      readSelector = Selector.open();
     } catch (IOException e) {
       throw new Exception(e.toString());
     }
     try {
-      channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE 
);
+      channel.register(writeSelector, SelectionKey.OP_WRITE);
+      channel.register(readSelector, SelectionKey.OP_READ);
     } catch (java.nio.channels.ClosedChannelException e) {
       throw new Exception(e.toString());
     }
@@ -90,6 +92,12 @@
 
   synchronized public int select(int interestOps, Integer timeout) throws 
Exception {
     int n;
+    Selector selector;
+    if ((interestOps & SelectionKey.OP_READ) != 0) {
+      selector = readSelector;
+    } else {
+      selector = writeSelector;
+    }
     selector.selectedKeys().clear();
     try {
       if (timeout == null) {
@@ -105,20 +113,10 @@
           break;
         }
       }
-      if (n == 0)
-        return -1;
     } catch (java.io.IOException e) {
       throw new Exception(e.toString());
     }
-    Set keys = selector.selectedKeys();
-    Iterator iter = keys.iterator();
-    while (iter.hasNext()) {
-      SelectionKey key = (SelectionKey)iter.next();
-      if ((key.readyOps() & interestOps) != 0) {
-        return n;
-      }
-    }
-    return 0;
+    return n;
   }
 
   public int write(ByteBuffer buf) throws Exception {
@@ -198,22 +196,27 @@
     try {
       if (channel != null)
         channel.close();
-      if (selector != null)
-        selector.close();
+      if (readSelector != null)
+        readSelector.close();
+      if (writeSelector != null)
+        writeSelector.close();
       channel = channel_;
       channel.configureBlocking(false);
-      selector = Selector.open();
+      writeSelector = Selector.open();
+      readSelector = Selector.open();
     } catch (java.io.IOException e) {
       throw new Exception(e.toString());
     }
     try {
-      channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE 
);
+      channel.register(writeSelector, SelectionKey.OP_WRITE);
+      channel.register(readSelector, SelectionKey.OP_READ);
     } catch (java.nio.channels.ClosedChannelException e) {
       System.out.println(e.toString());
     }
   }
   
   protected SocketChannel channel;
-  protected Selector selector;
+  protected Selector writeSelector;
+  protected Selector readSelector;
 
 }

Modified: trunk/java/com/tigervnc/rfb/CMsgWriter.java
===================================================================
--- trunk/java/com/tigervnc/rfb/CMsgWriter.java 2012-03-27 13:03:22 UTC (rev 
4879)
+++ trunk/java/com/tigervnc/rfb/CMsgWriter.java 2012-04-05 02:08:49 UTC (rev 
4880)
@@ -24,7 +24,7 @@
 
   abstract public void writeClientInit(boolean shared);
 
-  public void writeSetPixelFormat(PixelFormat pf) 
+  synchronized public void writeSetPixelFormat(PixelFormat pf) 
   {
     startMsg(MsgTypes.msgTypeSetPixelFormat);                                 
     os.pad(3);
@@ -32,7 +32,7 @@
     endMsg();
   }
 
-  public void writeSetEncodings(int nEncodings, int[] encodings) 
+  synchronized public void writeSetEncodings(int nEncodings, int[] encodings) 
   {
     startMsg(MsgTypes.msgTypeSetEncodings);
     os.skip(1);
@@ -45,7 +45,7 @@
   // Ask for encodings based on which decoders are supported.  Assumes higher
   // encoding numbers are more desirable.
 
-  public void writeSetEncodings(int preferredEncoding, boolean useCopyRect) 
+  synchronized public void writeSetEncodings(int preferredEncoding, boolean 
useCopyRect) 
   {
     int nEncodings = 0;
     int[] encodings = new int[Encodings.encodingMax+3];
@@ -113,7 +113,7 @@
     writeSetEncodings(nEncodings, encodings);
   }
 
-  public void writeFramebufferUpdateRequest(Rect r, boolean incremental) 
+  synchronized public void writeFramebufferUpdateRequest(Rect r, boolean 
incremental) 
   {
     startMsg(MsgTypes.msgTypeFramebufferUpdateRequest);
     os.writeU8(incremental?1:0);
@@ -124,7 +124,7 @@
     endMsg();
   }
 
-  public void writeKeyEvent(int key, boolean down) 
+  synchronized public void writeKeyEvent(int key, boolean down) 
   {
     startMsg(MsgTypes.msgTypeKeyEvent);
     os.writeU8(down?1:0);
@@ -133,7 +133,7 @@
     endMsg();
   }
 
-  public void writePointerEvent(Point pos, int buttonMask) 
+  synchronized public void writePointerEvent(Point pos, int buttonMask) 
   {
     Point p = new Point(pos.x,pos.y);
     if (p.x < 0) p.x = 0;
@@ -148,7 +148,7 @@
     endMsg();
   }
 
-  public void writeClientCutText(String str, int len) 
+  synchronized public void writeClientCutText(String str, int len) 
   {
     startMsg(MsgTypes.msgTypeClientCutText);
     os.pad(3);
@@ -165,7 +165,7 @@
   abstract public void startMsg(int type);
   abstract public void endMsg();
 
-  public void setOutStream(OutStream os_) { os = os_; }
+  synchronized public void setOutStream(OutStream os_) { os = os_; }
 
   ConnParams getConnParams() { return cp; }
   OutStream getOutStream() { return os; }

Modified: trunk/java/com/tigervnc/rfb/CMsgWriterV3.java
===================================================================
--- trunk/java/com/tigervnc/rfb/CMsgWriterV3.java       2012-03-27 13:03:22 UTC 
(rev 4879)
+++ trunk/java/com/tigervnc/rfb/CMsgWriterV3.java       2012-04-05 02:08:49 UTC 
(rev 4880)
@@ -26,20 +26,20 @@
 
   public CMsgWriterV3(ConnParams cp_, OutStream os_) { super(cp_, os_); }
 
-  public void writeClientInit(boolean shared) {
+  synchronized public void writeClientInit(boolean shared) {
     os.writeU8(shared?1:0);
     endMsg();
   }
 
-  public void startMsg(int type) {
+  synchronized public void startMsg(int type) {
     os.writeU8(type);
   }
 
-  public void endMsg() {
+  synchronized public void endMsg() {
     os.flush();
   }
 
-  public void writeSetDesktopSize(int width, int height,
+  synchronized public void writeSetDesktopSize(int width, int height,
                                   ScreenSet layout)
        {
          if (!cp.supportsSetDesktopSize)
@@ -67,7 +67,7 @@
          endMsg();
        }
 
-  public void writeFence(int flags, int len, byte[] data)
+  synchronized public void writeFence(int flags, int len, byte[] data)
   {
     if (!cp.supportsFence)
       throw new Exception("Server does not support fences");
@@ -87,7 +87,7 @@
     endMsg();
   }
   
-  public void writeEnableContinuousUpdates(boolean enable,
+  synchronized public void writeEnableContinuousUpdates(boolean enable,
                                            int x, int y, int w, int h)
   {
     if (!cp.supportsContinuousUpdates)

Modified: trunk/java/com/tigervnc/rfb/TightDecoder.java
===================================================================
--- trunk/java/com/tigervnc/rfb/TightDecoder.java       2012-03-27 13:03:22 UTC 
(rev 4879)
+++ trunk/java/com/tigervnc/rfb/TightDecoder.java       2012-04-05 02:08:49 UTC 
(rev 4880)
@@ -249,16 +249,7 @@
 
     // Create an Image object from the JPEG data.
     Image jpeg = tk.createImage(netbuf);
-    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");
-        }
-      }
-    }
+    jpeg.setAccelerationPriority(1);
     handler.imageRect(r, jpeg);
     jpeg.flush();
   }

Added: trunk/java/com/tigervnc/vncviewer/AWTPixelBuffer.java
===================================================================
--- trunk/java/com/tigervnc/vncviewer/AWTPixelBuffer.java                       
        (rev 0)
+++ trunk/java/com/tigervnc/vncviewer/AWTPixelBuffer.java       2012-04-05 
02:08:49 UTC (rev 4880)
@@ -0,0 +1,103 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2011-2012 TigerVNC Team.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.vncviewer;
+
+import java.awt.*;
+import java.awt.image.*;
+
+import com.tigervnc.rfb.*;
+import com.tigervnc.rfb.Exception;
+
+public class AWTPixelBuffer extends PlatformPixelBuffer
+{
+  public AWTPixelBuffer(int w, int h, CConn cc_, DesktopWindow desktop_) {
+    super(w, h, cc_, desktop_);
+  }
+
+  public void setPF(PixelFormat pf) {
+    super.setPF(pf);
+    if (source != null)
+      source.newPixels(data, cm, 0, width_);
+  }
+
+  public void updateColourMap() {
+    cm = new IndexColorModel(8, nColours, reds, greens, blues);
+    if (source != null)
+      source.newPixels(data, cm, 0, width_);
+  }
+  
+  // resize() resizes the image, preserving the image data where possible.
+  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;
+
+    data = new int[width() * height()];
+    for (int i = 0; i < rowsToCopy; i++)
+      System.arraycopy(oldData, copyWidth * i, 
+                       data, width_ * i, copyWidth);
+
+    source = new MemoryImageSource(w, h, cm, data, 0, w);
+    source.setAnimated(true);
+    source.setFullBufferUpdates(false);
+    image = desktop.createImage(source);
+    source.newPixels(data, cm, 0, width_);
+  }
+
+  public void fillRect(int x, int y, int w, int h, int pix) {
+    super.fillRect(x, y, w, h, pix);
+    source.newPixels(x, y, w, h, true);
+  }
+
+  public void imageRect(int x, int y, int w, int h, Object pix) {
+    if (pix instanceof Image) {
+      PixelGrabber pg = 
+        new PixelGrabber((Image)pix, 0, 0, w, h, data, (width_ * y) + x, 
width_);
+      try {
+        pg.grabPixels(0);
+      } catch (InterruptedException e) {
+        vlog.error("Tight Decoding: Wrong JPEG data recieved");
+      }
+    } else {
+      for (int j = 0; j < h; j++)
+        System.arraycopy(pix, (w*j), data, width_ * (y + j) + x, w);
+    }
+    source.newPixels(x, y, w, h, true);
+  }
+
+  public void copyRect(int x, int y, int w, int h, int srcX, int srcY) {
+    super.copyRect(x, y, w, h, srcX, srcY);
+    source.newPixels(x, y, w, h, true);
+  }
+
+  public Image getImage() {
+    return (Image)image;
+  }
+
+  Image image;
+  MemoryImageSource source;
+
+  static LogWriter vlog = new LogWriter("AWTPixelBuffer");
+}

Added: trunk/java/com/tigervnc/vncviewer/BIPixelBuffer.java
===================================================================
--- trunk/java/com/tigervnc/vncviewer/BIPixelBuffer.java                        
        (rev 0)
+++ trunk/java/com/tigervnc/vncviewer/BIPixelBuffer.java        2012-04-05 
02:08:49 UTC (rev 4880)
@@ -0,0 +1,105 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2011-2012 TigerVNC Team.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.vncviewer;
+
+import java.awt.*;
+import java.awt.image.*;
+
+import com.tigervnc.rfb.*;
+import com.tigervnc.rfb.Exception;
+
+public class BIPixelBuffer extends PlatformPixelBuffer
+{
+  public BIPixelBuffer(int w, int h, CConn cc_, DesktopWindow desktop_) {
+    super(w, h, cc_, desktop_);
+  }
+
+  // resize() resizes the image, preserving the image data where possible.
+  public void resize(int w, int h) {
+    if (w == width() && h == height()) return;
+
+    width_ = w;
+    height_ = h;
+    GraphicsEnvironment ge =
+      GraphicsEnvironment.getLocalGraphicsEnvironment();
+    GraphicsDevice gd = ge.getDefaultScreenDevice();
+    GraphicsConfiguration gc = gd.getDefaultConfiguration();
+    image = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
+    image.setAccelerationPriority(1);
+    image.createGraphics();
+  }
+
+  public void fillRect(int x, int y, int w, int h, int pix) {
+    Graphics2D graphics = (Graphics2D)image.getGraphics();
+    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;
+    }
+    graphics.dispose();
+  }
+
+  public void imageRect(int x, int y, int w, int h, Object pix) {
+    Graphics2D graphics = (Graphics2D)image.getGraphics();
+    Image img;
+    if (pix instanceof Image) {
+      img = (Image)pix;
+    } else {
+      img = tk.createImage(new MemoryImageSource(w, h, cm, (int[])pix, 0, w));
+      img.setAccelerationPriority(1);
+    }
+    boolean ret = tk.prepareImage(img, -1, -1, null);
+    if (!ret) {
+      while ((tk.checkImage(img, -1, -1, null) & ImageObserver.ALLBITS) == 0) {
+        synchronized (this) {
+          try {
+            this.wait(0, 10000);
+          } catch (InterruptedException e) {
+            throw new Exception("Error decoding JPEG data");
+          }
+        }
+      }
+    } 
+    graphics.drawImage(img, x, y, w, h, null); 
+    graphics.dispose();
+    img.flush();
+  }
+
+  public void copyRect(int x, int y, int w, int h, int srcX, int srcY) {
+    Graphics2D graphics = (Graphics2D)image.getGraphics();
+    graphics.copyArea(srcX, srcY, w, h, x - srcX, y - srcY);
+    graphics.dispose();
+  }
+
+  public Image getImage() {
+    return (Image)image;
+  }
+
+  BufferedImage image;
+
+  static LogWriter vlog = new LogWriter("BIPixelBuffer");
+}

Modified: trunk/java/com/tigervnc/vncviewer/CConn.java
===================================================================
--- trunk/java/com/tigervnc/vncviewer/CConn.java        2012-03-27 13:03:22 UTC 
(rev 4879)
+++ trunk/java/com/tigervnc/vncviewer/CConn.java        2012-04-05 02:08:49 UTC 
(rev 4880)
@@ -115,7 +115,6 @@
 
   public void addChild(DesktopWindow child) {
     sp = new JScrollPane(child);
-    sp.setDoubleBuffered(true);
     child.setBackground(Color.BLACK);
     child.setOpaque(true);
     sp.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
@@ -426,9 +425,7 @@
       // We need fences to make extra update requests and continuous
       // updates "safe". See fence() for the next step.
       if (cp.supportsFence)
-        synchronized(this) {
-          writer().writeFence(fenceTypes.fenceFlagRequest | 
fenceTypes.fenceFlagSyncNext, 0, null);
-        }
+        writer().writeFence(fenceTypes.fenceFlagRequest | 
fenceTypes.fenceFlagSyncNext, 0, null);
 
       if (cp.supportsSetDesktopSize &&
           viewer.desktopSize.getValue() != null &&
@@ -460,9 +457,7 @@
         screen0.dimensions.br.x = width;
         screen0.dimensions.br.y = height;
 
-        synchronized(this) {
-          writer().writeSetDesktopSize(width, height, layout);
-        }
+        writer().writeSetDesktopSize(width, height, layout);
       }
 
       firstUpdate = false;
@@ -537,9 +532,7 @@
       // We handle everything synchronously so we trivially honor these modes
       flags = flags & (fenceTypes.fenceFlagBlockBefore | 
fenceTypes.fenceFlagBlockAfter);
   
-      synchronized(this) {
-        writer().writeFence(flags, len, data);
-      }
+      writer().writeFence(flags, len, data);
       return;
     }
   
@@ -551,9 +544,7 @@
         if (cp.supportsContinuousUpdates) {
           vlog.info("Enabling continuous updates");
           continuousUpdates = true;
-          synchronized(this) {
-            writer().writeEnableContinuousUpdates(true, 0, 0, cp.width, 
cp.height);
-          }
+          writer().writeEnableContinuousUpdates(true, 0, 0, cp.width, 
cp.height);
         }
       }
     } else {
@@ -574,9 +565,7 @@
       return;
 
     if (continuousUpdates)
-      synchronized(this) {
-        writer().writeEnableContinuousUpdates(true, 0, 0, cp.width, cp.height);
-      }
+      writer().writeEnableContinuousUpdates(true, 0, 0, cp.width, cp.height);
 
     if ((cp.width == 0) && (cp.height == 0))
       return;
@@ -749,10 +738,8 @@
   
         pf.write(memStream);
   
-        synchronized(this) {
-          writer().writeFence(fenceTypes.fenceFlagRequest | 
fenceTypes.fenceFlagSyncNext,
-                              memStream.length(), (byte[])memStream.data());
-        }
+        writer().writeFence(fenceTypes.fenceFlagRequest | 
fenceTypes.fenceFlagSyncNext,
+                            memStream.length(), (byte[])memStream.data());
       } else {
         // New requests are sent out at the start of processing the last
         // one, so we cannot switch our internal format right now (doing so
@@ -763,9 +750,7 @@
 
       String str = pf.print();
       vlog.info("Using pixel format "+str);
-      synchronized (this) {
-        writer().writeSetPixelFormat(pf);
-      }
+      writer().writeSetPixelFormat(pf);
 
       formatChange = false;
     }
@@ -774,10 +759,8 @@
 
     if (forceNonincremental || !continuousUpdates) {
       pendingUpdate = true;
-      synchronized (this) {
-        writer().writeFramebufferUpdateRequest(new 
Rect(0,0,cp.width,cp.height),
-                                                   !formatChange);
-      }
+      writer().writeFramebufferUpdateRequest(new Rect(0,0,cp.width,cp.height),
+                                                 !formatChange);
     }
 
     forceNonincremental = false;
@@ -845,9 +828,7 @@
   }
 
   public void refresh() {
-    synchronized (this) {
-      writer().writeFramebufferUpdateRequest(new Rect(0,0,cp.width,cp.height), 
false);
-    }
+    writer().writeFramebufferUpdateRequest(new Rect(0,0,cp.width,cp.height), 
false);
     pendingUpdate = true;
   }
 
@@ -1216,17 +1197,17 @@
   }
 
   // writeClientCutText() is called from the clipboard dialog
-  synchronized public void writeClientCutText(String str, int len) {
+  public void writeClientCutText(String str, int len) {
     if (state() != RFBSTATE_NORMAL) return;
     writer().writeClientCutText(str,len);
   }
 
-  synchronized public void writeKeyEvent(int keysym, boolean down) {
+  public void writeKeyEvent(int keysym, boolean down) {
     if (state() != RFBSTATE_NORMAL) return;
     writer().writeKeyEvent(keysym, down);
   }
 
-  synchronized public void writeKeyEvent(KeyEvent ev) {
+  public void writeKeyEvent(KeyEvent ev) {
     if (ev.getID() != KeyEvent.KEY_PRESSED && !ev.isActionKey())
       return;
 
@@ -1335,9 +1316,7 @@
       break;
     }
 
-    synchronized (this) {
-      writeModifiers(ev.getModifiers() & ~KeyEvent.ALT_MASK & 
~KeyEvent.META_MASK);
-    }
+    writeModifiers(ev.getModifiers() & ~KeyEvent.ALT_MASK & 
~KeyEvent.META_MASK);
 
     if (cp.width != desktop.scaledWidth || 
         cp.height != desktop.scaledHeight) {
@@ -1348,9 +1327,7 @@
       ev.translatePoint(sx - ev.getX(), sy - ev.getY());
     }
     
-    synchronized (this) {
-      writer().writePointerEvent(new Point(ev.getX(),ev.getY()), buttonMask);
-    }
+    writer().writePointerEvent(new Point(ev.getX(),ev.getY()), buttonMask);
 
     if (buttonMask == 0) writeModifiers(0);
   }
@@ -1369,11 +1346,9 @@
     for (int i=0;i<Math.abs(clicks);i++) {
       x = ev.getX();
       y = ev.getY();
-      synchronized(this) {
-        writer().writePointerEvent(new Point(x, y), buttonMask);
-        buttonMask = 0;
-        writer().writePointerEvent(new Point(x, y), buttonMask);
-      }
+      writer().writePointerEvent(new Point(x, y), buttonMask);
+      buttonMask = 0;
+      writer().writePointerEvent(new Point(x, y), buttonMask);
     }
     writeModifiers(0);
 
@@ -1400,9 +1375,7 @@
   private void checkEncodings() {
     if (encodingChange && (writer() != null)) {
       vlog.info("Using "+Encodings.encodingName(currentEncoding)+" encoding");
-      synchronized(this) {
-        writer().writeSetEncodings(currentEncoding, true);
-      }
+      writer().writeSetEncodings(currentEncoding, true);
       encodingChange = false;
     }
   }

Modified: trunk/java/com/tigervnc/vncviewer/DesktopWindow.java
===================================================================
--- trunk/java/com/tigervnc/vncviewer/DesktopWindow.java        2012-03-27 
13:03:22 UTC (rev 4879)
+++ trunk/java/com/tigervnc/vncviewer/DesktopWindow.java        2012-04-05 
02:08:49 UTC (rev 4880)
@@ -55,7 +55,21 @@
   public DesktopWindow(int width, int height, PixelFormat serverPF, CConn cc_) 
{
     cc = cc_;
     setSize(width, height);
-    im = new PixelBufferImage(width, height, cc, this);
+    GraphicsEnvironment ge =
+      GraphicsEnvironment.getLocalGraphicsEnvironment();
+    GraphicsDevice gd = ge.getDefaultScreenDevice();
+    GraphicsConfiguration gc = gd.getDefaultConfiguration();
+    BufferCapabilities bufCaps = gc.getBufferCapabilities();
+    ImageCapabilities imgCaps = gc.getImageCapabilities();
+    if (bufCaps.isPageFlipping() || bufCaps.isMultiBufferAvailable() ||
+        imgCaps.isAccelerated()) {
+      vlog.debug("GraphicsDevice supports HW acceleration.");
+      setDoubleBuffered(false);
+      im = new BIPixelBuffer(width, height, cc, this);
+    } else {
+      vlog.debug("GraphicsDevice does not support HW acceleration.");
+      im = new AWTPixelBuffer(width, height, cc, this);
+    }
 
     cursor = new Cursor();
     cursorBacking = new ManagedPixelBuffer();
@@ -85,17 +99,14 @@
   // DesktopWindow has actually been made visible so that getGraphics() ought
   // to work.
 
-  synchronized public void initGraphics() { 
-    graphics = im.image.getGraphics();
-    prepareImage(im.image, scaledWidth, scaledHeight, this);
+  public void initGraphics() { 
+    synchronized(im) {
+      prepareImage(im.getImage(), scaledWidth, scaledHeight, null);
+    }
   }
 
   final public PixelFormat getPF() { return im.getPF(); }
 
-  synchronized public void setPF(PixelFormat pf) { 
-    im.setPF(pf); 
-  }
-
   public void setViewport(ViewportFrame viewport)
   {
     viewport.setChild(this);
@@ -214,9 +225,7 @@
     int h = cc.cp.height;
     hideLocalCursor();
     setSize(w, h);
-    synchronized (im) { 
-      im.resize(w, h);
-    }
+    im.resize(w, h);
   }
 
   final void drawInvalidRect() {
@@ -227,11 +236,7 @@
     int h = invalidBottom - y;
     invalidRect = false;
 
-    synchronized (im) {
-      graphics.setClip(x, y, w, h);
-      repaint(x, y, w, h);
-      graphics.setClip(0, 0, im.width(), im.height());
-    }
+    repaint(x, y, w, h);
   }
 
   final void invalidate(int x, int y, int w, int h) {
@@ -256,9 +261,7 @@
   final public void fillRect(int x, int y, int w, int h, int pix)
   {
     if (overlapsCursor(x, y, w, h)) hideLocalCursor();
-    synchronized (im) { 
-      im.fillRect(x, y, w, h, pix);
-    }
+    im.fillRect(x, y, w, h, pix);
     invalidate(x, y, w, h);
     if (softCursor == null)
       showLocalCursor();
@@ -267,9 +270,7 @@
   final public void imageRect(int x, int y, int w, int h,
                                            Object pix) {
     if (overlapsCursor(x, y, w, h)) hideLocalCursor();
-    synchronized (im) {
-      im.imageRect(x, y, w, h, pix);
-    }
+    im.imageRect(x, y, w, h, pix);
     invalidate(x, y, w, h);
     if (softCursor == null)
       showLocalCursor();
@@ -279,9 +280,7 @@
                                           int srcX, int srcY) {
     if (overlapsCursor(x, y, w, h) || overlapsCursor(srcX, srcY, w, h))
       hideLocalCursor();
-    synchronized (im) {
-      im.copyRect(x, y, w, h, srcX, srcY);
-    }
+    im.copyRect(x, y, w, h, srcX, srcY);
     invalidate(x, y, w, h);
   }
 
@@ -361,9 +360,9 @@
     g2.setRenderingHint(RenderingHints.KEY_RENDERING, 
                         RenderingHints.VALUE_RENDER_QUALITY);
     if (cc.cp.width == scaledWidth && cc.cp.height == scaledHeight) {
-      g2.drawImage(im.image, 0, 0, null);
+      g2.drawImage(im.getImage(), 0, 0, null);
     } else {
-      g2.drawImage(im.image, 0, 0, scaledWidth, scaledHeight, null);  
+      g2.drawImage(im.getImage(), 0, 0, scaledWidth, scaledHeight, null);  
     }
   }
   
@@ -403,14 +402,12 @@
       // - Render the cursor!
       if (e.getX() != cursorPosX || e.getY() != cursorPosY) {
         hideLocalCursor();
-        synchronized(im) {
-          if (e.getX() >= 0 && e.getX() < im.width() &&
-              e.getY() >= 0 && e.getY() < im.height()) {
-            cursorPosX = e.getX();
-            cursorPosY = e.getY();
-            if (softCursor == null)
-              showLocalCursor();
-          }
+        if (e.getX() >= 0 && e.getX() < im.width() &&
+            e.getY() >= 0 && e.getY() < im.height()) {
+          cursorPosX = e.getX();
+          cursorPosY = e.getY();
+          if (softCursor == null)
+            showLocalCursor();
         }
       }
     }
@@ -527,8 +524,7 @@
   CConn cc;
 
   // access to the following must be synchronized:
-  PixelBufferImage im;
-  Graphics graphics;
+  PlatformPixelBuffer im;
   Thread setColourMapEntriesTimerThread;
 
   Cursor cursor;

Deleted: trunk/java/com/tigervnc/vncviewer/PixelBufferImage.java
===================================================================
--- trunk/java/com/tigervnc/vncviewer/PixelBufferImage.java     2012-03-27 
13:03:22 UTC (rev 4879)
+++ trunk/java/com/tigervnc/vncviewer/PixelBufferImage.java     2012-04-05 
02:08:49 UTC (rev 4880)
@@ -1,164 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright (C) 2011-2012 TigerVNC Team.
- * 
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
- * USA.
- */
-
-//
-// PixelBufferImage is an PixelBuffer which also acts as an ImageProducer.
-// Currently it only supports 8-bit colourmapped pixel format.
-//
-
-package com.tigervnc.vncviewer;
-
-import java.awt.*;
-import java.awt.image.*;
-import java.nio.ByteOrder;
-
-import com.tigervnc.rfb.*;
-
-public class PixelBufferImage extends PixelBuffer
-{
-  public PixelBufferImage(int w, int h, CConn cc_, DesktopWindow desktop_) {
-    cc = cc_;
-    desktop = desktop_;
-    PixelFormat nativePF = getNativePF();
-    if (nativePF.depth > cc.serverPF.depth) {
-      setPF(cc.serverPF);
-    } else {
-      setPF(nativePF);
-    }
-    resize(w, h);
-  }
-
-  // resize() resizes the image, preserving the image data where possible.
-  public void resize(int w, int h) {
-    if (w == width() && h == height()) return;
-
-    width_ = w;
-    height_ = h;
-    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);
-    graphics = image.createGraphics();
-  }
-
-  public PixelFormat getNativePF() {
-    PixelFormat pf;
-    cm = tk.getColorModel();
-    if (cm.getColorSpace().getType() == java.awt.color.ColorSpace.TYPE_RGB) {
-      int depth = ((cm.getPixelSize() > 24) ? 24 : cm.getPixelSize());
-      int bpp = (depth > 16 ? 32 : (depth > 8 ? 16 : 8));
-      ByteOrder byteOrder = ByteOrder.nativeOrder();
-      boolean bigEndian = (byteOrder == ByteOrder.BIG_ENDIAN ? true : false);
-      boolean trueColour = (depth > 8 ? true : false);
-      int redShift    = cm.getComponentSize()[0] + cm.getComponentSize()[1];
-      int greenShift  = cm.getComponentSize()[0];
-      int blueShift   = 0;
-      pf = new PixelFormat(bpp, depth, bigEndian, trueColour,
-        (depth > 8 ? 0xff : 0),
-        (depth > 8 ? 0xff : 0),
-        (depth > 8 ? 0xff : 0),
-        (depth > 8 ? redShift : 0),
-        (depth > 8 ? greenShift : 0),
-        (depth > 8 ? blueShift : 0));
-    } else {
-      pf = new PixelFormat(8, 8, false, false, 7, 7, 3, 0, 3, 6);
-    }
-    vlog.debug("Native pixel format is "+pf.print());
-    return pf;
-  }
-
-  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;
-    }
-  }
-
-  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.copyArea(srcX, srcY, w, h, x - srcX, y - srcY);
-  }
-
-  // setColourMapEntries() changes some of the entries in the colourmap.
-  // However these settings won't take effect until updateColourMap() is
-  // called.  This is because getting java to recalculate its internal
-  // translation table and redraw the screen is expensive.
-
-  public void setColourMapEntries(int firstColour, int nColours_,
-                                               int[] rgbs) {
-    nColours = nColours_;
-    reds = new byte[nColours];
-    blues = new byte[nColours];
-    greens = new byte[nColours];
-    for (int i = 0; i < nColours; i++) {
-      reds[firstColour+i] = (byte)(rgbs[i*3]   >> 8);
-      greens[firstColour+i] = (byte)(rgbs[i*3+1] >> 8);
-      blues[firstColour+i] = (byte)(rgbs[i*3+2] >> 8);
-    }
-  }
-
-  public void updateColourMap() {
-    cm = new IndexColorModel(8, nColours, reds, greens, blues);
-  }
-
-  private static Toolkit tk = java.awt.Toolkit.getDefaultToolkit();
-
-  Graphics2D graphics;
-  BufferedImage image;
-  ImageConsumer ic;
-
-  int nColours;
-  byte[] reds;
-  byte[] greens;
-  byte[] blues;
-
-  CConn cc;
-  DesktopWindow desktop;
-  static LogWriter vlog = new LogWriter("PixelBufferImage");
-}

Added: trunk/java/com/tigervnc/vncviewer/PlatformPixelBuffer.java
===================================================================
--- trunk/java/com/tigervnc/vncviewer/PlatformPixelBuffer.java                  
        (rev 0)
+++ trunk/java/com/tigervnc/vncviewer/PlatformPixelBuffer.java  2012-04-05 
02:08:49 UTC (rev 4880)
@@ -0,0 +1,109 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2011-2012 TigerVNC Team.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+package com.tigervnc.vncviewer;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.nio.ByteOrder;
+
+import com.tigervnc.rfb.*;
+
+abstract public class PlatformPixelBuffer extends PixelBuffer
+{
+  public PlatformPixelBuffer(int w, int h, CConn cc_, DesktopWindow desktop_) {
+    cc = cc_;
+    desktop = desktop_;
+    PixelFormat nativePF = getNativePF();
+    if (nativePF.depth > cc.serverPF.depth) {
+      setPF(cc.serverPF);
+    } else {
+      setPF(nativePF);
+    }
+    resize(w, h);
+  }
+
+  // resize() resizes the image, preserving the image data where possible.
+  abstract public void resize(int w, int h);
+
+  public PixelFormat getNativePF() {
+    PixelFormat pf;
+    cm = tk.getColorModel();
+    if (cm.getColorSpace().getType() == java.awt.color.ColorSpace.TYPE_RGB) {
+      int depth = ((cm.getPixelSize() > 24) ? 24 : cm.getPixelSize());
+      int bpp = (depth > 16 ? 32 : (depth > 8 ? 16 : 8));
+      ByteOrder byteOrder = ByteOrder.nativeOrder();
+      boolean bigEndian = (byteOrder == ByteOrder.BIG_ENDIAN ? true : false);
+      boolean trueColour = (depth > 8 ? true : false);
+      int redShift    = cm.getComponentSize()[0] + cm.getComponentSize()[1];
+      int greenShift  = cm.getComponentSize()[0];
+      int blueShift   = 0;
+      pf = new PixelFormat(bpp, depth, bigEndian, trueColour,
+        (depth > 8 ? 0xff : 0),
+        (depth > 8 ? 0xff : 0),
+        (depth > 8 ? 0xff : 0),
+        (depth > 8 ? redShift : 0),
+        (depth > 8 ? greenShift : 0),
+        (depth > 8 ? blueShift : 0));
+    } else {
+      pf = new PixelFormat(8, 8, false, false, 7, 7, 3, 0, 3, 6);
+    }
+    vlog.debug("Native pixel format is "+pf.print());
+    return pf;
+  }
+
+  abstract public void imageRect(int x, int y, int w, int h, Object pix);
+
+  // setColourMapEntries() changes some of the entries in the colourmap.
+  // However these settings won't take effect until updateColourMap() is
+  // called.  This is because getting java to recalculate its internal
+  // translation table and redraw the screen is expensive.
+
+  public void setColourMapEntries(int firstColour, int nColours_,
+                                               int[] rgbs) {
+    nColours = nColours_;
+    reds = new byte[nColours];
+    blues = new byte[nColours];
+    greens = new byte[nColours];
+    for (int i = 0; i < nColours; i++) {
+      reds[firstColour+i] = (byte)(rgbs[i*3]   >> 8);
+      greens[firstColour+i] = (byte)(rgbs[i*3+1] >> 8);
+      blues[firstColour+i] = (byte)(rgbs[i*3+2] >> 8);
+    }
+  }
+
+  public void updateColourMap() {
+    cm = new IndexColorModel(8, nColours, reds, greens, blues);
+  }
+
+  protected static Toolkit tk = Toolkit.getDefaultToolkit();
+
+  abstract public Image getImage();
+
+  protected Image image;
+
+  int nColours;
+  byte[] reds;
+  byte[] greens;
+  byte[] blues;
+
+  CConn cc;
+  DesktopWindow desktop;
+  static LogWriter vlog = new LogWriter("PlatformPixelBuffer");
+}

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Better than sec? Nothing is better than sec when it comes to
monitoring Big Data applications. Try Boundary one-second 
resolution app monitoring today. Free.
http://p.sf.net/sfu/Boundary-dev2dev
_______________________________________________
Tigervnc-commits mailing list
Tigervnc-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tigervnc-commits

Reply via email to