aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2017-01-02 17:00:41 +0100
committerPierre Ossman <ossman@cendio.se>2017-02-10 17:02:13 +0100
commit403ac27d2377df4fed8bf5039125f6d89aaa6955 (patch)
tree00e740d165f0aedff234e50b2303581efe6805d5
parent13548819fa30b58f8d007a367d48934c7f064914 (diff)
downloadtigervnc-403ac27d2377df4fed8bf5039125f6d89aaa6955.tar.gz
tigervnc-403ac27d2377df4fed8bf5039125f6d89aaa6955.zip
Abstract platform rendering to "surfaces"
This will allow us to render more things than just the framebuffer.
-rw-r--r--tests/CMakeLists.txt10
-rw-r--r--tests/fbperf.cxx94
-rw-r--r--vncviewer/CMakeLists.txt8
-rw-r--r--vncviewer/OSXPixelBuffer.cxx114
-rw-r--r--vncviewer/PlatformPixelBuffer.cxx166
-rw-r--r--vncviewer/PlatformPixelBuffer.h29
-rw-r--r--vncviewer/Surface.cxx (renamed from vncviewer/Win32PixelBuffer.h)35
-rw-r--r--vncviewer/Surface.h (renamed from vncviewer/OSXPixelBuffer.h)49
-rw-r--r--vncviewer/Surface_OSX.cxx162
-rw-r--r--vncviewer/Surface_Win32.cxx146
-rw-r--r--vncviewer/Surface_X11.cxx139
-rw-r--r--vncviewer/Viewport.cxx36
-rw-r--r--vncviewer/Viewport.h2
-rw-r--r--vncviewer/Win32PixelBuffer.cxx93
-rw-r--r--vncviewer/X11PixelBuffer.cxx229
-rw-r--r--vncviewer/X11PixelBuffer.h47
16 files changed, 774 insertions, 585 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7c994539..5fbaa11a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -22,14 +22,14 @@ target_link_libraries(hostport rfb)
set(FBPERF_SOURCES
fbperf.cxx
- ../vncviewer/FLTKPixelBuffer.cxx
- ../vncviewer/PlatformPixelBuffer.cxx)
+ ../vncviewer/PlatformPixelBuffer.cxx
+ ../vncviewer/Surface.cxx)
if(WIN32)
- set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/Win32PixelBuffer.cxx)
+ set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/Surface_Win32.cxx)
elseif(APPLE)
- set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/OSXPixelBuffer.cxx)
+ set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/Surface_OSX.cxx)
else()
- set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/X11PixelBuffer.cxx)
+ set(FBPERF_SOURCES ${FBPERF_SOURCES} ../vncviewer/Surface_X11.cxx)
endif()
add_executable(fbperf ${FBPERF_SOURCES})
target_link_libraries(fbperf test_util rfb ${FLTK_LIBRARIES} ${GETTEXT_LIBRARIES})
diff --git a/tests/fbperf.cxx b/tests/fbperf.cxx
index 5c37b0f7..8c71d966 100644
--- a/tests/fbperf.cxx
+++ b/tests/fbperf.cxx
@@ -27,15 +27,6 @@
#include <rfb/util.h>
#include "../vncviewer/PlatformPixelBuffer.h"
-#include "../vncviewer/FLTKPixelBuffer.h"
-
-#if defined(WIN32)
-#include "../vncviewer/Win32PixelBuffer.h"
-#elif defined(__APPLE__)
-#include "../vncviewer/OSXPixelBuffer.h"
-#else
-#include "../vncviewer/X11PixelBuffer.h"
-#endif
#include "util.h"
@@ -70,6 +61,19 @@ protected:
virtual void changefb();
};
+class OverlayTestWindow: public PartialTestWindow {
+public:
+ OverlayTestWindow();
+
+ virtual void start(int width, int height);
+ virtual void stop();
+
+ virtual void draw();
+
+protected:
+ Surface* overlay;
+};
+
TestWindow::TestWindow() :
Fl_Window(0, 0, "Framebuffer Performance Test"),
fb(NULL)
@@ -93,17 +97,7 @@ void TestWindow::start(int width, int height)
frames = 0;
time = 0;
- try {
-#if defined(WIN32)
- fb = new Win32PixelBuffer(w(), h());
-#elif defined(__APPLE__)
- fb = new OSXPixelBuffer(w(), h());
-#else
- fb = new X11PixelBuffer(w(), h());
-#endif
- } catch (rdr::Exception& e) {
- fb = new FLTKPixelBuffer(w(), h());
- }
+ fb = new PlatformPixelBuffer(w(), h());
pixel = 0;
fb->fillRect(fb->getRect(), &pixel);
@@ -207,6 +201,60 @@ void PartialTestWindow::changefb()
fb->fillRect(r, &pixel);
}
+OverlayTestWindow::OverlayTestWindow() :
+ overlay(NULL)
+{
+}
+
+void OverlayTestWindow::start(int width, int height)
+{
+ PartialTestWindow::start(width, height);
+
+ overlay = new Surface(400, 200);
+ overlay->clear(0xff, 0x80, 0x00, 0xcc);
+}
+
+void OverlayTestWindow::stop()
+{
+ PartialTestWindow::stop();
+
+ delete overlay;
+ overlay = NULL;
+}
+
+void OverlayTestWindow::draw()
+{
+ int ox, oy, ow, oh;
+ int X, Y, W, H;
+
+ // Check what actually needs updating
+ fl_clip_box(0, 0, w(), h(), X, Y, W, H);
+ if ((W == 0) || (H == 0))
+ return;
+
+ PartialTestWindow::draw();
+
+ // We might get a redraw before we are fully ready
+ if (!overlay)
+ return;
+
+ // Simplify the clip region to a simple rectangle in order to
+ // properly draw all the layers even if they only partially overlap
+ fl_push_no_clip();
+ fl_push_clip(X, Y, W, H);
+
+ ox = (w() - overlay->width()) / 2;
+ oy = h() / 4 - overlay->height() / 2;
+ ow = overlay->width();
+ oh = overlay->height();
+ fl_clip_box(ox, oy, ow, oh, X, Y, W, H);
+ if ((W != 0) && (H != 0))
+ overlay->draw(X - ox, Y - oy, X, Y, W, H);
+
+ fl_pop_clip();
+ fl_pop_clip();
+}
+
static void dosubtest(TestWindow* win, int width, int height,
unsigned long long* pixels,
unsigned long long* frames,
@@ -311,5 +359,11 @@ int main(int argc, char** argv)
delete win;
fprintf(stderr, "\n");
+ fprintf(stderr, "Partial window update with overlay:\n\n");
+ win = new OverlayTestWindow();
+ dotest(win);
+ delete win;
+ fprintf(stderr, "\n");
+
return 0;
}
diff --git a/vncviewer/CMakeLists.txt b/vncviewer/CMakeLists.txt
index f11bae3f..d6a1b585 100644
--- a/vncviewer/CMakeLists.txt
+++ b/vncviewer/CMakeLists.txt
@@ -6,9 +6,9 @@ set(VNCVIEWER_SOURCES
menukey.cxx
CConn.cxx
DesktopWindow.cxx
- FLTKPixelBuffer.cxx
UserDialog.cxx
ServerDialog.cxx
+ Surface.cxx
OptionsDialog.cxx
PlatformPixelBuffer.cxx
Viewport.cxx
@@ -33,11 +33,11 @@ elseif(APPLE)
endif()
if(WIN32)
- set(VNCVIEWER_SOURCES ${VNCVIEWER_SOURCES} Win32PixelBuffer.cxx)
+ set(VNCVIEWER_SOURCES ${VNCVIEWER_SOURCES} Surface_Win32.cxx)
elseif(APPLE)
- set(VNCVIEWER_SOURCES ${VNCVIEWER_SOURCES} OSXPixelBuffer.cxx)
+ set(VNCVIEWER_SOURCES ${VNCVIEWER_SOURCES} Surface_OSX.cxx)
else()
- set(VNCVIEWER_SOURCES ${VNCVIEWER_SOURCES} X11PixelBuffer.cxx)
+ set(VNCVIEWER_SOURCES ${VNCVIEWER_SOURCES} Surface_X11.cxx)
endif()
if(WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
diff --git a/vncviewer/OSXPixelBuffer.cxx b/vncviewer/OSXPixelBuffer.cxx
deleted file mode 100644
index 5c9611cd..00000000
--- a/vncviewer/OSXPixelBuffer.cxx
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Copyright 2011-2014 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ApplicationServices/ApplicationServices.h>
-
-#include <FL/Fl_Window.H>
-#include <FL/x.H>
-
-#include <rfb/LogWriter.h>
-#include <rfb/Exception.h>
-
-#include "i18n.h"
-#include "OSXPixelBuffer.h"
-
-using namespace rfb;
-
-static rfb::LogWriter vlog("OSXPixelBuffer");
-
-OSXPixelBuffer::OSXPixelBuffer(int width, int height) :
- PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
- 255, 255, 255, 16, 8, 0),
- width, height, NULL, width),
- image(NULL)
-{
- CGColorSpaceRef lut;
- CGDataProviderRef provider;
-
- data = new rdr::U8[width * height * format.bpp/8];
- if (data == NULL)
- throw rfb::Exception(_("Not enough memory for framebuffer"));
-
- lut = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
- if (!lut) {
- vlog.error(_("Could not get screen color space. Using slower fallback."));
- lut = CGColorSpaceCreateDeviceRGB();
- if (!lut)
- throw rfb::Exception("CGColorSpaceCreateDeviceRGB");
- }
-
- provider = CGDataProviderCreateWithData(NULL, data,
- width * height * 4, NULL);
- if (!provider)
- throw rfb::Exception("CGDataProviderCreateWithData");
-
- image = CGImageCreate(width, height, 8, 32, width * 4, lut,
- kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
- provider, NULL, false, kCGRenderingIntentDefault);
- CGColorSpaceRelease(lut);
- CGDataProviderRelease(provider);
- if (!image)
- throw rfb::Exception("CGImageCreate");
-}
-
-
-OSXPixelBuffer::~OSXPixelBuffer()
-{
- CGImageRelease(image);
- delete [] data;
-}
-
-
-void OSXPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
-{
- CGContextRef gc;
- CGRect rect;
-
- gc = fl_gc;
-
- CGContextSaveGState(gc);
-
- // macOS Coordinates are from bottom left, not top left
- src_y = height() - (src_y + h);
- y = Fl_Window::current()->h() - (y + h);
-
- // Reset the transformation matrix back to the default identity
- // matrix as otherwise we get a massive performance hit
- CGContextConcatCTM(gc, CGAffineTransformInvert(CGContextGetCTM(gc)));
-
- // We have to use clipping to partially display an image
- rect.origin.x = x;
- rect.origin.y = y;
- rect.size.width = w;
- rect.size.height = h;
-
- CGContextClipToRect(gc, rect);
-
- rect.origin.x = x - src_x;
- rect.origin.y = y - src_y;
- rect.size.width = width();
- rect.size.height = height();
-
- CGContextDrawImage(gc, rect, image);
-
- CGContextRestoreGState(gc);
-}
diff --git a/vncviewer/PlatformPixelBuffer.cxx b/vncviewer/PlatformPixelBuffer.cxx
index 522bad3f..4802ba46 100644
--- a/vncviewer/PlatformPixelBuffer.cxx
+++ b/vncviewer/PlatformPixelBuffer.cxx
@@ -1,4 +1,4 @@
-/* Copyright 2011-2014 Pierre Ossman for Cendio AB
+/* Copyright 2011-2016 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,13 +16,70 @@
* USA.
*/
+#include <assert.h>
+
+#if !defined(WIN32) && !defined(__APPLE__)
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
+#include <FL/Fl.H>
+#include <FL/x.H>
+
+#include <rfb/LogWriter.h>
+#include <rdr/Exception.h>
+
#include "PlatformPixelBuffer.h"
-PlatformPixelBuffer::PlatformPixelBuffer(const rfb::PixelFormat& pf,
- int width, int height,
- rdr::U8* data, int stride) :
- FullFramePixelBuffer(pf, width, height, data, stride)
+static rfb::LogWriter vlog("PlatformPixelBuffer");
+
+PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
+ FullFramePixelBuffer(rfb::PixelFormat(32, 24, false, true,
+ 255, 255, 255, 16, 8, 0),
+ width, height, 0, stride),
+ Surface(width, height)
+#if !defined(WIN32) && !defined(__APPLE__)
+ , shminfo(NULL), xim(NULL)
+#endif
{
+#if !defined(WIN32) && !defined(__APPLE__)
+ if (!setupShm()) {
+ xim = XCreateImage(fl_display, CopyFromParent, 32,
+ ZPixmap, 0, 0, width, height, 32, 0);
+ if (!xim)
+ throw rdr::Exception("XCreateImage");
+
+ xim->data = (char*)malloc(xim->bytes_per_line * xim->height);
+ if (!xim->data)
+ throw rdr::Exception("malloc");
+
+ vlog.debug("Using standard XImage");
+ }
+
+ data = (rdr::U8*)xim->data;
+ stride = xim->bytes_per_line / (getPF().bpp/8);
+#else
+ FullFramePixelBuffer::data = (rdr::U8*)Surface::data;
+ stride = width;
+#endif
+}
+
+PlatformPixelBuffer::~PlatformPixelBuffer()
+{
+#if !defined(WIN32) && !defined(__APPLE__)
+ if (shminfo) {
+ vlog.debug("Freeing shared memory XImage");
+ shmdt(shminfo->shmaddr);
+ shmctl(shminfo->shmid, IPC_RMID, 0);
+ delete shminfo;
+ shminfo = NULL;
+ }
+
+ // XDestroyImage() will free(xim->data) if appropriate
+ if (xim)
+ XDestroyImage(xim);
+ xim = NULL;
+#endif
}
void PlatformPixelBuffer::commitBufferRW(const rfb::Rect& r)
@@ -42,5 +99,104 @@ rfb::Rect PlatformPixelBuffer::getDamage(void)
damage.clear();
mutex.unlock();
+#if !defined(WIN32) && !defined(__APPLE__)
+ GC gc;
+
+ gc = XCreateGC(fl_display, pixmap, 0, NULL);
+ if (shminfo) {
+ XShmPutImage(fl_display, pixmap, gc, xim,
+ r.tl.x, r.tl.y, r.tl.x, r.tl.y,
+ r.width(), r.height(), False);
+ // Need to make sure the X server has finished reading the
+ // shared memory before we return
+ XSync(fl_display, False);
+ } else {
+ XPutImage(fl_display, pixmap, gc, xim,
+ r.tl.x, r.tl.y, r.tl.x, r.tl.y, r.width(), r.height());
+ }
+ XFreeGC(fl_display, gc);
+#endif
+
return r;
}
+
+#if !defined(WIN32) && !defined(__APPLE__)
+
+static bool caughtError;
+
+static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error)
+{
+ caughtError = true;
+ return 0;
+}
+
+bool PlatformPixelBuffer::setupShm()
+{
+ int major, minor;
+ Bool pixmaps;
+ XErrorHandler old_handler;
+ const char *display_name = XDisplayName (NULL);
+
+ /* Don't use MIT-SHM on remote displays */
+ if (*display_name && *display_name != ':')
+ return false;
+
+ if (!XShmQueryVersion(fl_display, &major, &minor, &pixmaps))
+ return false;
+
+ shminfo = new XShmSegmentInfo;
+
+ xim = XShmCreateImage(fl_display, CopyFromParent, 32,
+ ZPixmap, 0, shminfo, width(), height());
+ if (!xim)
+ goto free_shminfo;
+
+ shminfo->shmid = shmget(IPC_PRIVATE,
+ xim->bytes_per_line * xim->height,
+ IPC_CREAT|0777);
+ if (shminfo->shmid == -1)
+ goto free_xim;
+
+ shminfo->shmaddr = xim->data = (char*)shmat(shminfo->shmid, 0, 0);
+ shmctl(shminfo->shmid, IPC_RMID, 0); // to avoid memory leakage
+ if (shminfo->shmaddr == (char *)-1)
+ goto free_xim;
+
+ shminfo->readOnly = True;
+
+ // This is the only way we can detect that shared memory won't work
+ // (e.g. because we're accessing a remote X11 server)
+ caughtError = false;
+ old_handler = XSetErrorHandler(XShmAttachErrorHandler);
+
+ if (!XShmAttach(fl_display, shminfo)) {
+ XSetErrorHandler(old_handler);
+ goto free_shmaddr;
+ }
+
+ XSync(fl_display, False);
+
+ XSetErrorHandler(old_handler);
+
+ if (caughtError)
+ goto free_shmaddr;
+
+ vlog.debug("Using shared memory XImage");
+
+ return true;
+
+free_shmaddr:
+ shmdt(shminfo->shmaddr);
+
+free_xim:
+ XDestroyImage(xim);
+ xim = NULL;
+
+free_shminfo:
+ delete shminfo;
+ shminfo = NULL;
+
+ return 0;
+}
+
+#endif
diff --git a/vncviewer/PlatformPixelBuffer.h b/vncviewer/PlatformPixelBuffer.h
index 795273a9..26ae7ca3 100644
--- a/vncviewer/PlatformPixelBuffer.h
+++ b/vncviewer/PlatformPixelBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright 2011-2014 Pierre Ossman for Cendio AB
+/* Copyright 2011-2016 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,24 +19,43 @@
#ifndef __PLATFORMPIXELBUFFER_H__
#define __PLATFORMPIXELBUFFER_H__
+#if !defined(WIN32) && !defined(__APPLE__)
+#include <X11/extensions/XShm.h>
+#endif
+
+#include <list>
+
#include <os/Mutex.h>
#include <rfb/PixelBuffer.h>
#include <rfb/Region.h>
-class PlatformPixelBuffer: public rfb::FullFramePixelBuffer {
+#include "Surface.h"
+
+class PlatformPixelBuffer: public rfb::FullFramePixelBuffer, public Surface {
public:
- PlatformPixelBuffer(const rfb::PixelFormat& pf, int width, int height,
- rdr::U8* data, int stride);
+ PlatformPixelBuffer(int width, int height);
+ ~PlatformPixelBuffer();
virtual void commitBufferRW(const rfb::Rect& r);
- virtual void draw(int src_x, int src_y, int x, int y, int w, int h) = 0;
rfb::Rect getDamage(void);
+ using rfb::FullFramePixelBuffer::width;
+ using rfb::FullFramePixelBuffer::height;
+
protected:
os::Mutex mutex;
rfb::Region damage;
+
+#if !defined(WIN32) && !defined(__APPLE__)
+protected:
+ bool setupShm();
+
+protected:
+ XShmSegmentInfo *shminfo;
+ XImage *xim;
+#endif
};
#endif
diff --git a/vncviewer/Win32PixelBuffer.h b/vncviewer/Surface.cxx
index 728e5948..fbd41437 100644
--- a/vncviewer/Win32PixelBuffer.h
+++ b/vncviewer/Surface.cxx
@@ -1,4 +1,4 @@
-/* Copyright 2011-2014 Pierre Ossman for Cendio AB
+/* Copyright 2016 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,23 +16,24 @@
* USA.
*/
-#ifndef __WIN32PIXELBUFFER_H__
-#define __WIN32PIXELBUFFER_H__
+#include <FL/Fl_RGB_Image.H>
-#include <windows.h>
+#include "Surface.h"
-#include "PlatformPixelBuffer.h"
+Surface::Surface(int width, int height) :
+ w(width), h(height)
+{
+ alloc();
+}
-class Win32PixelBuffer: public PlatformPixelBuffer {
-public:
- Win32PixelBuffer(int width, int height);
- ~Win32PixelBuffer();
+Surface::Surface(const Fl_RGB_Image* image) :
+ w(image->w()), h(image->h())
+{
+ alloc();
+ update(image);
+}
- virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
-
-protected:
- HBITMAP bitmap;
-};
-
-
-#endif
+Surface::~Surface()
+{
+ dealloc();
+}
diff --git a/vncviewer/OSXPixelBuffer.h b/vncviewer/Surface.h
index 958b1eae..02917e31 100644
--- a/vncviewer/OSXPixelBuffer.h
+++ b/vncviewer/Surface.h
@@ -1,4 +1,4 @@
-/* Copyright 2011-2014 Pierre Ossman for Cendio AB
+/* Copyright 2016 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,24 +16,53 @@
* USA.
*/
-#ifndef __OSXPIXELBUFFER_H__
-#define __OSXPIXELBUFFER_H__
-
-#include "PlatformPixelBuffer.h"
+#ifndef __SURFACE_H__
+#define __SURFACE_H__
+#if defined(WIN32)
+#include <windows.h>
+#elif defined(__APPLE__)
// Apple headers conflict with FLTK, so redefine types here
typedef struct CGImage* CGImageRef;
+#else
+#include <X11/extensions/Xrender.h>
+#endif
+
+class Fl_RGB_Image;
-class OSXPixelBuffer: public PlatformPixelBuffer {
+class Surface {
public:
- OSXPixelBuffer(int width, int height);
- ~OSXPixelBuffer();
+ Surface(int width, int height);
+ Surface(const Fl_RGB_Image* image);
+ ~Surface();
- virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
+ int width() { return w; }
+ int height() { return h; }
+
+ void clear(unsigned char r, unsigned char g, unsigned char b, unsigned char a=255);
+
+ void draw(int src_x, int src_y, int x, int y, int w, int h);
protected:
+ void alloc();
+ void dealloc();
+ void update(const Fl_RGB_Image* image);
+
+protected:
+ int w, h;
+
+#if defined(WIN32)
+ RGBQUAD* data;
+ HBITMAP bitmap;
+#elif defined(__APPLE__)
+ unsigned char* data;
CGImageRef image;
+#else
+ Pixmap pixmap;
+ Picture picture;
+ XRenderPictFormat* visFormat;
+#endif
};
-
#endif
+
diff --git a/vncviewer/Surface_OSX.cxx b/vncviewer/Surface_OSX.cxx
new file mode 100644
index 00000000..c51e47f5
--- /dev/null
+++ b/vncviewer/Surface_OSX.cxx
@@ -0,0 +1,162 @@
+/* Copyright 2016 Pierre Ossman for Cendio AB
+ *
+ * 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.
+ */
+
+#include <assert.h>
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <FL/Fl_RGB_Image.H>
+#include <FL/Fl_Window.H>
+#include <FL/x.H>
+
+#include <rdr/Exception.h>
+
+#include "Surface.h"
+
+void Surface::clear(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+ unsigned char* out;
+ int x, y;
+
+ r = (unsigned)r * a / 255;
+ g = (unsigned)g * a / 255;
+ b = (unsigned)b * a / 255;
+
+ out = data;
+ for (y = 0;y < width();y++) {
+ for (x = 0;x < height();x++) {
+ *out++ = b;
+ *out++ = g;
+ *out++ = r;
+ *out++ = a;
+ }
+ }
+}
+
+void Surface::draw(int src_x, int src_y, int x, int y, int w, int h)
+{
+ CGRect rect;
+
+ CGContextSaveGState(fl_gc);
+
+ // Reset the transformation matrix back to the default identity
+ // matrix as otherwise we get a massive performance hit
+ CGContextConcatCTM(fl_gc, CGAffineTransformInvert(CGContextGetCTM(fl_gc)));
+
+ // macOS Coordinates are from bottom left, not top left
+ src_y = height() - (src_y + h);
+ y = Fl_Window::current()->h() - (y + h);
+
+ // We have to use clipping to partially display an image
+ rect.origin.x = x;
+ rect.origin.y = y;
+ rect.size.width = w;
+ rect.size.height = h;
+
+ CGContextClipToRect(fl_gc, rect);
+
+ rect.origin.x = x - src_x;
+ rect.origin.y = y - src_y;
+ rect.size.width = width();
+ rect.size.height = height();
+
+ CGContextDrawImage(fl_gc, rect, image);
+
+ CGContextRestoreGState(fl_gc);
+}
+
+void Surface::alloc()
+{
+ CGColorSpaceRef lut;
+ CGDataProviderRef provider;
+
+ data = new unsigned char[width() * height() * 4];
+
+ lut = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
+ if (!lut) {
+ lut = CGColorSpaceCreateDeviceRGB();
+ if (!lut)
+ throw rdr::Exception("CGColorSpaceCreateDeviceRGB");
+ }
+
+ provider = CGDataProviderCreateWithData(NULL, data,
+ width() * height() * 4, NULL);
+ if (!provider)
+ throw rdr::Exception("CGDataProviderCreateWithData");
+
+ image = CGImageCreate(width(), height(), 8, 32, width() * 4, lut,
+ kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
+ provider, NULL, false, kCGRenderingIntentDefault);
+ CGColorSpaceRelease(lut);
+ CGDataProviderRelease(provider);
+ if (!image)
+ throw rdr::Exception("CGImageCreate");
+}
+
+void Surface::dealloc()
+{
+ CGImageRelease(image);
+ delete [] data;
+}
+
+void Surface::update(const Fl_RGB_Image* image)
+{
+ int x, y;
+ const unsigned char* in;
+ unsigned char* out;
+
+ assert(image->w() == width());
+ assert(image->h() == height());
+
+ // Convert data and pre-multiply alpha
+ in = (const unsigned char*)image->data()[0];
+ out = data;
+ for (y = 0;y < image->h();y++) {
+ for (x = 0;x < image->w();x++) {
+ switch (image->d()) {
+ case 1:
+ *out++ = in[0];
+ *out++ = in[0];
+ *out++ = in[0];
+ *out++ = 0xff;
+ break;
+ case 2:
+ *out++ = (unsigned)in[0] * in[1] / 255;
+ *out++ = (unsigned)in[0] * in[1] / 255;
+ *out++ = (unsigned)in[0] * in[1] / 255;
+ *out++ = in[1];
+ break;
+ case 3:
+ *out++ = in[2];
+ *out++ = in[1];
+ *out++ = in[0];
+ *out++ = 0xff;
+ break;
+ case 4:
+ *out++ = (unsigned)in[2] * in[3] / 255;
+ *out++ = (unsigned)in[1] * in[3] / 255;
+ *out++ = (unsigned)in[0] * in[3] / 255;
+ *out++ = in[3];
+ break;
+ }
+ in += image->d();
+ }
+ if (image->ld() != 0)
+ in += image->ld() - image->w() * image->d();
+ }
+}
diff --git a/vncviewer/Surface_Win32.cxx b/vncviewer/Surface_Win32.cxx
new file mode 100644
index 00000000..5a9a6546
--- /dev/null
+++ b/vncviewer/Surface_Win32.cxx
@@ -0,0 +1,146 @@
+/* Copyright 2016 Pierre Ossman for Cendio AB
+ *
+ * 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.
+ */
+
+#include <assert.h>
+
+#include <FL/Fl_RGB_Image.H>
+#include <FL/x.H>
+
+#include <rdr/Exception.h>
+
+#include "Surface.h"
+
+void Surface::clear(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+ RGBQUAD* out;
+ int x, y;
+
+ r = (unsigned)r * a / 255;
+ g = (unsigned)g * a / 255;
+ b = (unsigned)b * a / 255;
+
+ out = data;
+ for (y = 0;y < width();y++) {
+ for (x = 0;x < height();x++) {
+ out->rgbRed = r;
+ out->rgbGreen = g;
+ out->rgbBlue = b;
+ out->rgbReserved = a;
+ out++;
+ }
+ }
+}
+
+void Surface::draw(int src_x, int src_y, int x, int y, int w, int h)
+{
+ HDC dc;
+
+ dc = CreateCompatibleDC(fl_gc);
+ if (!dc)
+ throw rdr::SystemException("CreateCompatibleDC", GetLastError());
+
+ if (!SelectObject(dc, bitmap))
+ throw rdr::SystemException("SelectObject", GetLastError());
+
+ if (!BitBlt(fl_gc, x, y, w, h, dc, src_x, src_y, SRCCOPY)) {
+ // If the desktop we're rendering to is inactive (like when the screen
+ // is locked or the UAC is active), then GDI calls will randomly fail.
+ // This is completely undocumented so we have no idea how best to deal
+ // with it. For now, we've only seen this error and for this function
+ // so only ignore this combination.
+ if (GetLastError() != ERROR_INVALID_HANDLE)
+ throw rdr::SystemException("BitBlt", GetLastError());
+ }
+
+ DeleteDC(dc);
+}
+
+void Surface::alloc()
+{
+ BITMAPINFOHEADER bih;
+
+ data = new RGBQUAD[width() * height()];
+
+ memset(&bih, 0, sizeof(bih));
+
+ bih.biSize = sizeof(BITMAPINFOHEADER);
+ bih.biBitCount = 32;
+ bih.biPlanes = 1;
+ bih.biWidth = width();
+ bih.biHeight = -height(); // Negative to get top-down
+ bih.biCompression = BI_RGB;
+
+ bitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bih,
+ DIB_RGB_COLORS, (void**)&data, NULL, 0);
+ if (!bitmap)
+ throw rdr::SystemException("CreateDIBSection", GetLastError());
+}
+
+void Surface::dealloc()
+{
+ DeleteObject(bitmap);
+}
+
+void Surface::update(const Fl_RGB_Image* image)
+{
+ const unsigned char* in;
+ RGBQUAD* out;
+ int x, y;
+
+ assert(image->w() == width());
+ assert(image->h() == height());
+
+ // Convert data and pre-multiply alpha
+ in = (const unsigned char*)image->data()[0];
+ out = data;
+ for (y = 0;y < image->w();y++) {
+ for (x = 0;x < image->h();x++) {
+ switch (image->d()) {
+ case 1:
+ out->rgbBlue = in[0];
+ out->rgbGreen = in[0];
+ out->rgbRed = in[0];
+ out->rgbReserved = 0xff;
+ break;
+ case 2:
+ out->rgbBlue = (unsigned)in[0] * in[1] / 255;
+ out->rgbGreen = (unsigned)in[0] * in[1] / 255;
+ out->rgbRed = (unsigned)in[0] * in[1] / 255;
+ out->rgbReserved = in[1];
+ break;
+ case 3:
+ out->rgbBlue = in[2];
+ out->rgbGreen = in[1];
+ out->rgbRed = in[0];
+ out->rgbReserved = 0xff;
+ break;
+ case 4:
+ out->rgbBlue = (unsigned)in[2] * in[3] / 255;
+ out->rgbGreen = (unsigned)in[1] * in[3] / 255;
+ out->rgbRed = (unsigned)in[0] * in[3] / 255;
+ out->rgbReserved = in[3];
+ break;
+ }
+ in += image->d();
+ out++;
+ }
+ if (image->ld() != 0)
+ in += image->ld() - image->w() * image->d();
+ }
+}
+
diff --git a/vncviewer/Surface_X11.cxx b/vncviewer/Surface_X11.cxx
new file mode 100644
index 00000000..c7e3778e
--- /dev/null
+++ b/vncviewer/Surface_X11.cxx
@@ -0,0 +1,139 @@
+/* Copyright 2016 Pierre Ossman for Cendio AB
+ *
+ * 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.
+ */
+
+#include <assert.h>
+
+#include <FL/Fl_RGB_Image.H>
+#include <FL/x.H>
+
+#include <rdr/Exception.h>
+
+#include "Surface.h"
+
+void Surface::clear(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+ XRenderColor color;
+
+ color.red = (unsigned)r * 65535 / 255 * a / 255;
+ color.green = (unsigned)g * 65535 / 255 * a / 255;
+ color.blue = (unsigned)b * 65535 / 255 * a / 255;
+ color.alpha = (unsigned)a * 65535 / 255;
+
+ XRenderFillRectangle(fl_display, PictOpSrc, picture, &color,
+ 0, 0, width(), height());
+}
+
+void Surface::draw(int src_x, int src_y, int x, int y, int w, int h)
+{
+ Picture winPict;
+
+ winPict = XRenderCreatePicture(fl_display, fl_window, visFormat, 0, NULL);
+ XRenderComposite(fl_display, PictOpSrc, picture, None, winPict,
+ src_x, src_y, 0, 0, x, y, w, h);
+ XRenderFreePicture(fl_display, winPict);
+}
+
+void Surface::alloc()
+{
+ XRenderPictFormat* format;
+
+ // Might not be open at this point
+ fl_open_display();
+
+ pixmap = XCreatePixmap(fl_display, XDefaultRootWindow(fl_display),
+ width(), height(), 32);
+
+ format = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
+ picture = XRenderCreatePicture(fl_display, pixmap, format, 0, NULL);
+
+ visFormat = XRenderFindVisualFormat(fl_display, fl_visual->visual);
+}
+
+void Surface::dealloc()
+{
+ XRenderFreePicture(fl_display, picture);
+ XFreePixmap(fl_display, pixmap);
+}
+
+void Surface::update(const Fl_RGB_Image* image)
+{
+ XImage* img;
+ GC gc;
+
+ int x, y;
+ const unsigned char* in;
+ unsigned char* out;
+
+ assert(image->w() == width());
+ assert(image->h() == height());
+
+ img = XCreateImage(fl_display, CopyFromParent, 32,
+ ZPixmap, 0, NULL, width(), height(),
+ 32, 0);
+ if (!img)
+ throw rdr::Exception("XCreateImage");
+
+ img->data = (char*)malloc(img->bytes_per_line * img->height);
+ if (!img->data)
+ throw rdr::Exception("malloc");
+
+ // Convert data and pre-multiply alpha
+ in = (const unsigned char*)image->data()[0];
+ out = (unsigned char*)img->data;
+ for (y = 0;y < img->height;y++) {
+ for (x = 0;x < img->width;x++) {
+ switch (image->d()) {
+ case 1:
+ *out++ = in[0];
+ *out++ = in[0];
+ *out++ = in[0];
+ *out++ = 0xff;
+ break;
+ case 2:
+ *out++ = (unsigned)in[0] * in[1] / 255;
+ *out++ = (unsigned)in[0] * in[1] / 255;
+ *out++ = (unsigned)in[0] * in[1] / 255;
+ *out++ = in[1];
+ break;
+ case 3:
+ *out++ = in[2];
+ *out++ = in[1];
+ *out++ = in[0];
+ *out++ = 0xff;
+ break;
+ case 4:
+ *out++ = (unsigned)in[2] * in[3] / 255;
+ *out++ = (unsigned)in[1] * in[3] / 255;
+ *out++ = (unsigned)in[0] * in[3] / 255;
+ *out++ = in[3];
+ break;
+ }
+ in += image->d();
+ }
+ if (image->ld() != 0)
+ in += image->ld() - image->w() * image->d();
+ }
+
+ gc = XCreateGC(fl_display, pixmap, 0, NULL);
+ XPutImage(fl_display, pixmap, gc, img,
+ 0, 0, 0, 0, img->width, img->height);
+ XFreeGC(fl_display, gc);
+
+ XDestroyImage(img);
+}
+
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 1e4ee1aa..7b3487c4 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -62,15 +62,6 @@
#include "vncviewer.h"
#include "PlatformPixelBuffer.h"
-#include "FLTKPixelBuffer.h"
-
-#if defined(WIN32)
-#include "Win32PixelBuffer.h"
-#elif defined(__APPLE__)
-#include "OSXPixelBuffer.h"
-#else
-#include "X11PixelBuffer.h"
-#endif
#include <FL/fl_draw.H>
#include <FL/fl_ask.H>
@@ -111,7 +102,7 @@ Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
// We need to intercept keyboard events early
Fl::add_system_handler(handleSystemEvent, this);
- frameBuffer = createFramebuffer(w, h);
+ frameBuffer = new PlatformPixelBuffer(w, h);
assert(frameBuffer);
cc->setFramebuffer(frameBuffer);
@@ -272,7 +263,7 @@ void Viewport::resize(int x, int y, int w, int h)
vlog.debug("Resizing framebuffer from %dx%d to %dx%d",
frameBuffer->width(), frameBuffer->height(), w, h);
- frameBuffer = createFramebuffer(w, h);
+ frameBuffer = new PlatformPixelBuffer(w, h);
assert(frameBuffer);
cc->setFramebuffer(frameBuffer);
}
@@ -374,29 +365,6 @@ int Viewport::handle(int event)
return Fl_Widget::handle(event);
}
-
-PlatformPixelBuffer* Viewport::createFramebuffer(int w, int h)
-{
- PlatformPixelBuffer *fb;
-
- try {
-#if defined(WIN32)
- fb = new Win32PixelBuffer(w, h);
-#elif defined(__APPLE__)
- fb = new OSXPixelBuffer(w, h);
-#else
- fb = new X11PixelBuffer(w, h);
-#endif
- } catch (rdr::Exception& e) {
- vlog.error(_("Unable to create platform specific framebuffer: %s"), e.str());
- vlog.error(_("Using platform independent framebuffer"));
- fb = new FLTKPixelBuffer(w, h);
- }
-
- return fb;
-}
-
-
void Viewport::handleClipboardChange(int source, void *data)
{
Viewport *self = (Viewport *)data;
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
index b50c8157..ac1ec338 100644
--- a/vncviewer/Viewport.h
+++ b/vncviewer/Viewport.h
@@ -56,8 +56,6 @@ public:
private:
- PlatformPixelBuffer* createFramebuffer(int w, int h);
-
static void handleClipboardChange(int source, void *data);
void handlePointerEvent(const rfb::Point& pos, int buttonMask);
diff --git a/vncviewer/Win32PixelBuffer.cxx b/vncviewer/Win32PixelBuffer.cxx
deleted file mode 100644
index 002d4c82..00000000
--- a/vncviewer/Win32PixelBuffer.cxx
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011-2014 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-
-#include <windows.h>
-
-#include <FL/x.H>
-
-#include <rfb/LogWriter.h>
-#include <rfb/Exception.h>
-
-#include "i18n.h"
-#include "Win32PixelBuffer.h"
-
-using namespace rfb;
-
-static rfb::LogWriter vlog("Win32PixelBuffer");
-
-Win32PixelBuffer::Win32PixelBuffer(int width, int height) :
- PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
- 255, 255, 255, 16, 8, 0),
- width, height, NULL, width),
- bitmap(NULL)
-{
- BITMAPINFOHEADER bih;
-
- memset(&bih, 0, sizeof(bih));
-
- bih.biSize = sizeof(BITMAPINFOHEADER);
- bih.biBitCount = getPF().bpp;
- bih.biSizeImage = (getPF().bpp / 8) * width * height;
- bih.biPlanes = 1;
- bih.biWidth = width;
- bih.biHeight = -height; // Negative to get top-down
- bih.biCompression = BI_RGB;
-
- bitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bih,
- DIB_RGB_COLORS, (void**)&data, NULL, 0);
- if (!bitmap)
- throw rdr::SystemException("CreateDIBSection", GetLastError());
-}
-
-
-Win32PixelBuffer::~Win32PixelBuffer()
-{
- DeleteObject(bitmap);
-}
-
-
-void Win32PixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
-{
- HDC dc;
-
- dc = CreateCompatibleDC(fl_gc);
- if (!dc)
- throw rdr::SystemException("CreateCompatibleDC", GetLastError());
-
- if (!SelectObject(dc, bitmap))
- throw rdr::SystemException("SelectObject", GetLastError());
-
- if (!BitBlt(fl_gc, x, y, w, h, dc, src_x, src_y, SRCCOPY)) {
- // If the desktop we're rendering to is inactive (like when the screen
- // is locked or the UAC is active), then GDI calls will randomly fail.
- // This is completely undocumented so we have no idea how best to deal
- // with it. For now, we've only seen this error and for this function
- // so only ignore this combination.
- if (GetLastError() != ERROR_INVALID_HANDLE)
- throw rdr::SystemException("BitBlt", GetLastError());
- }
-
- DeleteDC(dc);
-}
diff --git a/vncviewer/X11PixelBuffer.cxx b/vncviewer/X11PixelBuffer.cxx
deleted file mode 100644
index e23f7771..00000000
--- a/vncviewer/X11PixelBuffer.cxx
+++ /dev/null
@@ -1,229 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011-2014 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include <FL/Fl.H>
-#include <FL/x.H>
-
-#include <rfb/LogWriter.h>
-#include <rfb/Exception.h>
-
-#include "i18n.h"
-#include "X11PixelBuffer.h"
-
-using namespace rfb;
-
-static rfb::LogWriter vlog("X11PixelBuffer");
-
-static PixelFormat display_pf()
-{
- int i;
-
- int bpp;
- int trueColour, bigEndian;
- int redShift, greenShift, blueShift;
- int redMax, greenMax, blueMax;
-
- int nformats;
- XPixmapFormatValues* format;
-
- // Might not be open at this point
- fl_open_display();
-
- format = XListPixmapFormats(fl_display, &nformats);
-
- for (i = 0; i < nformats; i++)
- if (format[i].depth == fl_visual->depth) break;
-
- if (i == nformats)
- // TRANSLATORS: "pixmap" is an X11 concept and may not be suitable
- // to translate.
- throw rfb::Exception(_("Display lacks pixmap format for default depth"));
-
- switch (format[i].bits_per_pixel) {
- case 8:
- case 16:
- case 32:
- bpp = format[i].bits_per_pixel;
- break;
- default:
- // TRANSLATORS: "pixmap" is an X11 concept and may not be suitable
- // to translate.
- throw rfb::Exception(_("Couldn't find suitable pixmap format"));
- }
-
- XFree(format);
-
- bigEndian = (ImageByteOrder(fl_display) == MSBFirst);
- trueColour = (fl_visual->c_class == TrueColor);
-
- if (!trueColour)
- throw rfb::Exception(_("Only true colour displays supported"));
-
- vlog.info(_("Using default colormap and visual, TrueColor, depth %d."),
- fl_visual->depth);
-
- redShift = ffs(fl_visual->red_mask) - 1;
- greenShift = ffs(fl_visual->green_mask) - 1;
- blueShift = ffs(fl_visual->blue_mask) - 1;
- redMax = fl_visual->red_mask >> redShift;
- greenMax = fl_visual->green_mask >> greenShift;
- blueMax = fl_visual->blue_mask >> blueShift;
-
- return PixelFormat(bpp, fl_visual->depth, bigEndian, trueColour,
- redMax, greenMax, blueMax,
- redShift, greenShift, blueShift);
-}
-
-X11PixelBuffer::X11PixelBuffer(int width, int height) :
- PlatformPixelBuffer(display_pf(), width, height, NULL, 0),
- shminfo(NULL), xim(NULL)
-{
- // Might not be open at this point
- fl_open_display();
-
- if (!setupShm()) {
- xim = XCreateImage(fl_display, fl_visual->visual, fl_visual->depth,
- ZPixmap, 0, 0, width, height, BitmapPad(fl_display), 0);
- if (!xim)
- throw rfb::Exception("XCreateImage");
-
- xim->data = (char*)malloc(xim->bytes_per_line * xim->height);
- if (!xim->data)
- throw rfb::Exception(_("Not enough memory for framebuffer"));
-
- vlog.debug("Using standard XImage");
- }
-
- data = (rdr::U8*)xim->data;
- stride = xim->bytes_per_line / (getPF().bpp/8);
-}
-
-
-X11PixelBuffer::~X11PixelBuffer()
-{
- if (shminfo) {
- vlog.debug("Freeing shared memory XImage");
- shmdt(shminfo->shmaddr);
- shmctl(shminfo->shmid, IPC_RMID, 0);
- delete shminfo;
- shminfo = NULL;
- }
-
- // XDestroyImage() will free(xim->data) if appropriate
- if (xim)
- XDestroyImage(xim);
- xim = NULL;
-}
-
-
-void X11PixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
-{
- if (shminfo) {
- XShmPutImage(fl_display, fl_window, fl_gc, xim, src_x, src_y, x, y, w, h, False);
- // Need to make sure the X server has finished reading the
- // shared memory before we return
- XSync(fl_display, False);
- } else {
- XPutImage(fl_display, fl_window, fl_gc, xim, src_x, src_y, x, y, w, h);
- }
-}
-
-static bool caughtError;
-
-static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error)
-{
- caughtError = true;
- return 0;
-}
-
-int X11PixelBuffer::setupShm()
-{
- int major, minor;
- Bool pixmaps;
- XErrorHandler old_handler;
- const char *display_name = XDisplayName (NULL);
-
- /* Don't use MIT-SHM on remote displays */
- if (*display_name && *display_name != ':')
- return 0;
-
- if (!XShmQueryVersion(fl_display, &major, &minor, &pixmaps))
- return 0;
-
- shminfo = new XShmSegmentInfo;
-
- xim = XShmCreateImage(fl_display, fl_visual->visual, fl_visual->depth,
- ZPixmap, 0, shminfo, width(), height());
- if (!xim)
- goto free_shminfo;
-
- shminfo->shmid = shmget(IPC_PRIVATE,
- xim->bytes_per_line * xim->height,
- IPC_CREAT|0777);
- if (shminfo->shmid == -1)
- goto free_xim;
-
- shminfo->shmaddr = xim->data = (char*)shmat(shminfo->shmid, 0, 0);
- shmctl(shminfo->shmid, IPC_RMID, 0); // to avoid memory leakage
- if (shminfo->shmaddr == (char *)-1)
- goto free_xim;
-
- shminfo->readOnly = True;
-
- // This is the only way we can detect that shared memory won't work
- // (e.g. because we're accessing a remote X11 server)
- caughtError = false;
- old_handler = XSetErrorHandler(XShmAttachErrorHandler);
-
- if (!XShmAttach(fl_display, shminfo)) {
- XSetErrorHandler(old_handler);
- goto free_shmaddr;
- }
-
- XSync(fl_display, False);
-
- XSetErrorHandler(old_handler);
-
- if (caughtError)
- goto free_shmaddr;
-
- vlog.debug("Using shared memory XImage");
-
- return 1;
-
-free_shmaddr:
- shmdt(shminfo->shmaddr);
-
-free_xim:
- XDestroyImage(xim);
- xim = NULL;
-
-free_shminfo:
- delete shminfo;
- shminfo = NULL;
-
- return 0;
-}
diff --git a/vncviewer/X11PixelBuffer.h b/vncviewer/X11PixelBuffer.h
deleted file mode 100644
index fdd88b75..00000000
--- a/vncviewer/X11PixelBuffer.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright 2011-2014 Pierre Ossman for Cendio AB
- *
- * 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.
- */
-
-#ifndef __X11PIXELBUFFER_H__
-#define __X11PIXELBUFFER_H__
-
-#include <X11/Xlib.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/extensions/XShm.h>
-
-#include <list>
-
-#include "PlatformPixelBuffer.h"
-
-class X11PixelBuffer: public PlatformPixelBuffer {
-public:
- X11PixelBuffer(int width, int height);
- ~X11PixelBuffer();
-
- virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
-
-protected:
- int setupShm();
-
-protected:
- XShmSegmentInfo *shminfo;
- XImage *xim;
-};
-
-
-#endif