]> source.dussan.org Git - tigervnc.git/commitdiff
Abstract platform rendering to "surfaces"
authorPierre Ossman <ossman@cendio.se>
Mon, 2 Jan 2017 16:00:41 +0000 (17:00 +0100)
committerPierre Ossman <ossman@cendio.se>
Fri, 10 Feb 2017 16:02:13 +0000 (17:02 +0100)
This will allow us to render more things than just the framebuffer.

18 files changed:
tests/CMakeLists.txt
tests/fbperf.cxx
vncviewer/CMakeLists.txt
vncviewer/OSXPixelBuffer.cxx [deleted file]
vncviewer/OSXPixelBuffer.h [deleted file]
vncviewer/PlatformPixelBuffer.cxx
vncviewer/PlatformPixelBuffer.h
vncviewer/Surface.cxx [new file with mode: 0644]
vncviewer/Surface.h [new file with mode: 0644]
vncviewer/Surface_OSX.cxx [new file with mode: 0644]
vncviewer/Surface_Win32.cxx [new file with mode: 0644]
vncviewer/Surface_X11.cxx [new file with mode: 0644]
vncviewer/Viewport.cxx
vncviewer/Viewport.h
vncviewer/Win32PixelBuffer.cxx [deleted file]
vncviewer/Win32PixelBuffer.h [deleted file]
vncviewer/X11PixelBuffer.cxx [deleted file]
vncviewer/X11PixelBuffer.h [deleted file]

index 7c994539ef5e9b57886cd3bb255ad0b0a072d821..5fbaa11ab79593be666f37364ca6dd9e589fc3b1 100644 (file)
@@ -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})
index 5c37b0f74b747855bd7ba3d1c336b1ace4faca54..8c71d966942d9361a24cf0cbd3b14928aa7ae1dc 100644 (file)
 #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;
 }
index f11bae3fbefa12a6902fe0c753a0f7d33912b3ff..d6a1b585e760426dc279e9abd035adfa75cd7694 100644 (file)
@@ -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 (file)
index 5c9611c..0000000
+++ /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/OSXPixelBuffer.h b/vncviewer/OSXPixelBuffer.h
deleted file mode 100644 (file)
index 958b1ea..0000000
+++ /dev/null
@@ -1,39 +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 __OSXPIXELBUFFER_H__
-#define __OSXPIXELBUFFER_H__
-
-#include "PlatformPixelBuffer.h"
-
-// Apple headers conflict with FLTK, so redefine types here
-typedef struct CGImage* CGImageRef;
-
-class OSXPixelBuffer: public PlatformPixelBuffer {
-public:
-  OSXPixelBuffer(int width, int height);
-  ~OSXPixelBuffer();
-
-  virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
-
-protected:
-  CGImageRef image;
-};
-
-
-#endif
index 522bad3f9755580d64c2d6062d4b343d5f2f2360..4802ba46836ecbd7a1aae29390083c2684b1dea2 100644 (file)
@@ -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
  * 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
index 795273a9bea4fc025f19144f559d06a990c56050..26ae7ca338c3c1b4c840095dcd9b54239a1e0c2a 100644 (file)
@@ -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
 #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/Surface.cxx b/vncviewer/Surface.cxx
new file mode 100644 (file)
index 0000000..fbd4143
--- /dev/null
@@ -0,0 +1,39 @@
+/* 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 <FL/Fl_RGB_Image.H>
+
+#include "Surface.h"
+
+Surface::Surface(int width, int height) :
+  w(width), h(height)
+{
+  alloc();
+}
+
+Surface::Surface(const Fl_RGB_Image* image) :
+  w(image->w()), h(image->h())
+{
+  alloc();
+  update(image);
+}
+
+Surface::~Surface()
+{
+  dealloc();
+}
diff --git a/vncviewer/Surface.h b/vncviewer/Surface.h
new file mode 100644 (file)
index 0000000..02917e3
--- /dev/null
@@ -0,0 +1,68 @@
+/* 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.
+ */
+
+#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 Surface {
+public:
+  Surface(int width, int height);
+  Surface(const Fl_RGB_Image* image);
+  ~Surface();
+
+  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 (file)
index 0000000..c51e47f
--- /dev/null
@@ -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 (file)
index 0000000..5a9a654
--- /dev/null
@@ -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 (file)
index 0000000..c7e3778
--- /dev/null
@@ -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);
+}
+
index 1e4ee1aa23abb0d0b323ea2e08822e915bade14c..7b3487c4686169b84a61d7965fc1e4442dca6767 100644 (file)
 #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;
index b50c815700db09cdafdb49093cd34df8110c8bb6..ac1ec338e85383fdc55f9b1d6032795f218ff756 100644 (file)
@@ -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 (file)
index 002d4c8..0000000
+++ /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/Win32PixelBuffer.h b/vncviewer/Win32PixelBuffer.h
deleted file mode 100644 (file)
index 728e594..0000000
+++ /dev/null
@@ -1,38 +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 __WIN32PIXELBUFFER_H__
-#define __WIN32PIXELBUFFER_H__
-
-#include <windows.h>
-
-#include "PlatformPixelBuffer.h"
-
-class Win32PixelBuffer: public PlatformPixelBuffer {
-public:
-  Win32PixelBuffer(int width, int height);
-  ~Win32PixelBuffer();
-
-  virtual void draw(int src_x, int src_y, int x, int y, int w, int h);
-
-protected:
-  HBITMAP bitmap;
-};
-
-
-#endif
diff --git a/vncviewer/X11PixelBuffer.cxx b/vncviewer/X11PixelBuffer.cxx
deleted file mode 100644 (file)
index e23f777..0000000
+++ /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 (file)
index fdd88b7..0000000
+++ /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