From 9760ff6ef9b538b92e93d9eb8db1b342eb3fc9d6 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 25 Mar 2009 10:32:07 +0000 Subject: [PATCH] Try to update an entire FramebufferUpdate in one go, avoiding tears. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3717 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- unix/vncviewer/DesktopWindow.cxx | 36 +++++++++++++++++++------------- unix/vncviewer/DesktopWindow.h | 18 ++++++++++------ 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/unix/vncviewer/DesktopWindow.cxx b/unix/vncviewer/DesktopWindow.cxx index 89198596..36f96fc7 100644 --- a/unix/vncviewer/DesktopWindow.cxx +++ b/unix/vncviewer/DesktopWindow.cxx @@ -65,7 +65,7 @@ static rfb::LogWriter vlog("DesktopWindow"); DesktopWindow::DesktopWindow(Display* dpy, int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_, TXWindow* parent) - : TXWindow(dpy, w, h, parent), cc(cc_), im(0), + : TXWindow(dpy, w, h, parent), cc(cc_), im(0), updateTimer(this), cursorVisible(false), cursorAvailable(false), currentSelectionTime(0), newSelection(0), gettingInitialSelectionTime(true), newServerCutText(false), serverCutText_(0), @@ -216,7 +216,6 @@ void DesktopWindow::hideLocalCursor() if (cursorVisible) { cursorVisible = false; im->imageRect(cursorBackingRect, cursorBacking.data); - im->put(win(), gc, cursorBackingRect); } } @@ -238,7 +237,6 @@ void DesktopWindow::showLocalCursor() im->getImage(cursorBacking.data, cursorBackingRect); im->maskRect(cursorRect, cursor.data, cursor.mask.buf); - im->put(win(), gc, cursorBackingRect); } } @@ -266,19 +264,11 @@ void DesktopWindow::serverCutText(const char* str, rdr::U32 len) } -// Call XSync() at the end of an update. We do this because we'd like to -// ensure that the current update has actually been drawn by the X server -// before the next update arrives - this is necessary for copyRect to -// behave correctly. In particular, if part of the source of a copyRect is -// not actually displayed in the window, then XCopyArea results in -// GraphicsExpose events, which require us to draw from the off-screen -// image. By the time XSync returns, the GraphicsExpose events will be in -// Xlib's queue, so hopefully will be processed before the next update. -// Possibly we should process the GraphicsExpose events here explicitly? +// Update the actual window with the changed parts of the framebuffer. void DesktopWindow::framebufferUpdateEnd() { - XSync(dpy, False); + updateWindow(); } @@ -297,7 +287,7 @@ void DesktopWindow::invertRect(const Rect& r) } } } - im->put(win(), gc, r); + damageRect(r); } @@ -311,6 +301,22 @@ void DesktopWindow::resize(int w, int h) } +// Copy the areas of the framebuffer that have been changed (damaged) +// to the displayed window. + +void DesktopWindow::updateWindow() +{ + Rect r; + + updateTimer.stop(); + + r = damage.get_bounding_rect(); + damage.clear(); + + im->put(win(), gc, r); +} + + bool DesktopWindow::handleTimeout(rfb::Timer* timer) { if (timer == &setColourMapEntriesTimer) { @@ -320,6 +326,8 @@ bool DesktopWindow::handleTimeout(rfb::Timer* timer) if (!viewOnly) { cc->writer()->pointerEvent(lastPointerPos, lastButtonMask); } + } else if (timer == &updateTimer) { + updateWindow(); } return false; } diff --git a/unix/vncviewer/DesktopWindow.h b/unix/vncviewer/DesktopWindow.h index fe5ef82a..433ac33b 100644 --- a/unix/vncviewer/DesktopWindow.h +++ b/unix/vncviewer/DesktopWindow.h @@ -24,6 +24,7 @@ #include #include +#include #include #include "TXWindow.h" #include "TXViewport.h" @@ -61,13 +62,13 @@ public: void fillRect(const rfb::Rect& r, rfb::Pixel pix) { if (r.overlaps(cursorBackingRect)) hideLocalCursor(); im->fillRect(r, pix); - im->put(win(), gc, r); + damageRect(r); showLocalCursor(); } void imageRect(const rfb::Rect& r, void* pixels) { if (r.overlaps(cursorBackingRect)) hideLocalCursor(); im->imageRect(r, pixels); - im->put(win(), gc, r); + damageRect(r); showLocalCursor(); } void copyRect(const rfb::Rect& r, int srcX, int srcY) { @@ -75,11 +76,8 @@ public: cursorBackingRect.overlaps(rfb::Rect(srcX, srcY, srcX+r.width(), srcY+r.height()))) hideLocalCursor(); - if (im->usingShm()) - XSync(dpy, False); im->copyRect(r, rfb::Point(r.tl.x-srcX, r.tl.y-srcY)); - XCopyArea(dpy, win(), win(), gc, srcX, srcY, - r.width(), r.height(), r.tl.x, r.tl.y); + damageRect(r); showLocalCursor(); } void invertRect(const rfb::Rect& r); @@ -97,12 +95,20 @@ private: void createXCursors(); void hideLocalCursor(); void showLocalCursor(); + void damageRect(const rfb::Rect& r) { + damage.assign_union(rfb::Region(r)); + if (!updateTimer.isStarted()) + updateTimer.start(100); + }; + void updateWindow(); bool handleTimeout(rfb::Timer* timer); void handlePointerEvent(const rfb::Point& pos, int buttonMask); CConn* cc; TXImage* im; GC gc; + rfb::Region damage; + rfb::Timer updateTimer; ::Cursor dotCursor, noCursor, localXCursor; rfb::Cursor cursor; -- 2.39.5