Browse Source

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.
tags/v1.6.90
Pierre Ossman 8 years ago
parent
commit
c9dd3a4023

+ 20
- 0
vncviewer/CConn.cxx View File

@@ -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);
}

+ 5
- 0
vncviewer/PlatformPixelBuffer.cxx View File

@@ -44,3 +44,8 @@ rfb::Rect PlatformPixelBuffer::getDamage(void)

return r;
}

bool PlatformPixelBuffer::isRendering(void)
{
return false;
}

+ 2
- 0
vncviewer/PlatformPixelBuffer.h View File

@@ -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;

+ 49
- 4
vncviewer/X11PixelBuffer.cxx View File

@@ -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;
}

+ 9
- 0
vncviewer/X11PixelBuffer.h View File

@@ -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;
};



Loading…
Cancel
Save