diff --git a/ChangeLog b/ChangeLog index 62b29e23..7091d076 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2002-01-10 Tim Jansen + + * krfb/XUpdateScanner.cc: improved finding of hints (join adjacent + hint regions, get rid of unneccessary comparisons) + 2002-01-09 Tim Jansen * Fixed problems with closing dialogs diff --git a/TODO b/TODO index e012824b..5fd9624f 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,5 @@ Todo: +- clip framebuffer updates to requested region! - reminder: enable non-raw in hextile, enable sendSingleHint - i18n - docs diff --git a/krfb/XUpdateScanner.cc b/krfb/XUpdateScanner.cc index 43771eed..9cef1da8 100644 --- a/krfb/XUpdateScanner.cc +++ b/krfb/XUpdateScanner.cc @@ -80,11 +80,11 @@ XUpdateScanner::XUpdateScanner(Display *_dpy, tilesX = (fb->width + tileWidth - 1) / tileWidth; tilesY = (fb->height + tileHeight - 1) / tileHeight; - tileMap = (char*) malloc(tilesX * tilesY); + tileMap = new bool[tilesX * tilesY]; unsigned int i; for (i = 0; i < tilesX * tilesY; i++) - tileMap[i] = 0; + tileMap[i] = false; scanline = XShmCreateImage(dpy, DefaultVisual(dpy, 0), @@ -112,7 +112,7 @@ XUpdateScanner::~XUpdateScanner() XDestroyImage(scanline); shmdt(shminfo_scanline.shmaddr); shmctl(shminfo_scanline.shmid, IPC_RMID, 0); - free(tileMap); + delete tileMap; XShmDetach(dpy, &shminfo_tile); XDestroyImage(tile); shmdt(shminfo_tile.shmaddr); @@ -120,7 +120,7 @@ XUpdateScanner::~XUpdateScanner() } -void XUpdateScanner::checkTile(int x, int y, list &hintList) +void XUpdateScanner::copyTile(int x, int y) { unsigned int maxWidth = fb->width - x; unsigned int maxHeight = fb->height - y; @@ -136,38 +136,152 @@ void XUpdateScanner::checkTile(int x, int y, list &hintList) AllPlanes, ZPixmap, tile, 0, 0); } unsigned int line; - bool changed = false; int pixelsize = fb->pixelFormat.bits_per_pixel >> 3; unsigned char *src = (unsigned char*) tile->data; unsigned char *dest = fb->data + y * fb->bytesPerLine + x * pixelsize; for (line = 0; line < maxHeight; line++) { - if ( changed || memcmp(dest, src, maxWidth * pixelsize) ) { - changed = true; - memcpy(dest, src, maxWidth * pixelsize ); - } + memcpy(dest, src, maxWidth * pixelsize ); src += tile->bytes_per_line; dest += fb->bytesPerLine; } +} - if (changed) { - Hint hint; - hint.type = hintRefresh; +void XUpdateScanner::copyAllTiles() +{ + unsigned int x, y; + // TODO: is it useful to compare again instead of only copying? + for (y = 0; y < tilesY; y++) { + for (x = 0; x < tilesX; x++) { + if (tileMap[x + y * tilesX]) + copyTile(x*tileWidth, y*tileHeight); + } + } + +} + +void XUpdateScanner::initHint(Hint &hint) +{ + hint.type = hintRefresh; + hint.hint.refresh.x = 0; + hint.hint.refresh.y = 0; + hint.hint.refresh.width = 0; + hint.hint.refresh.height = 0; +} + +void XUpdateScanner::createHintFromTile(int x, int y, Hint &hint) +{ + unsigned int w = fb->width - x; + unsigned int h = fb->height - y; + if (w > tileWidth) + w = tileWidth; + if (h > tileHeight) + h = tileHeight; + + hint.hint.refresh.x = x; + hint.hint.refresh.y = y; + hint.hint.refresh.width = w; + hint.hint.refresh.height = h; +} + +void XUpdateScanner::addTileToHint(int x, int y, Hint &hint) +{ + unsigned int w = fb->width - x; + unsigned int h = fb->height - y; + if (w > tileWidth) + w = tileWidth; + if (h > tileHeight) + h = tileHeight; + + if (hint.hint.refresh.x > x) { + hint.hint.refresh.width += hint.hint.refresh.x - x; hint.hint.refresh.x = x; + } + + if (hint.hint.refresh.y > y) { + hint.hint.refresh.height += hint.hint.refresh.y - y; hint.hint.refresh.y = y; - hint.hint.refresh.width = maxWidth; - hint.hint.refresh.height = maxHeight; - hintList.push_back(hint); + } + + if ((hint.hint.refresh.x+hint.hint.refresh.width) < (x+w)) { + hint.hint.refresh.width = (x+w) - hint.hint.refresh.x; + } + + if ((hint.hint.refresh.y+hint.hint.refresh.height) < (y+h)) { + hint.hint.refresh.height = (y+h) - hint.hint.refresh.y; + } +} + +void XUpdateScanner::flushHint(int x, int y, int &x0, + Hint &hint, list &hintList) +{ + if (x0 < 0) + return; + + int h = 1; + for (int i = y+1; i < tilesY; i++) { + bool lk = true; + for (int j = x0; j < x; j++) { + if (!tileMap[j + i * tilesX]) { + lk = false; + break; + } + } + if (!lk) + break; + + for (int j = x0; j < x; j++) + tileMap[j + i * tilesX] = false; + h++; + } + + hint.hint.refresh.height = h * tileHeight; + if ((hint.hint.refresh.y + hint.hint.refresh.height) > fb->height) + hint.hint.refresh.height = fb->height - hint.hint.refresh.y; + + x0 = -1; + + hintList.push_back(hint); + initHint(hint); +} + +void XUpdateScanner::createHints(list &hintList) +{ + Hint hint; + initHint(hint); + int x0 = -1; + + for (int y = 0; y < tilesY; y++) { + int x; + for (x = 0; x < tilesX; x++) { + if (tileMap[x + y * tilesX]) { + if (x0 < 0) { + createHintFromTile(x * tileWidth, + y * tileHeight, + hint); + x0 = x; + } + else + addTileToHint(x * tileWidth, + y * tileHeight, + hint); + } + else + flushHint(x, y, x0, hint, hintList); + } + flushHint(x, y, x0, hint, hintList); } } void XUpdateScanner::searchUpdates(list &hintList) { + count++; count %= 32; + unsigned int i; unsigned int x, y; for (i = 0; i < (tilesX * tilesY); i++) { - tileMap[i] = 0; + tileMap[i] = false; } y = scanlines[count]; @@ -180,24 +294,18 @@ void XUpdateScanner::searchUpdates(list &hintList) x * pixelsize; unsigned char *dest = fb->data + y * fb->bytesPerLine + x * pixelsize; - if (memcmp(dest, src, 32 * pixelsize)) { + int w = (x + 32) > fb->width ? (fb->width-x) : 32; + if (memcmp(dest, src, w * pixelsize)) tileMap[(x / tileWidth) + - (y / tileHeight) * tilesX] = 1; - } + (y / tileHeight) * tilesX] = true; x += 32; } y += 32; } - for (y = 0; y < tilesY; y++) { - for (x = 0; x < tilesX; x++) { - if (tileMap[x + y * tilesX] > 0) - checkTile(x*tileWidth, y*tileHeight, - hintList); - } - } + copyAllTiles(); - count++; + createHints(hintList); } } // namespace rfb diff --git a/krfb/XUpdateScanner.h b/krfb/XUpdateScanner.h index 452e7829..ccf1e522 100644 --- a/krfb/XUpdateScanner.h +++ b/krfb/XUpdateScanner.h @@ -43,9 +43,14 @@ class XUpdateScanner ~XUpdateScanner(); - void checkTile( int x, int y, list< Hint > &hintList ); + void copyTile( int x, int y); + void copyAllTiles(); void searchUpdates( list< Hint > &hintList); - + void initHint(Hint &hint); + void flushHint(int x, int y, int &x0, Hint &hint, list &hintList); + void createHints(list &hintList); + void addTileToHint(int x, int y, Hint &hint); + void createHintFromTile(int x, int y, Hint &hint); Display *dpy; Window window; @@ -60,7 +65,7 @@ class XUpdateScanner XShmSegmentInfo shminfo_tile; unsigned int tilesX, tilesY; - char *tileMap; + bool *tileMap; };