diff options
Diffstat (limited to 'vncviewer/X11PixelBuffer.cxx')
-rw-r--r-- | vncviewer/X11PixelBuffer.cxx | 53 |
1 files changed, 49 insertions, 4 deletions
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; +} |