Преглед на файлове

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 години
родител
ревизия
c9dd3a4023
променени са 5 файла, в които са добавени 85 реда и са изтрити 4 реда
  1. 20
    0
      vncviewer/CConn.cxx
  2. 5
    0
      vncviewer/PlatformPixelBuffer.cxx
  3. 2
    0
      vncviewer/PlatformPixelBuffer.h
  4. 49
    4
      vncviewer/X11PixelBuffer.cxx
  5. 9
    0
      vncviewer/X11PixelBuffer.h

+ 20
- 0
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);
}

+ 5
- 0
vncviewer/PlatformPixelBuffer.cxx Целия файл

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

return r;
}

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

+ 2
- 0
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;

+ 49
- 4
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;
}

+ 9
- 0
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;
};



Loading…
Отказ
Запис