"Fossies" - the Fresh Open Source Software Archive

Member "tvnserver-2.0.4/desktop/UpdateFilter.cpp" (3 Aug 2011, 8534 Bytes) of archive /windows/misc/tvnserver-2.0.4-src.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "UpdateFilter.cpp" see the Fossies "Dox" file reference documentation.

    1 // Copyright (C) 2008, 2009, 2010 GlavSoft LLC.
    2 // All rights reserved.
    3 //
    4 //-------------------------------------------------------------------------
    5 // This file is part of the TightVNC software.  Please visit our Web site:
    6 //
    7 //                       http://www.tightvnc.com/
    8 //
    9 // This program is free software; you can redistribute it and/or modify
   10 // it under the terms of the GNU General Public License as published by
   11 // the Free Software Foundation; either version 2 of the License, or
   12 // (at your option) any later version.
   13 //
   14 // This program is distributed in the hope that it will be useful,
   15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
   16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17 // GNU General Public License for more details.
   18 //
   19 // You should have received a copy of the GNU General Public License along
   20 // with this program; if not, write to the Free Software Foundation, Inc.,
   21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   22 //-------------------------------------------------------------------------
   23 //
   24 
   25 #include "UpdateFilter.h"
   26 #include "util/Log.h"
   27 #include "util/CommonHeader.h"
   28 
   29 static const int BLOCK_SIZE = 32;
   30 
   31 UpdateFilter::UpdateFilter(ScreenGrabber *screenGrabber,
   32                            FrameBuffer *frameBuffer,
   33                            LocalMutex *frameBufferCriticalSection)
   34 : m_screenGrabber(screenGrabber),
   35   m_frameBuffer(frameBuffer),
   36   m_fbMutex(frameBufferCriticalSection)
   37 {
   38 }
   39 
   40 UpdateFilter::~UpdateFilter(void)
   41 {
   42 }
   43 
   44 void UpdateFilter::filter(UpdateContainer *updateContainer)
   45 {
   46   AutoLock al(m_fbMutex);
   47 
   48   FrameBuffer *screenFrameBuffer = m_screenGrabber->getScreenBuffer();
   49 
   50   if (!screenFrameBuffer->isEqualTo(m_frameBuffer)) {
   51     return;
   52   }
   53 
   54   Region toCheck = updateContainer->changedRegion;
   55   toCheck.add(&updateContainer->copiedRegion);
   56   toCheck.add(&updateContainer->videoRegion);
   57 
   58   std::vector<Rect> rects;
   59   std::vector<Rect>::iterator iRect;
   60 
   61   updateContainer->copiedRegion.getRectVector(&rects);
   62   Point *src = &updateContainer->copySrc;
   63   for (iRect = rects.begin(); iRect < rects.end(); iRect++) {
   64     m_frameBuffer->move(&(*iRect), src->x, src->y);
   65   }
   66 
   67   toCheck.getRectVector(&rects);
   68 
   69   Log::debug(_T("grabbing region, %d rectangles"), (int)rects.size());
   70   for (iRect = rects.begin(); iRect < rects.end(); iRect++) {
   71     if (!m_screenGrabber->grab(&(*iRect))) {
   72       return;
   73     }
   74   }
   75   Log::debug(_T("end of grabbing region"));
   76 
   77   updateContainer->changedRegion.clear();
   78   Rect *rect;
   79   for (iRect = rects.begin(); iRect < rects.end(); iRect++) {
   80     rect = &(*iRect);
   81     getChangedRegion(&updateContainer->changedRegion, rect);
   82   }
   83 
   84   updateContainer->changedRegion.getRectVector(&rects);
   85   for (iRect = rects.begin(); iRect < rects.end(); iRect++) {
   86     rect = &(*iRect);
   87     m_frameBuffer->copyFrom(rect, screenFrameBuffer, rect->left, rect->top);
   88   }
   89 }
   90 
   91 void UpdateFilter::getChangedRegion(Region *rgn, const Rect *rect)
   92 {
   93   
   94   const UINT bytesPerPixel = m_frameBuffer->getBytesPerPixel();
   95   const int bytes_per_scanline = (rect->right - rect->left) * bytesPerPixel;
   96 
   97   const int bytesPerRow = m_frameBuffer->getBytesPerRow();
   98   const int offset = rect->top * bytesPerRow + rect->left * bytesPerPixel;
   99   unsigned char *o_ptr = (unsigned char *)m_frameBuffer->getBuffer() + offset;
  100   unsigned char *n_ptr = (unsigned char *)m_screenGrabber->getScreenBuffer()->getBuffer() + offset;
  101 
  102   Rect new_rect = rect;
  103 
  104   if ( rect->right - rect->left <= BLOCK_SIZE &&
  105        rect->bottom - rect->top <= BLOCK_SIZE ) {
  106       for (int y = rect->top; y < rect->bottom; y++) {
  107         if (memcmp(o_ptr, n_ptr, bytes_per_scanline) != 0) {
  108           new_rect.top = y;
  109           updateChangedSubRect(rgn, &new_rect);
  110           break;
  111         }
  112         o_ptr += bytesPerRow;
  113         n_ptr += bytesPerRow;
  114       }
  115       return;
  116   }
  117 
  118   new_rect.top = -1;
  119   for (int y = rect->top; y < rect->bottom; y++) {
  120     if (memcmp(o_ptr, n_ptr, bytes_per_scanline) != 0) {
  121       if (new_rect.top == -1) {
  122         new_rect.top = y;
  123       }
  124       int n = BLOCK_SIZE / 2 - 1;
  125       y += n;
  126       o_ptr += n * bytesPerRow;
  127       n_ptr += n * bytesPerRow;
  128     } else {
  129       if (new_rect.top != -1) {
  130         new_rect.bottom = y;
  131         updateChangedRect(rgn, &new_rect);
  132         new_rect.top = -1;
  133       }
  134     }
  135     o_ptr += bytesPerRow;
  136     n_ptr += bytesPerRow;
  137   }
  138   if (new_rect.top != -1) {
  139     new_rect.bottom = rect->bottom;
  140     updateChangedRect(rgn, &new_rect);
  141   }
  142 }
  143 
  144 void UpdateFilter::updateChangedRect(Region *rgn, const Rect *rect)
  145 {
  146   if ( rect->right - rect->left <= BLOCK_SIZE &&
  147        rect->bottom - rect->top <= BLOCK_SIZE ) {
  148       updateChangedSubRect(rgn, rect);
  149       return;
  150   }
  151 
  152   const UINT bytesPerPixel = m_frameBuffer->getBytesPerPixel();
  153 
  154   Rect new_rect;
  155   int x, y, ay;
  156 
  157   const int bytesPerRow = m_frameBuffer->getBytesPerRow();
  158   const int offset = rect->top * bytesPerRow + rect->left * bytesPerPixel;
  159   unsigned char *o_topleft_ptr = (unsigned char *)m_frameBuffer->getBuffer() + offset;
  160   unsigned char *n_topleft_ptr = (unsigned char *)m_screenGrabber->getScreenBuffer()->getBuffer() + offset;
  161 
  162   for (y = rect->top; y < rect->bottom; y += BLOCK_SIZE)
  163   {
  164     unsigned char *o_row_ptr = o_topleft_ptr;
  165     unsigned char *n_row_ptr = n_topleft_ptr;
  166 
  167     const int blockbottom = min(y + BLOCK_SIZE, rect->bottom);
  168     new_rect.bottom = blockbottom;
  169     new_rect.left = -1;
  170 
  171     for (x = rect->left; x < rect->right; x += BLOCK_SIZE)
  172     {
  173       unsigned char *n_block_ptr = n_row_ptr;
  174       unsigned char *o_block_ptr = o_row_ptr;
  175 
  176       const UINT blockright = min(x + BLOCK_SIZE, rect->right);
  177       const UINT bytesPerBlockRow = (blockright-x) * bytesPerPixel;
  178 
  179       for (ay = y; ay < blockbottom; ay++) {
  180         if (memcmp(n_block_ptr, o_block_ptr, bytesPerBlockRow) != 0)
  181           break;
  182         n_block_ptr += bytesPerRow;
  183         o_block_ptr += bytesPerRow;
  184       }
  185       if (ay < blockbottom) {
  186         if (new_rect.left == -1) {
  187           new_rect.left = x;
  188           new_rect.top = ay;
  189         } else if (ay < new_rect.top) {
  190           new_rect.top = ay;
  191         }
  192       } else {
  193         if (new_rect.left != -1) {
  194           new_rect.right = x;
  195           updateChangedSubRect(rgn, &new_rect);
  196           new_rect.left = -1;
  197         }
  198       }
  199 
  200       o_row_ptr += bytesPerBlockRow;
  201       n_row_ptr += bytesPerBlockRow;
  202     }
  203 
  204     if (new_rect.left != -1) {
  205       new_rect.right = rect->right;
  206       updateChangedSubRect(rgn, &new_rect);
  207     }
  208 
  209     o_topleft_ptr += bytesPerRow * BLOCK_SIZE;
  210     n_topleft_ptr += bytesPerRow * BLOCK_SIZE;
  211   }
  212 }
  213 
  214 void UpdateFilter::updateChangedSubRect(Region *rgn, const Rect *rect)
  215 {
  216   const UINT bytesPerPixel = m_frameBuffer->getBytesPerPixel();
  217   int bytes_in_row = (rect->right - rect->left) * bytesPerPixel;
  218   int y, i;
  219 
  220   const int bytesPerRow = m_frameBuffer->getBytesPerRow();
  221   int offset = (rect->bottom - 1) * bytesPerRow + rect->left * bytesPerPixel;
  222   unsigned char *o_ptr = (unsigned char *)m_frameBuffer->getBuffer() + offset;
  223   unsigned char *n_ptr = (unsigned char *)m_screenGrabber->getScreenBuffer()->getBuffer() + offset;
  224   Rect final_rect = rect;
  225   final_rect.bottom = rect->top + 1;
  226   for (y = rect->bottom - 1; y > rect->top; y--) {
  227     if (memcmp(o_ptr, n_ptr, bytes_in_row) != 0) {
  228       final_rect.bottom = y + 1;
  229       break;
  230     }
  231     n_ptr -= bytesPerRow;
  232     o_ptr -= bytesPerRow;
  233   }
  234 
  235   offset = final_rect.top * bytesPerRow + final_rect.left * bytesPerPixel;
  236   o_ptr = (unsigned char *)m_frameBuffer->getBuffer() + offset;
  237   n_ptr = (unsigned char *)m_screenGrabber->getScreenBuffer()->getBuffer() + offset;
  238   int left_delta = bytes_in_row - 1;
  239   int right_delta = 0;
  240   for (y = final_rect.top; y < final_rect.bottom; y++) {
  241     for (i = 0; i < bytes_in_row - 1; i++) {
  242       if (n_ptr[i] != o_ptr[i]) {
  243         if (i < left_delta)
  244           left_delta = i;
  245         break;
  246       }
  247     }
  248     for (i = bytes_in_row - 1; i > 0; i--) {
  249       if (n_ptr[i] != o_ptr[i]) {
  250         if (i > right_delta)
  251           right_delta = i;
  252         break;
  253       }
  254     }
  255     n_ptr += bytesPerRow;
  256     o_ptr += bytesPerRow;
  257   }
  258   final_rect.right = final_rect.left + right_delta / bytesPerPixel + 1;
  259   final_rect.left += left_delta / bytesPerPixel;
  260 
  261   rgn->addRect(&final_rect);
  262 }