1
0
mirror of https://github.com/KDE/krfb synced 2026-07-01 07:41:17 -07:00

prepared for limited horizontal joining and half-tiles

svn path=/trunk/kdenetwork/krfb/; revision=137536
This commit is contained in:
Tim Jansen
2002-02-20 00:24:52 +00:00
parent e7df26c898
commit a4a09d9091
3 changed files with 192 additions and 66 deletions

View File

@@ -4,6 +4,8 @@
first time (did not create share/krfb dir for eventrc)
* krfb/xupdatescanner.cc: improved scanning algorithm and renamed the file.
It now calculates the correct height of tiles and only joins them
if it wouldn't include too many unused pixels.
Result seems to be a reduction between 25% (web browsing) and 40% (text
editing) of transmitted raw data. Note that the effectiveness of some
encoders decreases with less adjacent regions, so the real reduction is

View File

@@ -21,6 +21,7 @@
* December 15th 2001: removed coments, mouse pointer options and some
* other stuff
* January 10th 2002: improved hint creation (join adjacent hints)
* February 20th 2002: shrink tiles to match actual changes
*
* Tim Jansen <tim@tjansen.de>
*/
@@ -38,14 +39,14 @@
#include "xupdatescanner.h"
unsigned int scanlines[32] = { 0, 16, 8, 24,
4, 20, 12, 28,
10, 26, 18, 2,
22, 6, 30, 14,
1, 17, 9, 25,
7, 23, 15, 31,
19, 3, 27, 11,
29, 13, 5, 21 };
int scanlines[32] = { 0, 16, 8, 24,
4, 20, 12, 28,
10, 26, 18, 2,
22, 6, 30, 14,
1, 17, 9, 25,
7, 23, 15, 31,
19, 3, 27, 11,
29, 13, 5, 21 };
#define MAX_ADJ_TOLERANCE 8
XUpdateScanner::XUpdateScanner(Display *_dpy,
@@ -93,8 +94,7 @@ XUpdateScanner::XUpdateScanner(Display *_dpy,
tileMap = new bool[tilesX * tilesY];
tileRegionMap = new struct TileChangeRegion[tilesX * tilesY];
unsigned int i;
for (i = 0; i < tilesX * tilesY; i++)
for (int i = 0; i < tilesX * tilesY; i++)
tileMap[i] = false;
scanline = XShmCreateImage(dpy,
@@ -131,11 +131,88 @@ XUpdateScanner::~XUpdateScanner()
shmctl(shminfo_tile.shmid, IPC_RMID, 0);
}
bool XUpdateScanner::checkRight(unsigned char *src,
unsigned char *dest,
int halfWidthBytes)
{
return memcmp(dest + halfWidthBytes,
src + halfWidthBytes,
halfWidthBytes) != 0;
}
bool XUpdateScanner::checkSide(unsigned char *src,
unsigned char *dest,
int halfWidthBytes,
int n)
{
for (int i = 0; i < n; i++) {
if (memcmp(dest + halfWidthBytes,
src + halfWidthBytes,
halfWidthBytes))
return true;
src += tile->bytes_per_line;
dest += bytesPerLine;
}
return false;
}
int XUpdateScanner::findFirstLine(int maxHeight,
unsigned char *&ssrc,
unsigned char *&sdest,
int halfWidthBytes,
bool &left) {
int firstLine = maxHeight;
left = true;
for (int line = 0; line < maxHeight; line++) {
if (memcmp(sdest, ssrc, halfWidthBytes)) {
firstLine = line;
break;
}
if (memcmp(sdest + halfWidthBytes,
ssrc + halfWidthBytes,
halfWidthBytes)) {
firstLine = line;
left = false;
break;
}
ssrc += tile->bytes_per_line;
sdest += bytesPerLine;
}
return firstLine;
}
int XUpdateScanner::findLastLine(int maxHeight,
int firstLine,
unsigned char *msrc,
unsigned char *mdest,
int halfWidthBytes,
bool &left) {
int lastLine = firstLine;
left = true;
for (int line = maxHeight-1; line > firstLine; line--) {
msrc -= tile->bytes_per_line;
mdest -= bytesPerLine;
if (memcmp(mdest, msrc, halfWidthBytes)) {
lastLine = line;
break;
}
if (memcmp(mdest + halfWidthBytes,
msrc + halfWidthBytes,
halfWidthBytes)) {
lastLine = line;
left = false;
break;
}
}
return lastLine;
}
bool XUpdateScanner::copyTile(int x, int y, int tx, int ty)
{
unsigned int maxWidth = width - x;
unsigned int maxHeight = height - y;
int maxWidth = width - x;
int maxHeight = height - y;
if (maxWidth > tileWidth)
maxWidth = tileWidth;
if (maxHeight > tileHeight)
@@ -147,44 +224,68 @@ bool XUpdateScanner::copyTile(int x, int y, int tx, int ty)
XGetSubImage(dpy, window, x, y, maxWidth, maxHeight,
AllPlanes, ZPixmap, tile, 0, 0);
}
unsigned int line;
int pixelsize = bitsPerPixel >> 3;
int halfWidthBytes = (maxWidth*pixelsize)>>1;
bool hitLeft = true;
bool leftConfirmed = false;
bool rightConfirmed = false;
unsigned char *src = (unsigned char*) tile->data;
unsigned char *dest = fb + y * bytesPerLine + x * pixelsize;
unsigned char *ssrc = src;
unsigned char *sdest = dest;
int firstLine = maxHeight;
for (line = 0; line < maxHeight; line++) {
if (memcmp(sdest, ssrc, maxWidth * pixelsize)) {
firstLine = line;
break;
}
ssrc += tile->bytes_per_line;
sdest += bytesPerLine;
}
int firstLine = findFirstLine(maxHeight, ssrc, sdest,
halfWidthBytes, hitLeft);
if (firstLine == maxHeight) {
tileMap[tx + ty * tilesX] = false;
return false;
}
if (hitLeft) {
leftConfirmed = true;
rightConfirmed = checkRight(ssrc, sdest, halfWidthBytes);
}
else
rightConfirmed = true;
unsigned char *msrc = src + (tile->bytes_per_line * maxHeight);
unsigned char *mdest = dest + (bytesPerLine * maxHeight);
int lastLine = firstLine;
int lastLine = findLastLine(maxHeight, firstLine, msrc, mdest,
halfWidthBytes, hitLeft);
if (hitLeft) {
leftConfirmed = true;
if (!rightConfirmed)
rightConfirmed = checkRight(ssrc, sdest, halfWidthBytes);
}
else
rightConfirmed = true;
for (line = maxHeight-1; line > firstLine; line--) {
msrc -= tile->bytes_per_line;
mdest -= bytesPerLine;
if (memcmp(mdest, msrc, maxWidth * pixelsize)) {
lastLine = line;
break;
}
}
if (!leftConfirmed)
leftConfirmed = checkSide(sdest, ssrc, halfWidthBytes,
lastLine-firstLine+1);
if (!rightConfirmed)
rightConfirmed = checkSide(sdest+halfWidthBytes,
ssrc+halfWidthBytes,
halfWidthBytes,
lastLine-firstLine+1);
for (line = firstLine; line <= lastLine; line++) {
memcpy(sdest, ssrc, maxWidth * pixelsize );
int cw;
if (leftConfirmed && rightConfirmed)
cw = maxWidth * pixelsize;
else {
cw = halfWidthBytes;
if (rightConfirmed) {
sdest += halfWidthBytes;
ssrc += halfWidthBytes;
}
else
assert(leftConfirmed);
}
for (int line = firstLine; line <= lastLine; line++) {
memcpy(sdest, ssrc, cw);
ssrc += tile->bytes_per_line;
sdest += bytesPerLine;
}
@@ -192,14 +293,16 @@ bool XUpdateScanner::copyTile(int x, int y, int tx, int ty)
struct TileChangeRegion *r = &tileRegionMap[tx + (ty * tilesX)];
r->firstLine = firstLine;
r->lastLine = lastLine;
r->leftSide = leftConfirmed;
r->rightSide = rightConfirmed;
return lastLine == (maxHeight-1);
}
void XUpdateScanner::copyAllTiles()
{
for (unsigned int y = 0; y < tilesY; y++) {
for (unsigned int x = 0; x < tilesX; x++) {
for (int y = 0; y < tilesY; y++) {
for (int x = 0; x < tilesX; x++) {
if (tileMap[x + y * tilesX])
if (copyTile(x*tileWidth, y*tileHeight, x, y) &&
((y+1) < tilesY))
@@ -211,8 +314,8 @@ void XUpdateScanner::copyAllTiles()
void XUpdateScanner::createHintFromTile(int x, int y, int th, Hint &hint)
{
unsigned int w = width - x;
unsigned int h = height - y;
int w = width - x;
int h = height - y;
if (w > tileWidth)
w = tileWidth;
if (h > th)
@@ -224,11 +327,11 @@ void XUpdateScanner::createHintFromTile(int x, int y, int th, Hint &hint)
hint.h = h;
}
void XUpdateScanner::addTileToHint(int x, int y, int th, Hint &hint)
bool XUpdateScanner::addTileToHint(int x, int y, int x0, int th, Hint &hint)
{
// todo: refuse to add hint if this one is much smaller or bigger (use x0)
unsigned int w = width - x;
unsigned int h = height - y;
int w = width - x;
int h = height - y;
if (w > tileWidth)
w = tileWidth;
if (h > th)
@@ -251,6 +354,7 @@ void XUpdateScanner::addTileToHint(int x, int y, int th, Hint &hint)
if ((hint.y+hint.h) < (y+h)) {
hint.h = (y+h) - hint.y;
}
return true;
}
void XUpdateScanner::extendHintY(int x, int y, int x0, Hint &hint)
@@ -327,7 +431,7 @@ void XUpdateScanner::flushHint(int x, int y, int &x0,
assert (hint.w > 0);
assert (hint.h > 0);
//printStatistics(hint);
printStatistics(hint);
hintList.append(new Hint(hint));
}
@@ -341,25 +445,33 @@ void XUpdateScanner::createHints(QPtrList<Hint> &hintList)
int x;
for (x = 0; x < tilesX; x++) {
int idx = x + y * tilesX;
if (tileMap[idx]) {
int ty = tileRegionMap[idx].firstLine;
int th = tileRegionMap[idx].lastLine - ty +1;
if (x0 < 0) {
createHintFromTile(x * tileWidth,
(y * tileHeight) + ty,
th,
hint);
x0 = x;
}
else {
addTileToHint(x * tileWidth,
(y * tileHeight) + ty,
th,
hint);
}
}
else
if (!tileMap[idx]) {
flushHint(x, y, x0, hint, hintList);
continue;
}
int ty = tileRegionMap[idx].firstLine;
int th = tileRegionMap[idx].lastLine - ty +1;
if (x0 < 0) {
createHintFromTile(x * tileWidth,
(y * tileHeight) + ty,
th,
hint);
x0 = x;
continue;
}
if (!addTileToHint(x * tileWidth,
(y * tileHeight) + ty,
x0,
th,
hint)) {
flushHint(x, y, x0, hint, hintList);
createHintFromTile(x * tileWidth,
(y * tileHeight) + ty,
th,
hint);
x0 = x;
}
}
flushHint(x, y, x0, hint, hintList);
}
@@ -370,8 +482,8 @@ void XUpdateScanner::searchUpdates(QPtrList<Hint> &hintList)
count++;
count %= 32;
unsigned int i;
unsigned int x, y;
int i;
int x, y;
for (i = 0; i < (tilesX * tilesY); i++) {
tileMap[i] = false;

View File

@@ -59,6 +59,7 @@ class Hint {
struct TileChangeRegion {
short firstLine, lastLine;
bool leftSide, rightSide;
};
@@ -83,17 +84,28 @@ class XUpdateScanner
void flushHint(int x, int y, int &x0, Hint &hint,
QPtrList<Hint> &hintList);
void createHints(QPtrList<Hint> &hintList);
void addTileToHint(int x, int y, int th, Hint &hint);
bool addTileToHint(int x, int y, int x0, int th, Hint &hint);
void createHintFromTile(int x, int y, int th, Hint &hint);
void extendHintY(int x, int y, int x0, Hint &h);
int findFirstLine(int maxH, unsigned char *&ssrc,
unsigned char *&sdest, int halfWidthBytes,
bool &left);
int findLastLine(int maxH, int firstL, unsigned char *msrc,
unsigned char *mdest, int halfWidthBytes,
bool &left);
bool checkRight(unsigned char *src,
unsigned char *dest,
int halfWidthBytes);
bool checkSide(unsigned char *src, unsigned char *dest,
int halfWidthBytes, int n);
Display *dpy;
Window window;
unsigned char *fb;
int width, height;
int bitsPerPixel, bytesPerLine;
unsigned int tileWidth, tileHeight;
unsigned int count;
int tileWidth, tileHeight;
int count;
XImage *scanline;
XShmSegmentInfo shminfo_scanline;
@@ -101,7 +113,7 @@ class XUpdateScanner
XImage *tile;
XShmSegmentInfo shminfo_tile;
unsigned int tilesX, tilesY;
int tilesX, tilesY;
bool *tileMap;
struct TileChangeRegion *tileRegionMap;
};