From a32040d7c9972f70272218effbc0242416d417d2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 6 Feb 2014 16:31:10 +0100 Subject: [PATCH] Provide a better R/W base PixelBuffer class Clearly separates the read API from the write API and also from actual implementation. --- common/rfb/ComparingUpdateTracker.cxx | 2 + common/rfb/PixelBuffer.cxx | 67 ++++++++++++++++++++------- common/rfb/PixelBuffer.h | 46 ++++++++++++++---- vncviewer/CConn.cxx | 2 +- vncviewer/DesktopWindow.cxx | 4 +- vncviewer/DesktopWindow.h | 2 +- vncviewer/Viewport.cxx | 6 +++ vncviewer/Viewport.h | 5 +- win/rfb_win32/DeviceFrameBuffer.cxx | 1 + 9 files changed, 103 insertions(+), 32 deletions(-) diff --git a/common/rfb/ComparingUpdateTracker.cxx b/common/rfb/ComparingUpdateTracker.cxx index 8d4311a1..1d27f3c4 100644 --- a/common/rfb/ComparingUpdateTracker.cxx +++ b/common/rfb/ComparingUpdateTracker.cxx @@ -157,6 +157,8 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) oldData += oldStrideBytes * BLOCK_SIZE; } + oldFb.commitBufferRW(r); + if (!changedBlocks.empty()) { Region temp; temp.setOrderedRects(changedBlocks); diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx index ea19d183..bcffa791 100644 --- a/common/rfb/PixelBuffer.cxx +++ b/common/rfb/PixelBuffer.cxx @@ -60,26 +60,24 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) { } } +// -=- Modifiable generic pixel buffer class -FullFramePixelBuffer::FullFramePixelBuffer(const PixelFormat& pf, int w, int h, - rdr::U8* data_, int stride_) - : PixelBuffer(pf, w, h), data(data_), stride(stride_) +ModifiablePixelBuffer::ModifiablePixelBuffer(const PixelFormat& pf, + int w, int h) + : PixelBuffer(pf, w, h) { } -FullFramePixelBuffer::FullFramePixelBuffer() : data(0) {} - -FullFramePixelBuffer::~FullFramePixelBuffer() {} - - -rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_) +ModifiablePixelBuffer::ModifiablePixelBuffer() { - *stride_ = stride; - return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8]; } +ModifiablePixelBuffer::~ModifiablePixelBuffer() +{ +} -void FullFramePixelBuffer::fillRect(const Rect& r, Pixel pix) { +void ModifiablePixelBuffer::fillRect(const Rect& r, Pixel pix) +{ int stride; U8 *buf, pixbuf[4]; int w, h, b; @@ -99,9 +97,13 @@ void FullFramePixelBuffer::fillRect(const Rect& r, Pixel pix) { } buf += (stride - w) * b; } + + commitBufferRW(r); } -void FullFramePixelBuffer::imageRect(const Rect& r, const void* pixels, int srcStride) { +void ModifiablePixelBuffer::imageRect(const Rect& r, + const void* pixels, int srcStride) +{ int bytesPerPixel = getPF().bpp/8; int destStride; U8* dest = getBufferRW(r, &destStride); @@ -116,9 +118,12 @@ void FullFramePixelBuffer::imageRect(const Rect& r, const void* pixels, int srcS dest += bytesPerDestRow; src += bytesPerSrcRow; } + commitBufferRW(r); } -void FullFramePixelBuffer::maskRect(const Rect& r, const void* pixels, const void* mask_) { +void ModifiablePixelBuffer::maskRect(const Rect& r, + const void* pixels, const void* mask_) +{ Rect cr = getRect().intersect(r); if (cr.is_empty()) return; int stride; @@ -154,9 +159,13 @@ void FullFramePixelBuffer::maskRect(const Rect& r, const void* pixels, const voi } mask += maskStride; } + + commitBufferRW(cr); } -void FullFramePixelBuffer::maskRect(const Rect& r, Pixel pixel, const void* mask_) { +void ModifiablePixelBuffer::maskRect(const Rect& r, + Pixel pixel, const void* mask_) +{ Rect cr = getRect().intersect(r); if (cr.is_empty()) return; int stride; @@ -190,9 +199,13 @@ void FullFramePixelBuffer::maskRect(const Rect& r, Pixel pixel, const void* mask } mask += maskStride; } + + commitBufferRW(cr); } -void FullFramePixelBuffer::copyRect(const Rect &rect, const Point &move_by_delta) { +void ModifiablePixelBuffer::copyRect(const Rect &rect, + const Point &move_by_delta) +{ int stride; U8* data; unsigned int bytesPerPixel, bytesPerRow, bytesPerMemCpy; @@ -241,8 +254,30 @@ void FullFramePixelBuffer::copyRect(const Rect &rect, const Point &move_by_delta src -= bytesPerRow; } } + commitBufferRW(getRect()); +} + +// -=- Simple pixel buffer with a continuous block of memory + +FullFramePixelBuffer::FullFramePixelBuffer(const PixelFormat& pf, int w, int h, + rdr::U8* data_, int stride_) + : ModifiablePixelBuffer(pf, w, h), data(data_), stride(stride_) +{ } +FullFramePixelBuffer::FullFramePixelBuffer() : data(0) {} + +FullFramePixelBuffer::~FullFramePixelBuffer() {} + +rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_) +{ + *stride_ = stride; + return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8]; +} + +void FullFramePixelBuffer::commitBufferRW(const Rect& r) +{ +} // -=- Managed pixel buffer class // Automatically allocates enough space for the specified format & area diff --git a/common/rfb/PixelBuffer.h b/common/rfb/PixelBuffer.h index 59d71c79..e2cc3e92 100644 --- a/common/rfb/PixelBuffer.h +++ b/common/rfb/PixelBuffer.h @@ -66,7 +66,6 @@ namespace rfb { // The pointer is to the top-left pixel of the specified Rect. // The buffer stride (in pixels) is returned. virtual const rdr::U8* getBuffer(const Rect& r, int* stride) = 0; - virtual rdr::U8* getBufferRW(const Rect& r, int* stride) = 0; // Get pixel data for a given part of the buffer // Data is copied into the supplied buffer, with the specified @@ -89,20 +88,31 @@ namespace rfb { int width_, height_; }; - // FullFramePixelBuffer - - class FullFramePixelBuffer : public PixelBuffer { + // ModifiablePixelBuffer + class ModifiablePixelBuffer : public PixelBuffer { public: - FullFramePixelBuffer(const PixelFormat& pf, int width, int height, - rdr::U8* data, int stride); - virtual ~FullFramePixelBuffer(); + ModifiablePixelBuffer(const PixelFormat& pf, int width, int height); + virtual ~ModifiablePixelBuffer(); - public: - // Get a pointer to specified pixel data + /////////////////////////////////////////////// + // Access to pixel data + // + + // Get a writeable pointer into the buffer + // Like getBuffer(), the pointer is to the top-left pixel of the + // specified Rect and the stride in pixels is returned. + virtual rdr::U8* getBufferRW(const Rect& r, int* stride) = 0; + // Commit the modified contents + // Ensures that the changes to the specified Rect is properly + // stored away and any temporary buffers are freed. The Rect given + // here needs to match the Rect given to the earlier call to + // getBufferRW(). + virtual void commitBufferRW(const Rect& r) = 0; + + // Default trivial handling of read-only access virtual const rdr::U8* getBuffer(const Rect& r, int* stride) { return getBufferRW(r, stride); } - virtual rdr::U8* getBufferRW(const Rect& r, int* stride); /////////////////////////////////////////////// // Basic rendering operations @@ -127,6 +137,22 @@ namespace rfb { // pixel is the Pixel value to be used where mask_ is set void maskRect(const Rect& r, Pixel pixel, const void* mask_); + protected: + ModifiablePixelBuffer(); + }; + + // FullFramePixelBuffer + + class FullFramePixelBuffer : public ModifiablePixelBuffer { + public: + FullFramePixelBuffer(const PixelFormat& pf, int width, int height, + rdr::U8* data_, int stride); + virtual ~FullFramePixelBuffer(); + + public: + virtual rdr::U8* getBufferRW(const Rect& r, int* stride); + virtual void commitBufferRW(const Rect& r); + protected: FullFramePixelBuffer(); diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx index db1a08a5..c78bb891 100644 --- a/vncviewer/CConn.cxx +++ b/vncviewer/CConn.cxx @@ -470,7 +470,7 @@ rdr::U8* CConn::getRawBufferRW(const rfb::Rect& r, int* stride) { return desktop->getBufferRW(r, stride); } void CConn::releaseRawBuffer(const rfb::Rect& r) { - desktop->damageRect(r); + desktop->commitBufferRW(r); } diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx index 3e9b57e6..a64f02a2 100644 --- a/vncviewer/DesktopWindow.cxx +++ b/vncviewer/DesktopWindow.cxx @@ -232,8 +232,8 @@ rdr::U8* DesktopWindow::getBufferRW(const rfb::Rect& r, int* stride) { return viewport->getBufferRW(r, stride); } -void DesktopWindow::damageRect(const rfb::Rect& r) { - viewport->damageRect(r); +void DesktopWindow::commitBufferRW(const rfb::Rect& r) { + viewport->commitBufferRW(r); } diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h index 08a66522..83a8c767 100644 --- a/vncviewer/DesktopWindow.h +++ b/vncviewer/DesktopWindow.h @@ -55,7 +55,7 @@ public: void copyRect(const rfb::Rect& r, int srcX, int srcY); rdr::U8* getBufferRW(const rfb::Rect& r, int* stride); - void damageRect(const rfb::Rect& r); + void commitBufferRW(const rfb::Rect& r); void resizeFramebuffer(int new_w, int new_h); diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx index d1d51622..70964b76 100644 --- a/vncviewer/Viewport.cxx +++ b/vncviewer/Viewport.cxx @@ -229,6 +229,7 @@ void Viewport::imageRect(const rfb::Rect& r, void* pixels) { pixelTrans->translateRect(pixels, r.width(), rfb::Rect(0, 0, r.width(), r.height()), buffer, stride, rfb::Point(0, 0)); + frameBuffer->commitBufferRW(r); } else { frameBuffer->imageRect(r, pixels); } @@ -244,6 +245,11 @@ rdr::U8* Viewport::getBufferRW(const rfb::Rect& r, int* stride) { return frameBuffer->getBufferRW(r, stride); } +void Viewport::commitBufferRW(const rfb::Rect& r) { + frameBuffer->commitBufferRW(r); + damageRect(r); +} + void Viewport::damageRect(const rfb::Rect& r) { damage.assign_union(rfb::Region(r)); if (!Fl::has_timeout(handleUpdateTimeout, this)) diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h index bd17655a..e112efda 100644 --- a/vncviewer/Viewport.h +++ b/vncviewer/Viewport.h @@ -56,8 +56,7 @@ public: void copyRect(const rfb::Rect& r, int srcX, int srcY); rdr::U8* getBufferRW(const rfb::Rect& r, int* stride); - - void damageRect(const rfb::Rect& r); + void commitBufferRW(const rfb::Rect& r); void setCursor(int width, int height, const rfb::Point& hotspot, void* data, void* mask); @@ -72,6 +71,8 @@ public: private: + void damageRect(const rfb::Rect& r); + PlatformPixelBuffer* createFramebuffer(int w, int h); static void handleUpdateTimeout(void *data); diff --git a/win/rfb_win32/DeviceFrameBuffer.cxx b/win/rfb_win32/DeviceFrameBuffer.cxx index 0ad06e9e..d075c259 100644 --- a/win/rfb_win32/DeviceFrameBuffer.cxx +++ b/win/rfb_win32/DeviceFrameBuffer.cxx @@ -220,6 +220,7 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server) } } } + cursorBm.commitBufferRW(cursorBm.getRect()); } // Finally invert the AND mask so it's suitable for RFB and pack it into -- 2.39.5