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

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 Целия файл

#include "CConn.h" #include "CConn.h"
#include "OptionsDialog.h" #include "OptionsDialog.h"
#include "DesktopWindow.h" #include "DesktopWindow.h"
#include "PlatformPixelBuffer.h"
#include "i18n.h" #include "i18n.h"
#include "parameters.h" #include "parameters.h"
#include "vncviewer.h" #include "vncviewer.h"
// one. // one.
void CConn::framebufferUpdateStart() void CConn::framebufferUpdateStart()
{ {
ModifiablePixelBuffer* pb;
PlatformPixelBuffer* ppb;

CConnection::framebufferUpdateStart(); CConnection::framebufferUpdateStart();


// Note: This might not be true if sync fences are supported // Note: This might not be true if sync fences are supported


requestNewUpdate(); 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 // Update the screen prematurely for very slow updates
Fl::add_timeout(1.0, handleUpdateTimeout, this); Fl::add_timeout(1.0, handleUpdateTimeout, this);
} }

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



return r; return r;
} }

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

+ 2
- 0
vncviewer/PlatformPixelBuffer.h Целия файл

virtual void draw(int src_x, int src_y, int x, int y, int w, int h) = 0; virtual void draw(int src_x, int src_y, int x, int y, int w, int h) = 0;
rfb::Rect getDamage(void); rfb::Rect getDamage(void);


virtual bool isRendering(void);

protected: protected:
os::Mutex mutex; os::Mutex mutex;
rfb::Region damage; rfb::Region damage;

+ 49
- 4
vncviewer/X11PixelBuffer.cxx Целия файл

#include <config.h> #include <config.h>
#endif #endif


#include <assert.h>
#include <stdlib.h> #include <stdlib.h>


#include <FL/Fl.H>
#include <FL/x.H> #include <FL/x.H>


#include <rfb/LogWriter.h> #include <rfb/LogWriter.h>


static rfb::LogWriter vlog("X11PixelBuffer"); static rfb::LogWriter vlog("X11PixelBuffer");


std::list<X11PixelBuffer*> X11PixelBuffer::shmList;

static PixelFormat display_pf() static PixelFormat display_pf()
{ {
int i; int i;


X11PixelBuffer::X11PixelBuffer(int width, int height) : X11PixelBuffer::X11PixelBuffer(int width, int height) :
PlatformPixelBuffer(display_pf(), width, height, NULL, 0), PlatformPixelBuffer(display_pf(), width, height, NULL, 0),
shminfo(NULL), xim(NULL)
shminfo(NULL), xim(NULL), pendingPutImage(0)
{ {
// Might not be open at this point // Might not be open at this point
fl_open_display(); fl_open_display();
{ {
if (shminfo) { if (shminfo) {
vlog.debug("Freeing shared memory XImage"); vlog.debug("Freeing shared memory XImage");
shmList.remove(this);
Fl::remove_system_handler(handleSystemEvent);
shmdt(shminfo->shmaddr); shmdt(shminfo->shmaddr);
shmctl(shminfo->shmid, IPC_RMID, 0); shmctl(shminfo->shmid, IPC_RMID, 0);
delete shminfo; delete shminfo;


void X11PixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h) 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); 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 bool caughtError;


if (caughtError) if (caughtError)
goto free_shmaddr; 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"); vlog.debug("Using shared memory XImage");


return 1; return 1;


return 0; 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 Целия файл

#include <sys/shm.h> #include <sys/shm.h>
#include <X11/extensions/XShm.h> #include <X11/extensions/XShm.h>


#include <list>

#include "PlatformPixelBuffer.h" #include "PlatformPixelBuffer.h"


class X11PixelBuffer: public PlatformPixelBuffer { class X11PixelBuffer: public PlatformPixelBuffer {


virtual void draw(int src_x, int src_y, int x, int y, int w, int h); virtual void draw(int src_x, int src_y, int x, int y, int w, int h);


virtual bool isRendering(void);

protected: protected:
int setupShm(); int setupShm();


static int handleSystemEvent(void* event, void* data);

protected: protected:
XShmSegmentInfo *shminfo; XShmSegmentInfo *shminfo;
XImage *xim; XImage *xim;
int pendingPutImage;

static std::list<X11PixelBuffer*> shmList;
}; };





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