123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- /* Copyright (C) 2002-2004 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)
- : SimpleUpdateTracker(true), fb(buffer),
- oldFb(fb->getPF(), 0, 0), firstCompare(true)
- {
- changed.assign_union(fb->getRect());
- }
-
- ComparingUpdateTracker::~ComparingUpdateTracker()
- {
- }
-
-
- void ComparingUpdateTracker::flush_update(UpdateInfo* info,
- const Region& cliprgn, int maxArea)
- {
- throw rfb::Exception("flush_update(UpdateInfo*) not implemented");
- }
-
- void ComparingUpdateTracker::flush_update(UpdateTracker &ut,
- const Region &cliprgn)
- {
- throw rfb::Exception("flush_update(UpdateTracker&) not implemented");
- }
-
-
- #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(), min(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, min(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 = min(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 = min(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);
- }
- }
|