Try to eliminate spurious repaints, improve rendering speed, and simplify viewport constructor.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4887 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java
index 861144c..7c357e6 100644
--- a/java/com/tigervnc/vncviewer/CConn.java
+++ b/java/com/tigervnc/vncviewer/CConn.java
@@ -66,6 +66,9 @@
     setTitle(name+" - TigerVNC");
     setFocusable(false);
     setFocusTraversalKeysEnabled(false);
+    sp = new JScrollPane();
+    sp.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
+    getContentPane().add(sp);
     addWindowFocusListener(new WindowAdapter() {
       public void windowGainedFocus(WindowEvent e) {
         sp.getViewport().getView().requestFocusInWindow();
@@ -113,17 +116,8 @@
     });
   }
 
-  public void addChild(DesktopWindow child) {
-    sp = new JScrollPane(child);
-    child.setBackground(Color.BLACK);
-    child.setOpaque(true);
-    sp.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
-    getContentPane().add(sp);
-  }
-
   public void setChild(DesktopWindow child) {
-    getContentPane().removeAll();
-    addChild(child);
+    sp.getViewport().setView(child);
   }
 
   public void setGeometry(int x, int y, int w, int h, boolean pack) {
@@ -594,11 +588,9 @@
       icon = new ImageIcon(url);
       viewport.setIconImage(icon.getImage());
     }
-    viewport.addChild(desktop);
     reconfigureViewport();
     if ((cp.width > 0) && (cp.height > 0))
       viewport.setVisible(true);
-    desktop.initGraphics();
     desktop.requestFocusInWindow();
   }
 
diff --git a/java/com/tigervnc/vncviewer/DesktopWindow.java b/java/com/tigervnc/vncviewer/DesktopWindow.java
index 3aa0dfd..da3ffd1 100644
--- a/java/com/tigervnc/vncviewer/DesktopWindow.java
+++ b/java/com/tigervnc/vncviewer/DesktopWindow.java
@@ -55,6 +55,8 @@
   public DesktopWindow(int width, int height, PixelFormat serverPF, CConn cc_) {
     cc = cc_;
     setSize(width, height);
+    setBackground(Color.BLACK);
+    setOpaque(true);
     GraphicsEnvironment ge =
       GraphicsEnvironment.getLocalGraphicsEnvironment();
     GraphicsDevice gd = ge.getDefaultScreenDevice();
@@ -64,7 +66,6 @@
     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.");
@@ -94,17 +95,6 @@
     return getHeight();
   }
 
-  // initGraphics() is needed because for some reason you can't call
-  // getGraphics() on a newly-created awt Component.  It is called when the
-  // DesktopWindow has actually been made visible so that getGraphics() ought
-  // to work.
-
-  public void initGraphics() { 
-    synchronized(im) {
-      prepareImage(im.getImage(), scaledWidth, scaledHeight, null);
-    }
-  }
-
   final public PixelFormat getPF() { return im.getPF(); }
 
   public void setViewport(ViewportFrame viewport)
@@ -219,7 +209,11 @@
   // Update the actual window with the changed parts of the framebuffer.
   public void updateWindow()
   {
-    drawInvalidRect();
+    Rect r = damage;
+    if (!r.is_empty()) {
+      paintImmediately(r.tl.x, r.tl.y, r.width(), r.height());
+      damage.clear();
+    }
   }
 
   // resize() is called when the desktop has changed size
@@ -231,41 +225,11 @@
     im.resize(w, h);
   }
 
-  final void drawInvalidRect() {
-    if (!invalidRect) return;
-    int x = invalidLeft;
-    int w = invalidRight - x;
-    int y = invalidTop;
-    int h = invalidBottom - y;
-    invalidRect = false;
-
-    repaint(x, y, w, h);
-  }
-
-  final void invalidate(int x, int y, int w, int h) {
-    if (invalidRect) {
-      if (x < invalidLeft) invalidLeft = x;
-      if (x + w > invalidRight) invalidRight = x + w;
-      if (y < invalidTop) invalidTop = y;
-      if (y + h > invalidBottom) invalidBottom = y + h;
-    } else {
-      invalidLeft = x;
-      invalidRight = x + w;
-      invalidTop = y;
-      invalidBottom = y + h;
-      invalidRect = true;
-    }
-  }
-
-  public void beginRect(int x, int y, int w, int h, int encoding) {
-    invalidRect = false;
-  }
-
   final public void fillRect(int x, int y, int w, int h, int pix)
   {
     if (overlapsCursor(x, y, w, h)) hideLocalCursor();
     im.fillRect(x, y, w, h, pix);
-    invalidate(x, y, w, h);
+    damageRect(new Rect(x, y, x+w, y+h));
     if (softCursor == null)
       showLocalCursor();
   }
@@ -274,7 +238,7 @@
                                            Object pix) {
     if (overlapsCursor(x, y, w, h)) hideLocalCursor();
     im.imageRect(x, y, w, h, pix);
-    invalidate(x, y, w, h);
+    damageRect(new Rect(x, y, x+w, y+h));
     if (softCursor == null)
       showLocalCursor();
   }
@@ -284,7 +248,7 @@
     if (overlapsCursor(x, y, w, h) || overlapsCursor(srcX, srcY, w, h))
       hideLocalCursor();
     im.copyRect(x, y, w, h, srcX, srcY);
-    invalidate(x, y, w, h);
+    damageRect(new Rect(x, y, x+w, y+h));
   }
 
 
@@ -358,14 +322,10 @@
 
   public void paintComponent(Graphics g) {
     Graphics2D g2 = (Graphics2D) g;
-    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
-                        RenderingHints.VALUE_INTERPOLATION_BILINEAR);  
-    g2.setRenderingHint(RenderingHints.KEY_RENDERING, 
-                        RenderingHints.VALUE_RENDER_QUALITY);
-    if (cc.cp.width == scaledWidth && cc.cp.height == scaledHeight) {
-      g2.drawImage(im.getImage(), 0, 0, null);
-    } else {
+    if (cc.cp.width != scaledWidth || cc.cp.height != scaledHeight) {
       g2.drawImage(im.getImage(), 0, 0, scaledWidth, scaledHeight, null);  
+    } else {
+      g2.drawImage(im.getImage(), 0, 0, null);
     }
   }
   
@@ -512,6 +472,14 @@
     }
   }
 
+  void damageRect(Rect r) {
+    if (damage.is_empty()) {
+      damage.setXYWH(r.tl.x, r.tl.y, r.width(), r.height());
+    } else {
+      r = damage.union_boundary(r);
+      damage.setXYWH(r.tl.x, r.tl.y, r.width(), r.height());
+    }
+  }
 
   // run() is executed by the setColourMapEntriesTimerThread - it sleeps for
   // 100ms before actually updating the colourmap.
@@ -542,12 +510,9 @@
   public int scaledWidth = 0, scaledHeight = 0;
   float scaleWidthRatio, scaleHeightRatio;
 
-  // the following are only ever accessed by the RFB thread:
-  boolean invalidRect;
-  int invalidLeft, invalidRight, invalidTop, invalidBottom;
-
   // the following are only ever accessed by the GUI thread:
   int lastX, lastY;
+  Rect damage = new Rect();
 
   static LogWriter vlog = new LogWriter("DesktopWindow");
 }