|
|
@@ -37,8 +37,6 @@ using namespace rfb; |
|
|
|
|
|
|
|
static rfb::LogWriter vlog("X11PixelBuffer"); |
|
|
|
|
|
|
|
std::list<X11PixelBuffer*> X11PixelBuffer::shmList; |
|
|
|
|
|
|
|
static PixelFormat display_pf() |
|
|
|
{ |
|
|
|
int i; |
|
|
@@ -101,7 +99,7 @@ static PixelFormat display_pf() |
|
|
|
|
|
|
|
X11PixelBuffer::X11PixelBuffer(int width, int height) : |
|
|
|
PlatformPixelBuffer(display_pf(), width, height, NULL, 0), |
|
|
|
shminfo(NULL), xim(NULL), pendingPutImage(0), pendingDrawable(0) |
|
|
|
shminfo(NULL), xim(NULL) |
|
|
|
{ |
|
|
|
// Might not be open at this point |
|
|
|
fl_open_display(); |
|
|
@@ -128,8 +126,6 @@ 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; |
|
|
@@ -146,20 +142,15 @@ 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, True); |
|
|
|
pendingPutImage++; |
|
|
|
assert((pendingPutImage == 1) || (pendingDrawable == fl_window)); |
|
|
|
pendingDrawable = fl_window; |
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bool X11PixelBuffer::isRendering(void) |
|
|
|
{ |
|
|
|
return pendingPutImage > 0; |
|
|
|
} |
|
|
|
|
|
|
|
static bool caughtError; |
|
|
|
|
|
|
|
static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error) |
|
|
@@ -218,11 +209,6 @@ 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; |
|
|
@@ -243,39 +229,3 @@ 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) + ShmCompletion) |
|
|
|
return 0; |
|
|
|
|
|
|
|
shmevent = (XShmCompletionEvent*)event; |
|
|
|
|
|
|
|
if (shmevent->send_event) |
|
|
|
return 0; |
|
|
|
|
|
|
|
for (iter = shmList.begin();iter != shmList.end();++iter) { |
|
|
|
if (shmevent->shmseg != (*iter)->shminfo->shmseg) |
|
|
|
continue; |
|
|
|
|
|
|
|
/* HP has a buggy X server on their thin clients that sends bogus |
|
|
|
* extra events with an incorrect drawable id */ |
|
|
|
if (shmevent->drawable != (*iter)->pendingDrawable) |
|
|
|
continue; |
|
|
|
|
|
|
|
(*iter)->pendingPutImage--; |
|
|
|
assert((*iter)->pendingPutImage >= 0); |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |