aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorBrian Hinz <bphinz@users.sourceforge.net>2012-03-05 23:57:05 +0000
committerBrian Hinz <bphinz@users.sourceforge.net>2012-03-05 23:57:05 +0000
commit44bc7d23d109cbab01555ddc3933eea65caa5a1f (patch)
tree9e732d4459da433b4a43f42ed8834dc8e31afd49 /java
parentdcfcca49c9cf9dc648f95954f2aab435ac78d090 (diff)
downloadtigervnc-44bc7d23d109cbab01555ddc3933eea65caa5a1f.tar.gz
tigervnc-44bc7d23d109cbab01555ddc3933eea65caa5a1f.zip
Improve performance of Java viewer by using buffered image as drawing surface. Simplified soft cursor construction.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4860 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'java')
-rw-r--r--java/com/tigervnc/rfb/CMsgHandler.java2
-rw-r--r--java/com/tigervnc/rfb/TightDecoder.java26
-rw-r--r--java/com/tigervnc/vncviewer/CConn.java2
-rw-r--r--java/com/tigervnc/vncviewer/DesktopWindow.java33
-rw-r--r--java/com/tigervnc/vncviewer/PixelBufferImage.java101
5 files changed, 71 insertions, 93 deletions
diff --git a/java/com/tigervnc/rfb/CMsgHandler.java b/java/com/tigervnc/rfb/CMsgHandler.java
index 533bfbc2..731362d7 100644
--- a/java/com/tigervnc/rfb/CMsgHandler.java
+++ b/java/com/tigervnc/rfb/CMsgHandler.java
@@ -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();
diff --git a/java/com/tigervnc/rfb/TightDecoder.java b/java/com/tigervnc/rfb/TightDecoder.java
index cfc259e5..74244572 100644
--- a/java/com/tigervnc/rfb/TightDecoder.java
+++ b/java/com/tigervnc/rfb/TightDecoder.java
@@ -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,
diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java
index b20b82ea..e74cad56 100644
--- a/java/com/tigervnc/vncviewer/CConn.java
+++ b/java/com/tigervnc/vncviewer/CConn.java
@@ -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);
}
diff --git a/java/com/tigervnc/vncviewer/DesktopWindow.java b/java/com/tigervnc/vncviewer/DesktopWindow.java
index 814b9d06..aa019625 100644
--- a/java/com/tigervnc/vncviewer/DesktopWindow.java
+++ b/java/com/tigervnc/vncviewer/DesktopWindow.java
@@ -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;
}
diff --git a/java/com/tigervnc/vncviewer/PixelBufferImage.java b/java/com/tigervnc/vncviewer/PixelBufferImage.java
index 0efc3c1d..5f666487 100644
--- a/java/com/tigervnc/vncviewer/PixelBufferImage.java
+++ b/java/com/tigervnc/vncviewer/PixelBufferImage.java
@@ -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;