diff options
author | Pierre Ossman <ossman@cendio.se> | 2015-11-18 16:24:16 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2015-11-27 11:15:38 +0100 |
commit | c9dd3a40234b54c7cc9bade71a6cd84af5325fb2 (patch) | |
tree | 994af4dfd3fd75626007c15b316eb8148b443caf /vncviewer | |
parent | 5102fa96876907adca3d0897d67108c60a2545b0 (diff) | |
download | tigervnc-c9dd3a40234b54c7cc9bade71a6cd84af5325fb2.tar.gz tigervnc-c9dd3a40234b54c7cc9bade71a6cd84af5325fb2.zip |
Throttle overlapping screen updates
We need to make sure the display server has finished reading our
previous update before we overwrite the buffer with the next update.
Diffstat (limited to 'vncviewer')
-rw-r--r-- | vncviewer/CConn.cxx | 20 | ||||
-rw-r--r-- | vncviewer/PlatformPixelBuffer.cxx | 5 | ||||
-rw-r--r-- | vncviewer/PlatformPixelBuffer.h | 2 | ||||
-rw-r--r-- | vncviewer/X11PixelBuffer.cxx | 53 | ||||
-rw-r--r-- | vncviewer/X11PixelBuffer.h | 9 |
5 files changed, 85 insertions, 4 deletions
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx index fb136b5f..262dd2ce 100644 --- a/vncviewer/CConn.cxx +++ b/vncviewer/CConn.cxx @@ -46,6 +46,7 @@ #include "CConn.h" #include "OptionsDialog.h" #include "DesktopWindow.h" +#include "PlatformPixelBuffer.h" #include "i18n.h" #include "parameters.h" #include "vncviewer.h" @@ -336,6 +337,9 @@ void CConn::setName(const char* name) // one. void CConn::framebufferUpdateStart() { + ModifiablePixelBuffer* pb; + PlatformPixelBuffer* ppb; + CConnection::framebufferUpdateStart(); // Note: This might not be true if sync fences are supported @@ -343,6 +347,22 @@ void CConn::framebufferUpdateStart() requestNewUpdate(); + // We might still be rendering the previous update + pb = getFramebuffer(); + assert(pb != NULL); + ppb = dynamic_cast<PlatformPixelBuffer*>(pb); + assert(ppb != NULL); + if (ppb->isRendering()) { + // Need to stop monitoring the socket or we'll just busy loop + assert(sock != NULL); + Fl::remove_fd(sock->getFd()); + + while (ppb->isRendering()) + run_mainloop(); + + Fl::add_fd(sock->getFd(), FL_READ | FL_EXCEPT, socketEvent, this); + } + // Update the screen prematurely for very slow updates Fl::add_timeout(1.0, handleUpdateTimeout, this); } diff --git a/vncviewer/PlatformPixelBuffer.cxx b/vncviewer/PlatformPixelBuffer.cxx index 522bad3f..876ab94a 100644 --- a/vncviewer/PlatformPixelBuffer.cxx +++ b/vncviewer/PlatformPixelBuffer.cxx @@ -44,3 +44,8 @@ rfb::Rect PlatformPixelBuffer::getDamage(void) return r; } + +bool PlatformPixelBuffer::isRendering(void) +{ + return false; +} diff --git a/vncviewer/PlatformPixelBuffer.h b/vncviewer/PlatformPixelBuffer.h index 795273a9..9f0e3b16 100644 --- a/vncviewer/PlatformPixelBuffer.h +++ b/vncviewer/PlatformPixelBuffer.h @@ -34,6 +34,8 @@ public: virtual void draw(int src_x, int src_y, int x, int y, int w, int h) = 0; rfb::Rect getDamage(void); + virtual bool isRendering(void); + protected: os::Mutex mutex; rfb::Region damage; diff --git a/vncviewer/X11PixelBuffer.cxx b/vncviewer/X11PixelBuffer.cxx index 9196fdca..046676eb 100644 --- a/vncviewer/X11PixelBuffer.cxx +++ b/vncviewer/X11PixelBuffer.cxx @@ -21,8 +21,10 @@ #include <config.h> #endif +#include <assert.h> #include <stdlib.h> +#include <FL/Fl.H> #include <FL/x.H> #include <rfb/LogWriter.h> @@ -35,6 +37,8 @@ using namespace rfb; static rfb::LogWriter vlog("X11PixelBuffer"); +std::list<X11PixelBuffer*> X11PixelBuffer::shmList; + static PixelFormat display_pf() { int i; @@ -97,7 +101,7 @@ static PixelFormat display_pf() X11PixelBuffer::X11PixelBuffer(int width, int height) : PlatformPixelBuffer(display_pf(), width, height, NULL, 0), - shminfo(NULL), xim(NULL) + shminfo(NULL), xim(NULL), pendingPutImage(0) { // Might not be open at this point fl_open_display(); @@ -122,6 +126,8 @@ X11PixelBuffer::~X11PixelBuffer() { if (shminfo) { vlog.debug("Freeing shared memory XImage"); + shmList.remove(this); + Fl::remove_system_handler(handleSystemEvent); shmdt(shminfo->shmaddr); shmctl(shminfo->shmid, IPC_RMID, 0); delete shminfo; @@ -137,12 +143,18 @@ X11PixelBuffer::~X11PixelBuffer() 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); - else + if (shminfo) { + XShmPutImage(fl_display, fl_window, fl_gc, xim, src_x, src_y, x, y, w, h, True); + pendingPutImage++; + } else { XPutImage(fl_display, fl_window, fl_gc, xim, src_x, src_y, x, y, w, h); + } } +bool X11PixelBuffer::isRendering(void) +{ + return pendingPutImage > 0; +} static bool caughtError; @@ -202,6 +214,11 @@ int X11PixelBuffer::setupShm() if (caughtError) goto free_shmaddr; + // FLTK is a bit stupid and unreliable if you register the same + // callback with different data values. + Fl::add_system_handler(handleSystemEvent, NULL); + shmList.push_back(this); + vlog.debug("Using shared memory XImage"); return 1; @@ -222,3 +239,31 @@ free_shminfo: return 0; } + +int X11PixelBuffer::handleSystemEvent(void* event, void* data) +{ + XEvent* xevent; + XShmCompletionEvent* shmevent; + + std::list<X11PixelBuffer*>::iterator iter; + + xevent = (XEvent*)event; + assert(xevent); + + if (xevent->type != XShmGetEventBase(fl_display)) + return 0; + + shmevent = (XShmCompletionEvent*)event; + + for (iter = shmList.begin();iter != shmList.end();++iter) { + if (shmevent->shmseg != (*iter)->shminfo->shmseg) + continue; + + (*iter)->pendingPutImage--; + assert((*iter)->pendingPutImage >= 0); + + return 1; + } + + return 0; +} diff --git a/vncviewer/X11PixelBuffer.h b/vncviewer/X11PixelBuffer.h index c2ffdc28..115984da 100644 --- a/vncviewer/X11PixelBuffer.h +++ b/vncviewer/X11PixelBuffer.h @@ -24,6 +24,8 @@ #include <sys/shm.h> #include <X11/extensions/XShm.h> +#include <list> + #include "PlatformPixelBuffer.h" class X11PixelBuffer: public PlatformPixelBuffer { @@ -33,12 +35,19 @@ public: virtual void draw(int src_x, int src_y, int x, int y, int w, int h); + virtual bool isRendering(void); + protected: int setupShm(); + static int handleSystemEvent(void* event, void* data); + protected: XShmSegmentInfo *shminfo; XImage *xim; + int pendingPutImage; + + static std::list<X11PixelBuffer*> shmList; }; |