Migrating to new directory structure adopted from the RealVNC's source tree. More changes will follow.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@589 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/ComparingUpdateTracker.cxx b/common/rfb/ComparingUpdateTracker.cxx
new file mode 100644
index 0000000..ce3d68a
--- /dev/null
+++ b/common/rfb/ComparingUpdateTracker.cxx
@@ -0,0 +1,137 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#include <stdio.h>
+#include <vector>
+#include <rdr/types.h>
+#include <rfb/Exception.h>
+#include <rfb/ComparingUpdateTracker.h>
+
+using namespace rfb;
+
+ComparingUpdateTracker::ComparingUpdateTracker(PixelBuffer* buffer)
+ : fb(buffer), oldFb(fb->getPF(), 0, 0), firstCompare(true)
+{
+ changed.assign_union(fb->getRect());
+}
+
+ComparingUpdateTracker::~ComparingUpdateTracker()
+{
+}
+
+
+#define BLOCK_SIZE 16
+
+void ComparingUpdateTracker::compare()
+{
+ std::vector<Rect> rects;
+ std::vector<Rect>::iterator i;
+
+ if (firstCompare) {
+ // NB: We leave the change region untouched on this iteration,
+ // since in effect the entire framebuffer has changed.
+ oldFb.setSize(fb->width(), fb->height());
+ for (int y=0; y<fb->height(); y+=BLOCK_SIZE) {
+ Rect pos(0, y, fb->width(), __rfbmin(fb->height(), y+BLOCK_SIZE));
+ int srcStride;
+ const rdr::U8* srcData = fb->getPixelsR(pos, &srcStride);
+ oldFb.imageRect(pos, srcData, srcStride);
+ }
+ firstCompare = false;
+ } else {
+ copied.get_rects(&rects, copy_delta.x<=0, copy_delta.y<=0);
+ for (i = rects.begin(); i != rects.end(); i++)
+ oldFb.copyRect(*i, copy_delta);
+
+ Region to_check = changed.union_(copied);
+ to_check.get_rects(&rects);
+
+ Region newChanged;
+ for (i = rects.begin(); i != rects.end(); i++)
+ compareRect(*i, &newChanged);
+
+ copied.assign_subtract(newChanged);
+ changed = newChanged;
+ }
+}
+
+void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged)
+{
+ if (!r.enclosed_by(fb->getRect())) {
+ fprintf(stderr,"ComparingUpdateTracker: rect outside fb (%d,%d-%d,%d)\n", r.tl.x, r.tl.y, r.br.x, r.br.y);
+ return;
+ }
+
+ int bytesPerPixel = fb->getPF().bpp/8;
+ int oldStride;
+ rdr::U8* oldData = oldFb.getPixelsRW(r, &oldStride);
+ int oldStrideBytes = oldStride * bytesPerPixel;
+
+ std::vector<Rect> changedBlocks;
+
+ for (int blockTop = r.tl.y; blockTop < r.br.y; blockTop += BLOCK_SIZE)
+ {
+ // Get a strip of the source buffer
+ Rect pos(r.tl.x, blockTop, r.br.x, __rfbmin(r.br.y, blockTop+BLOCK_SIZE));
+ int fbStride;
+ const rdr::U8* newBlockPtr = fb->getPixelsR(pos, &fbStride);
+ int newStrideBytes = fbStride * bytesPerPixel;
+
+ rdr::U8* oldBlockPtr = oldData;
+ int blockBottom = __rfbmin(blockTop+BLOCK_SIZE, r.br.y);
+
+ for (int blockLeft = r.tl.x; blockLeft < r.br.x; blockLeft += BLOCK_SIZE)
+ {
+ const rdr::U8* newPtr = newBlockPtr;
+ rdr::U8* oldPtr = oldBlockPtr;
+
+ int blockRight = __rfbmin(blockLeft+BLOCK_SIZE, r.br.x);
+ int blockWidthInBytes = (blockRight-blockLeft) * bytesPerPixel;
+
+ for (int y = blockTop; y < blockBottom; y++)
+ {
+ if (memcmp(oldPtr, newPtr, blockWidthInBytes) != 0)
+ {
+ // A block has changed - copy the remainder to the oldFb
+ changedBlocks.push_back(Rect(blockLeft, blockTop,
+ blockRight, blockBottom));
+ for (int y2 = y; y2 < blockBottom; y2++)
+ {
+ memcpy(oldPtr, newPtr, blockWidthInBytes);
+ newPtr += newStrideBytes;
+ oldPtr += oldStrideBytes;
+ }
+ break;
+ }
+
+ newPtr += newStrideBytes;
+ oldPtr += oldStrideBytes;
+ }
+
+ oldBlockPtr += blockWidthInBytes;
+ newBlockPtr += blockWidthInBytes;
+ }
+
+ oldData += oldStrideBytes * BLOCK_SIZE;
+ }
+
+ if (!changedBlocks.empty()) {
+ Region temp;
+ temp.setOrderedRects(changedBlocks);
+ newChanged->assign_union(temp);
+ }
+}