aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Hinz <bphinz@users.sourceforge.net>2012-04-05 02:08:49 +0000
committerBrian Hinz <bphinz@users.sourceforge.net>2012-04-05 02:08:49 +0000
commit28aa3a810f56b89d90ae32e5e75101db133ff530 (patch)
treef718ef00c7f0c2bbded56225f50eb62e19a1e1c4
parent0878eca6aa47106a24fee53ab3791c677fdfefbe (diff)
downloadtigervnc-28aa3a810f56b89d90ae32e5e75101db133ff530.tar.gz
tigervnc-28aa3a810f56b89d90ae32e5e75101db133ff530.zip
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
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4880 3789f03b-4d11-0410-bbf8-ca57d06f2519
-rw-r--r--java/com/tigervnc/network/SocketDescriptor.java39
-rw-r--r--java/com/tigervnc/rfb/CMsgWriter.java16
-rw-r--r--java/com/tigervnc/rfb/CMsgWriterV3.java12
-rw-r--r--java/com/tigervnc/rfb/TightDecoder.java11
-rw-r--r--java/com/tigervnc/vncviewer/AWTPixelBuffer.java103
-rw-r--r--java/com/tigervnc/vncviewer/BIPixelBuffer.java105
-rw-r--r--java/com/tigervnc/vncviewer/CConn.java67
-rw-r--r--java/com/tigervnc/vncviewer/DesktopWindow.java70
-rw-r--r--java/com/tigervnc/vncviewer/PlatformPixelBuffer.java (renamed from java/com/tigervnc/vncviewer/PixelBufferImage.java)73
9 files changed, 306 insertions, 190 deletions
diff --git a/java/com/tigervnc/network/SocketDescriptor.java b/java/com/tigervnc/network/SocketDescriptor.java
index f9207316..e336a863 100644
--- a/java/com/tigervnc/network/SocketDescriptor.java
+++ b/java/com/tigervnc/network/SocketDescriptor.java
@@ -38,12 +38,14 @@ public class SocketDescriptor extends SocketChannel
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 @@ public class SocketDescriptor extends SocketChannel
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 @@ public class SocketDescriptor extends SocketChannel
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 @@ public class SocketDescriptor extends SocketChannel
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;
}
diff --git a/java/com/tigervnc/rfb/CMsgWriter.java b/java/com/tigervnc/rfb/CMsgWriter.java
index c4f43554..af7d1370 100644
--- a/java/com/tigervnc/rfb/CMsgWriter.java
+++ b/java/com/tigervnc/rfb/CMsgWriter.java
@@ -24,7 +24,7 @@ abstract public class CMsgWriter {
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 @@ abstract public class CMsgWriter {
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 @@ abstract public class CMsgWriter {
// 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 @@ abstract public class CMsgWriter {
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 @@ abstract public class CMsgWriter {
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 @@ abstract public class CMsgWriter {
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 @@ abstract public class CMsgWriter {
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 class CMsgWriter {
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; }
diff --git a/java/com/tigervnc/rfb/CMsgWriterV3.java b/java/com/tigervnc/rfb/CMsgWriterV3.java
index 430c3746..8f01f3c2 100644
--- a/java/com/tigervnc/rfb/CMsgWriterV3.java
+++ b/java/com/tigervnc/rfb/CMsgWriterV3.java
@@ -26,20 +26,20 @@ public class CMsgWriterV3 extends CMsgWriter {
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 @@ public class CMsgWriterV3 extends CMsgWriter {
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 @@ public class CMsgWriterV3 extends CMsgWriter {
endMsg();
}
- public void writeEnableContinuousUpdates(boolean enable,
+ synchronized public void writeEnableContinuousUpdates(boolean enable,
int x, int y, int w, int h)
{
if (!cp.supportsContinuousUpdates)
diff --git a/java/com/tigervnc/rfb/TightDecoder.java b/java/com/tigervnc/rfb/TightDecoder.java
index 74244572..9902097e 100644
--- a/java/com/tigervnc/rfb/TightDecoder.java
+++ b/java/com/tigervnc/rfb/TightDecoder.java
@@ -249,16 +249,7 @@ public class TightDecoder extends Decoder {
// 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();
}
diff --git a/java/com/tigervnc/vncviewer/AWTPixelBuffer.java b/java/com/tigervnc/vncviewer/AWTPixelBuffer.java
new file mode 100644
index 00000000..6b74eee9
--- /dev/null
+++ b/java/com/tigervnc/vncviewer/AWTPixelBuffer.java
@@ -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");
+}
diff --git a/java/com/tigervnc/vncviewer/BIPixelBuffer.java b/java/com/tigervnc/vncviewer/BIPixelBuffer.java
new file mode 100644
index 00000000..cc19c1da
--- /dev/null
+++ b/java/com/tigervnc/vncviewer/BIPixelBuffer.java
@@ -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");
+}
diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java
index 061e6fbe..0f95c691 100644
--- a/java/com/tigervnc/vncviewer/CConn.java
+++ b/java/com/tigervnc/vncviewer/CConn.java
@@ -115,7 +115,6 @@ class ViewportFrame extends JFrame
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 @@ public class CConn extends CConnection
// 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 @@ public class CConn extends CConnection
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 @@ public class CConn extends CConnection
// 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 @@ public class CConn extends CConnection
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 @@ public class CConn extends CConnection
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 @@ public class CConn extends CConnection
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 @@ public class CConn extends CConnection
String str = pf.print();
vlog.info("Using pixel format "+str);
- synchronized (this) {
- writer().writeSetPixelFormat(pf);
- }
+ writer().writeSetPixelFormat(pf);
formatChange = false;
}
@@ -774,10 +759,8 @@ public class CConn extends CConnection
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 class CConn extends CConnection
}
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 @@ public class CConn extends CConnection
}
// 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 @@ public class CConn extends CConnection
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 @@ public class CConn extends CConnection
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 @@ public class CConn extends CConnection
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 @@ public class CConn extends CConnection
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;
}
}
diff --git a/java/com/tigervnc/vncviewer/DesktopWindow.java b/java/com/tigervnc/vncviewer/DesktopWindow.java
index aa019625..362c47a7 100644
--- a/java/com/tigervnc/vncviewer/DesktopWindow.java
+++ b/java/com/tigervnc/vncviewer/DesktopWindow.java
@@ -55,7 +55,21 @@ class DesktopWindow extends JPanel implements
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 @@ class DesktopWindow extends JPanel implements
// 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 @@ class DesktopWindow extends JPanel implements
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 @@ class DesktopWindow extends JPanel implements
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 @@ class DesktopWindow extends JPanel implements
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 @@ class DesktopWindow extends JPanel implements
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 @@ class DesktopWindow extends JPanel implements
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 @@ class DesktopWindow extends JPanel implements
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 @@ class DesktopWindow extends JPanel implements
// - 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 @@ class DesktopWindow extends JPanel implements
CConn cc;
// access to the following must be synchronized:
- PixelBufferImage im;
- Graphics graphics;
+ PlatformPixelBuffer im;
Thread setColourMapEntriesTimerThread;
Cursor cursor;
diff --git a/java/com/tigervnc/vncviewer/PixelBufferImage.java b/java/com/tigervnc/vncviewer/PlatformPixelBuffer.java
index e77f460e..f5844d55 100644
--- a/java/com/tigervnc/vncviewer/PixelBufferImage.java
+++ b/java/com/tigervnc/vncviewer/PlatformPixelBuffer.java
@@ -17,11 +17,6 @@
* 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.*;
@@ -30,9 +25,9 @@ import java.nio.ByteOrder;
import com.tigervnc.rfb.*;
-public class PixelBufferImage extends PixelBuffer
+abstract public class PlatformPixelBuffer extends PixelBuffer
{
- public PixelBufferImage(int w, int h, CConn cc_, DesktopWindow desktop_) {
+ public PlatformPixelBuffer(int w, int h, CConn cc_, DesktopWindow desktop_) {
cc = cc_;
desktop = desktop_;
PixelFormat nativePF = getNativePF();
@@ -45,30 +40,7 @@ public class PixelBufferImage extends PixelBuffer
}
// 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();
- }
+ abstract public void resize(int w, int h);
public PixelFormat getNativePF() {
PixelFormat pf;
@@ -96,34 +68,7 @@ public class PixelBufferImage extends PixelBuffer
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);
- }
+ 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
@@ -147,11 +92,11 @@ public class PixelBufferImage extends PixelBuffer
cm = new IndexColorModel(8, nColours, reds, greens, blues);
}
- private static Toolkit tk = java.awt.Toolkit.getDefaultToolkit();
+ protected static Toolkit tk = Toolkit.getDefaultToolkit();
+
+ abstract public Image getImage();
- Graphics2D graphics;
- BufferedImage image;
- ImageConsumer ic;
+ protected Image image;
int nColours;
byte[] reds;
@@ -160,5 +105,5 @@ public class PixelBufferImage extends PixelBuffer
CConn cc;
DesktopWindow desktop;
- static LogWriter vlog = new LogWriter("PixelBufferImage");
+ static LogWriter vlog = new LogWriter("PlatformPixelBuffer");
}