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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user