x11vnc: -8to24 now works on default depth 8 displays.

pull/1/head
runge 19 years ago
parent e38c3c224b
commit 17e6b6a2bf

@ -6,13 +6,20 @@
#include "win_utils.h" #include "win_utils.h"
int multivis_count = 0; int multivis_count = 0;
int multivis_24count = 0;
void check_for_multivis(void); void check_for_multivis(void);
void bpp8to24(int, int, int, int); void bpp8to24(int, int, int, int);
void mark_8bpp(void); void mark_8bpp(void);
static void set_root_cmap(void);
static void check_pointer_in_depth24(void);
static int check_depth(Window win, Window top, int doall); static int check_depth(Window win, Window top, int doall);
static int check_depth_win(Window win, Window top, XWindowAttributes attr); static int check_depth_win(Window win, Window top, XWindowAttributes attr);
static int get_8pp_region(sraRegionPtr region8bpp, sraRegionPtr rect,
int validate);
static int get_cmap(int j, Colormap cmap);
static void do_8bpp_region(sraRect rect);
/* struct for keeping info about the 8bpp windows: */ /* struct for keeping info about the 8bpp windows: */
typedef struct window8 { typedef struct window8 {
@ -27,12 +34,69 @@ typedef struct window8 {
int fetched; int fetched;
} window8bpp_t; } window8bpp_t;
static Colormap root_cmap = 0;
static void set_root_cmap(void) {
static time_t last_set = 0;
time_t now = time(0);
XWindowAttributes attr;
if (now > last_set + 5) {
root_cmap = 0;
}
if (! root_cmap) {
if (valid_window(window, &attr, 1)) {
last_set = now;
root_cmap = attr.colormap;
}
}
}
/* fixed size array. Will primarily hold visible 8bpp windows */ /* fixed size array. Will primarily hold visible 8bpp windows */
#define MAX_8BPP_WINDOWS 64 #define MAX_8BPP_WINDOWS 64
static window8bpp_t windows_8bpp[MAX_8BPP_WINDOWS]; static window8bpp_t windows_8bpp[MAX_8BPP_WINDOWS];
static int db24 = 0; static int db24 = 0;
static int xgetimage_8to24 = 0; static int xgetimage_8to24 = 0;
static int do_hibits = 0;
static void check_pointer_in_depth24(void) {
int tries = 0, in_24 = 0;
XWindowAttributes attr;
Window c, w;
double now = dnow();
c = window;
if (now > last_keyboard_time + 1.0 && now > last_pointer_time + 1.0) {
return;
}
X_LOCK;
while (c && tries++ < 3) {
c = query_pointer(c);
if (valid_window(c, &attr, 1)) {
if (attr.depth == 24) {
in_24 = 1;
break;
}
}
}
X_UNLOCK;
if (in_24) {
int x1, y1, x2, y2;
X_LOCK;
xtranslate(c, window, 0, 0, &x1, &y1, &w, 1);
X_UNLOCK;
x2 = x1 + attr.width;
y2 = y1 + attr.height;
x1 = nfix(x1, dpy_x);
y1 = nfix(y1, dpy_y);
x2 = nfix(x2, dpy_x);
y2 = nfix(y2, dpy_y);
if (db24 > 1) fprintf(stderr, "check_pointer_in_depth24 %d %d %d %d\n", x1, y1, x2, y2);
mark_rect_as_modified(x1, y1, x2, y2, 0);
}
}
void check_for_multivis(void) { void check_for_multivis(void) {
XWindowAttributes attr; XWindowAttributes attr;
@ -61,9 +125,13 @@ void check_for_multivis(void) {
if (getenv("XGETIMAGE_8TO24") != NULL) { if (getenv("XGETIMAGE_8TO24") != NULL) {
xgetimage_8to24 = 1; xgetimage_8to24 = 1;
} }
if (getenv("HIGHBITS_8TO24") != NULL) {
do_hibits = 1;
}
first = 0; first = 0;
doall = 1; /* fetch everything first time */ doall = 1; /* fetch everything first time */
} }
set_root_cmap();
/* /*
* allocate an "old stack" list of all toplevels. we compare * allocate an "old stack" list of all toplevels. we compare
@ -117,9 +185,17 @@ void check_for_multivis(void) {
if (diff && multivis_count) { if (diff && multivis_count) {
if (db24) fprintf(stderr, "check_for_multivis stack diff: mark_all %f\n", now - x11vnc_start); if (db24) fprintf(stderr, "check_for_multivis stack diff: mark_all %f\n", now - x11vnc_start);
mark_8bpp(); mark_8bpp();
} else if (depth == 8 && multivis_24count) {
static double last_check = 0.0;
if (now > last_check + 0.25) {
last_check = now;
check_pointer_in_depth24();
}
} }
multivis_count = 0; multivis_count = 0;
multivis_24count = 0;
/* /*
* every 10 seconds we try to clean out and also refresh the window * every 10 seconds we try to clean out and also refresh the window
@ -130,8 +206,8 @@ if (db24) fprintf(stderr, "check_for_multivis stack diff: mark_all %f\n", now -
X_LOCK; X_LOCK;
for (i=0; i < MAX_8BPP_WINDOWS; i++) { for (i=0; i < MAX_8BPP_WINDOWS; i++) {
Window w = windows_8bpp[i].win; Window w = windows_8bpp[i].win;
if ((db24) && w != None) fprintf(stderr, " windows_8bpp: 0x%lx i=%02d ms: %d\n", windows_8bpp[i].win, i, windows_8bpp[i].map_state); if ((db24) && w != None) fprintf(stderr, " windows_8bpp: 0x%lx i=%02d ms: %d dep=%d\n", windows_8bpp[i].win, i, windows_8bpp[i].map_state, windows_8bpp[i].depth);
if (w == None || ! valid_window(w, &attr, 1)) { if (! valid_window(w, &attr, 1)) {
/* catch windows that went away: */ /* catch windows that went away: */
windows_8bpp[i].win = None; windows_8bpp[i].win = None;
windows_8bpp[i].top = None; windows_8bpp[i].top = None;
@ -252,18 +328,30 @@ static int check_depth(Window win, Window top, int doall) {
} }
static int check_depth_win(Window win, Window top, XWindowAttributes attr) { static int check_depth_win(Window win, Window top, XWindowAttributes attr) {
int store_it = 0;
/* /*
* only store windows with depth not equal to the default visual's depth * only store windows with depth not equal to the default visual's depth
* note some windows can have depth == 0 ... (skip them). * note some windows can have depth == 0 ... (skip them).
*/ */
if (attr.depth != depth && attr.depth > 0) { if (attr.depth > 0) {
set_root_cmap();
if (depth == 24 && attr.depth != 24) {
store_it = 1;
} else if (depth == 8 && root_cmap && attr.colormap !=
root_cmap) {
store_it = 1;
}
}
if (store_it) {
int i, j = -1, none = -1, nomap = -1; int i, j = -1, none = -1, nomap = -1;
int new = 0; int new = 0;
if (attr.map_state == IsViewable) { if (attr.map_state == IsViewable) {
/* count the visible ones: */ /* count the visible ones: */
multivis_count++; multivis_count++;
if (attr.depth == 24) {
multivis_24count++;
}
if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr.depth); if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr.depth);
} }
@ -299,14 +387,19 @@ if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr.depth);
/* otherwise we cannot store it... */ /* otherwise we cannot store it... */
} }
if (db24 > 1) fprintf(stderr, "multivis: 0x%lx ms: %d j: %d no: %d nm: %d\n", win, attr.map_state, j, none, nomap); if (db24 > 1) fprintf(stderr, "multivis: 0x%lx ms: %d j: %d no: %d nm: %d dep=%d\n", win, attr.map_state, j, none, nomap, attr.depth);
/* store if if we found a slot j: */ /* store if if we found a slot j: */
if (j >= 0) { if (j >= 0) {
Window w; Window w;
int x, y; int x, y;
int now_vis = 0;
if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d\n", win, j, attr.map_state); if (attr.map_state == IsViewable &&
windows_8bpp[j].map_state != IsViewable) {
now_vis = 1;
}
if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d dep=%d\n", win, j, attr.map_state, attr.depth);
windows_8bpp[j].win = win; windows_8bpp[j].win = win;
windows_8bpp[j].top = top; windows_8bpp[j].top = top;
windows_8bpp[j].depth = attr.depth; windows_8bpp[j].depth = attr.depth;
@ -323,8 +416,8 @@ if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d\n", win, j, a
windows_8bpp[j].fetched = 1; windows_8bpp[j].fetched = 1;
if (new) { if (new || now_vis) {
if (db24) fprintf(stderr, "new: 0x%lx\n", win); if (db24) fprintf(stderr, "new/now_vis: 0x%lx %d/%d\n", win, new, now_vis);
/* mark it immediately if a new one: */ /* mark it immediately if a new one: */
mark_rect_as_modified(x, y, x + attr.width, mark_rect_as_modified(x, y, x + attr.width,
y + attr.height, 0); y + attr.height, 0);
@ -345,76 +438,26 @@ if (db24 > 1) fprintf(stderr, " ------------ 0x%lx i=%d\n", windows_8bp
return 0; return 0;
} }
void bpp8to24(int x1, int y1, int x2, int y2) { #define CMAPMAX 64
char *src; Colormap cmaps[CMAPMAX];
char *dst; int ncmaps;
unsigned int *ui;
unsigned int hi, idx;
int ps, pixelsize = bpp/8;
int line, i, h, k, w;
# define CMAPMAX 64
Colormap cmaps[CMAPMAX];
int ncmaps, cmap_max = CMAPMAX;
sraRegionPtr rect, disp, region8bpp;
XWindowAttributes attr;
static int last_map_count = 0, call_count = 0;
static double last_validate = 0.0;
int validate = 1;
int histo[256];
if (! cmap8to24 || !cmap8to24_fb) { static int get_8pp_region(sraRegionPtr region8bpp, sraRegionPtr rect,
/* hmmm, why were we called? */ int validate) {
return;
}
call_count++; XWindowAttributes attr;
int i, k, mapcount = 0;
/* initialize color map list */ /* initialize color map list */
ncmaps = 0; ncmaps = 0;
for (i=0; i < cmap_max; i++) { for (i=0; i < CMAPMAX; i++) {
cmaps[i] = (Colormap) 0; cmaps[i] = (Colormap) 0;
} }
/* clip to display just in case: */
x1 = nfix(x1, dpy_x);
y1 = nfix(y1, dpy_y);
x2 = nfix(x2, dpy_x);
y2 = nfix(y2, dpy_y);
/* create regions for finding overlap, etc. */
disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
rect = sraRgnCreateRect(x1, y1, x2, y2);
region8bpp = sraRgnCreate();
X_LOCK;
XFlush(dpy); /* make sure X server is up to date WRT input, etc */
X_UNLOCK;
if (last_map_count > MAX_8BPP_WINDOWS/4) {
/* table is filling up... skip validating sometimes: */
int skip = 3;
if (last_map_count > MAX_8BPP_WINDOWS/2) {
skip = 6;
}
if (last_map_count > 3*MAX_8BPP_WINDOWS/4) {
skip = 12;
}
if (call_count % skip != 0) {
validate = 0;
if (db24) fprintf(stderr, " bpp8to24: No validate: %d -- %d\n", skip, last_map_count);
} else {
if (db24) fprintf(stderr, " bpp8to24: yesvalidate: %d -- %d\n", skip, last_map_count);
}
}
last_map_count = 0;
if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}}
/* loop over the table of 8bpp windows: */ /* loop over the table of 8bpp windows: */
for (i=0; i < MAX_8BPP_WINDOWS; i++) { for (i=0; i < MAX_8BPP_WINDOWS; i++) {
sraRegionPtr tmp_reg, tmp_reg2; sraRegionPtr tmp_reg, tmp_reg2;
Window w = windows_8bpp[i].win; Window c, w = windows_8bpp[i].win;
Window c;
int x, y; int x, y;
if (wireframe_in_progress) { if (wireframe_in_progress) {
@ -425,13 +468,12 @@ if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}}
continue; continue;
} }
if (db24 > 1) fprintf(stderr, "bpp8to24: 0x%lx ms=%d i=%d\n", w, windows_8bpp[i].map_state, i); if (db24 > 1) fprintf(stderr, "get_8pp_region: 0x%lx ms=%d dep=%d i=%d\n", w, windows_8bpp[i].map_state, windows_8bpp[i].depth, i);
if (validate) { if (validate) {
/* /*
* this could be slow: validating 8bpp windows each * this could be slow: validating 8bpp windows each
* time... * time...
*/ */
last_validate = dnow();
X_LOCK; X_LOCK;
if (! valid_window(w, &attr, 1)) { if (! valid_window(w, &attr, 1)) {
@ -451,8 +493,9 @@ if (db24 > 1) fprintf(stderr, "bpp8to24: 0x%lx ms=%d i=%d\n", w, windows_8bpp[i]
X_LOCK; X_LOCK;
xtranslate(w, window, 0, 0, &x, &y, &c, 1); xtranslate(w, window, 0, 0, &x, &y, &c, 1);
X_UNLOCK; X_UNLOCK;
} else { } else {
/* this would be faster: no call to X server: */ /* this will be faster: no call to X server: */
if (windows_8bpp[i].map_state != IsViewable) { if (windows_8bpp[i].map_state != IsViewable) {
continue; continue;
} }
@ -463,17 +506,16 @@ if (db24 > 1) fprintf(stderr, "bpp8to24: 0x%lx ms=%d i=%d\n", w, windows_8bpp[i]
attr.map_state = windows_8bpp[i].map_state; attr.map_state = windows_8bpp[i].map_state;
attr.colormap = windows_8bpp[i].cmap; attr.colormap = windows_8bpp[i].cmap;
} }
last_map_count++;
mapcount++;
/* tmp region for this 8bpp rectangle: */ /* tmp region for this 8bpp rectangle: */
tmp_reg = sraRgnCreateRect(nfix(x, dpy_x), nfix(y, dpy_y), tmp_reg = sraRgnCreateRect(nfix(x, dpy_x), nfix(y, dpy_y),
nfix(x + attr.width, dpy_x), nfix(y + attr.height, dpy_y)); nfix(x + attr.width, dpy_x), nfix(y + attr.height, dpy_y));
/* clip to display screen: */
if (0) sraRgnAnd(tmp_reg, disp);
/* find overlap with mark region in rect: */ /* find overlap with mark region in rect: */
sraRgnAnd(tmp_reg, rect); sraRgnAnd(tmp_reg, rect);
if (sraRgnEmpty(tmp_reg)) { if (sraRgnEmpty(tmp_reg)) {
/* skip if no overlap: */ /* skip if no overlap: */
sraRgnDestroy(tmp_reg); sraRgnDestroy(tmp_reg);
@ -485,7 +527,7 @@ if (db24 > 1) fprintf(stderr, "bpp8to24: 0x%lx ms=%d i=%d\n", w, windows_8bpp[i]
Window swin = stack_list[k].win; Window swin = stack_list[k].win;
int sx, sy, sw, sh; int sx, sy, sw, sh;
if (db24 > 1) fprintf(stderr, "Stack win: 0x%lx %d iv=%d\n", swin, k, stack_list[k].map_state); if (db24 > 1 && stack_list[k].map_state == IsViewable) fprintf(stderr, "Stack win: 0x%lx %d iv=%d\n", swin, k, stack_list[k].map_state);
if (swin == windows_8bpp[i].top) { if (swin == windows_8bpp[i].top) {
/* found our top level: we clip the rest. */ /* found our top level: we clip the rest. */
@ -503,10 +545,11 @@ if (db24 > 1) fprintf(stderr, "found top: 0x%lx %d iv=%d\n", swin, k, stack_list
sw = stack_list[k].width; sw = stack_list[k].width;
sh = stack_list[k].height; sh = stack_list[k].height;
if (db24 > 1) fprintf(stderr, "subtract: 0x%lx %d -- %d %d %d %d\n", swin, k, sx, sy, sw, sh);
tmp_reg2 = sraRgnCreateRect(nfix(sx, dpy_x), tmp_reg2 = sraRgnCreateRect(nfix(sx, dpy_x),
nfix(sy, dpy_y), nfix(sx + sw, dpy_x), nfix(sy, dpy_y), nfix(sx + sw, dpy_x),
nfix(sy + sh, dpy_y)); nfix(sy + sh, dpy_y));
if (0) sraRgnAnd(tmp_reg2, disp);
/* subtract it from the 8bpp window region */ /* subtract it from the 8bpp window region */
sraRgnSubtract(tmp_reg, tmp_reg2); sraRgnSubtract(tmp_reg, tmp_reg2);
@ -521,7 +564,7 @@ if (db24 > 1) fprintf(stderr, "Empty tmp_reg\n");
} }
/* otherwise, store any new colormaps: */ /* otherwise, store any new colormaps: */
if (ncmaps < cmap_max && attr.colormap != (Colormap) 0) { if (ncmaps < CMAPMAX && attr.colormap != (Colormap) 0) {
int m, sawit = 0; int m, sawit = 0;
for (m=0; m < ncmaps; m++) { for (m=0; m < ncmaps; m++) {
if (cmaps[m] == attr.colormap) { if (cmaps[m] == attr.colormap) {
@ -529,7 +572,7 @@ if (db24 > 1) fprintf(stderr, "Empty tmp_reg\n");
break; break;
} }
} }
if (! sawit) { if (! sawit && attr.depth == 8) {
/* store only new ones: */ /* store only new ones: */
cmaps[ncmaps++] = attr.colormap; cmaps[ncmaps++] = attr.colormap;
} }
@ -540,43 +583,29 @@ if (db24 > 1) fprintf(stderr, "Empty tmp_reg\n");
sraRgnDestroy(tmp_reg); sraRgnDestroy(tmp_reg);
} }
/* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */ return mapcount;
src = main_fb + main_bytes_per_line * y1 + pixelsize * x1; }
dst = cmap8to24_fb + main_bytes_per_line * y1 + pixelsize * x1;
h = y2 - y1;
w = x2 - x1;
for (line = 0; line < h; line++) {
memcpy(dst, src, w * pixelsize);
src += main_bytes_per_line;
dst += main_bytes_per_line;
}
if (db24 > 1) fprintf(stderr, "bpp8to24 w=%d h=%d m=%p c=%p r=%p \n", w, h, main_fb, cmap8to24_fb, rfb_fb);
/*
* now go back and tranform and 8bpp regions to TrueColor in
* cmap8to24_fb. we have to guess the best colormap to use if
* there is more than one...
*/
#define NCOLOR 256 #define NCOLOR 256
if (! sraRgnEmpty(region8bpp) && ncmaps) { static XColor color[CMAPMAX][NCOLOR];
sraRectangleIterator *iter; static unsigned int rgb[CMAPMAX][NCOLOR];
sraRect rect; static int cmap_failed[CMAPMAX];
int i, j, ncells; int histo[256];
int cmap_failed[CMAPMAX];
static XColor color[CMAPMAX][NCOLOR]; static int get_cmap(int j, Colormap cmap) {
static unsigned int rgb[CMAPMAX][NCOLOR]; int i, ncells;
XErrorHandler old_handler = NULL; XErrorHandler old_handler = NULL;
#if 0 if (0) {
/* not working properly for depth 24... */ /* not working properly for depth 24... */
X_LOCK; X_LOCK;
ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr));
X_UNLOCK; X_UNLOCK;
#else } else {
ncells = NCOLOR; ncells = NCOLOR;
#endif }
if (db24 > 1) fprintf(stderr, "get_cmap: %d 0x%x\n", j, (unsigned int) cmap);
/* ncells should "always" be 256. */ /* ncells should "always" be 256. */
if (ncells > NCOLOR) { if (ncells > NCOLOR) {
ncells = NCOLOR; ncells = NCOLOR;
@ -585,14 +614,6 @@ if (db24 > 1) fprintf(stderr, "bpp8to24 w=%d h=%d m=%p c=%p r=%p \n", w, h, main
ncells = NCOLOR; ncells = NCOLOR;
} }
/*
* first, grab all of the associated colormaps from the
* X server. Hopefully just 1 or 2...
*/
for (j=0; j<ncmaps; j++) {
if (db24 > 1) fprintf(stderr, "cmap %d\n", (int) cmaps[j]);
/* initialize XColor array: */ /* initialize XColor array: */
for (i=0; i < ncells; i++) { for (i=0; i < ncells; i++) {
color[j][i].pixel = i; color[j][i].pixel = i;
@ -603,20 +624,15 @@ if (db24 > 1) fprintf(stderr, "cmap %d\n", (int) cmaps[j]);
X_LOCK; X_LOCK;
trapped_xerror = 0; trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror); old_handler = XSetErrorHandler(trap_xerror);
XQueryColors(dpy, cmaps[j], color[j], ncells); XQueryColors(dpy, cmap, color[j], ncells);
XSetErrorHandler(old_handler); XSetErrorHandler(old_handler);
X_UNLOCK; X_UNLOCK;
if (trapped_xerror) { if (trapped_xerror) {
/*
* results below will be indefinite...
* need to exclude this one.
*/
trapped_xerror = 0; trapped_xerror = 0;
cmap_failed[j] = 1; return 0;
continue;
} }
trapped_xerror = 0; trapped_xerror = 0;
cmap_failed[j] = 0;
/* now map each index to depth 24 RGB */ /* now map each index to depth 24 RGB */
for (i=0; i < ncells; i++) { for (i=0; i < ncells; i++) {
@ -634,7 +650,7 @@ if (db24 > 1) fprintf(stderr, "cmap %d\n", (int) cmaps[j]);
green = (main_green_max * green)/255; green = (main_green_max * green)/255;
blue = (main_blue_max * blue )/255; blue = (main_blue_max * blue )/255;
if (db24 > 2) fprintf(stderr, " cmap[%02d][%03d]: %03d %03d %03d 0x%08lx \n", j, i, red, green, blue, ( red << main_red_shift | green << main_green_shift | blue << main_blue_shift)); if (db24 > 2) fprintf(stderr, " cmap[%02d][%03d]: %03d %03d %03d 0x%08x \n", j, i, red, green, blue, ( red << main_red_shift | green << main_green_shift | blue << main_blue_shift));
/* shift them over and or together for value */ /* shift them over and or together for value */
red = red << main_red_shift; red = red << main_red_shift;
@ -643,26 +659,26 @@ if (db24 > 2) fprintf(stderr, " cmap[%02d][%03d]: %03d %03d %03d 0x%08lx \n", j
rgb[j][i] = red | green | blue; rgb[j][i] = red | green | blue;
} }
} return 1;
}
static void do_8bpp_region(sraRect rect) {
char *src, *dst;
unsigned int *ui;
unsigned char *uc;
int ps, pixelsize = bpp/8;
int do_getimage = xgetimage_8to24;
int line, n_off, j, h, w;
unsigned int hi, idx;
XWindowAttributes attr;
XErrorHandler old_handler = NULL;
/* loop over the rectangles making up region8bpp */
iter = sraRgnGetIterator(region8bpp);
while (sraRgnIteratorNext(iter, &rect)) {
double score, max_score = -1.0; double score, max_score = -1.0;
int n, m, best; int m, best, best_depth = 0;
Window best_win = None; Window best_win = None;
if (rect.x1 > rect.x2) {
int tmp = rect.x2;
rect.x2 = rect.x1;
rect.x1 = tmp;
}
if (rect.y1 > rect.y2) {
int tmp = rect.y2;
rect.y2 = rect.y1;
rect.y1 = tmp;
}
if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps); if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps);
/* /*
@ -684,12 +700,11 @@ if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps);
/* see if XQueryColors failed: */ /* see if XQueryColors failed: */
for (k=0; k<ncmaps; k++) { for (k=0; k<ncmaps; k++) {
if (windows_8bpp[m].cmap == cmaps[k] if (windows_8bpp[m].cmap == cmaps[k] && cmap_failed[k]) {
&& cmap_failed[k]) {
failed = 1; failed = 1;
} }
} }
if (failed) { if (windows_8bpp[m].depth == 8 && failed) {
continue; continue;
} }
@ -700,15 +715,15 @@ if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps);
my2 = windows_8bpp[m].y + windows_8bpp[m].h; my2 = windows_8bpp[m].y + windows_8bpp[m].h;
/* use overlap as score: */ /* use overlap as score: */
score = rect_overlap(mx1, my1, mx2, my2, score = rect_overlap(mx1, my1, mx2, my2, rect.x1, rect.y1,
rect.x1, rect.y1, rect.x2, rect.y2); rect.x2, rect.y2);
if (score > max_score) { if (score > max_score) {
max_score = score; max_score = score;
best = m; best = m;
best_win = windows_8bpp[m].win; best_win = windows_8bpp[m].win;
best_depth = windows_8bpp[m].depth;
} }
if (db24 > 1) fprintf(stderr, "cmap_score: 0x%x %.3f %.3f\n", (int) windows_8bpp[m].cmap, score, max_score); if (db24 > 1) fprintf(stderr, "cmap_score: 0x%x %.3f %.3f\n", (int) windows_8bpp[m].cmap, score, max_score);
} }
@ -738,41 +753,48 @@ if (db24 > 1) fprintf(stderr, "cmap_score: 0x%x %.3f %.3f\n", (int) windows_8bpp
if (db24 > 1) fprintf(stderr, "transform %d %d %d %d\n", rect.x1, rect.y1, rect.x2, rect.y2); if (db24 > 1) fprintf(stderr, "transform %d %d %d %d\n", rect.x1, rect.y1, rect.x2, rect.y2);
/* now tranform the pixels in this rectangle: */ /* now tranform the pixels in this rectangle: */
n = main_bytes_per_line * rect.y1 + pixelsize * rect.x1; n_off = main_bytes_per_line * rect.y1 + pixelsize * rect.x1;
src = cmap8to24_fb + n;
h = rect.y2 - rect.y1; h = rect.y2 - rect.y1;
w = rect.x2 - rect.x1; w = rect.x2 - rect.x1;
if (xgetimage_8to24 && best_win != None && if (depth == 8) {
valid_window(best_win, &attr, 1)) { /*
/* experimental mode. */ * need to fetch depth 24 data. might need for
* best_depth == 8 too... (hi | ... failure).
*/
if (best_depth == 24) {
do_getimage = 1;
} else if (! do_hibits) {
do_getimage = 1;
}
}
if (do_getimage && valid_window(best_win, &attr, 1)) {
XImage *xi; XImage *xi;
Window c; Window c;
XErrorHandler old_handler = NULL;
unsigned int wu, hu; unsigned int wu, hu;
int xo, yo; int xo, yo;
ps = 1; /* assume 8bpp */
wu = (unsigned int) w; wu = (unsigned int) w;
hu = (unsigned int) h; hu = (unsigned int) h;
X_LOCK; X_LOCK;
xtranslate(best_win, window, 0, 0, &xo, &yo, xtranslate(best_win, window, 0, 0, &xo, &yo, &c, 1);
&c, 1);
xo = rect.x1 - xo; xo = rect.x1 - xo;
yo = rect.y1 - yo; yo = rect.y1 - yo;
if (db24 > 1) fprintf(stderr, "xywh: %d %d %d %d vs. %d %d\n", xo, yo, w, h, attr.width, attr.height); if (db24 > 1) fprintf(stderr, "xywh: %d %d %d %d vs. %d %d\n", xo, yo, w, h, attr.width, attr.height);
if (xo < 0 || yo < 0 || w > attr.width ||
h > attr.height) { if (xo < 0 || yo < 0 || w > attr.width || h > attr.height) {
if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n");
X_UNLOCK; X_UNLOCK;
continue; if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n");
return;
} }
trapped_xerror = 0; trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror); old_handler = XSetErrorHandler(trap_xerror);
/* FIXME: XGetSubImage? */
xi = XGetImage(dpy, best_win, xo, yo, wu, hu, xi = XGetImage(dpy, best_win, xo, yo, wu, hu,
AllPlanes, ZPixmap); AllPlanes, ZPixmap);
XSetErrorHandler(old_handler); XSetErrorHandler(old_handler);
@ -780,51 +802,90 @@ if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n");
if (! xi || trapped_xerror) { if (! xi || trapped_xerror) {
trapped_xerror = 0; trapped_xerror = 0;
if (db24 > 1) fprintf(stderr, "xi-fail: 0x%p trap=%d %d %d %d %d\n", xi, trapped_xerror, xo, yo, w, h); if (db24 > 1) fprintf(stderr, "xi-fail: 0x%p trap=%d %d %d %d %d\n", (void *)xi, trapped_xerror, xo, yo, w, h);
continue; return;
} else { } else {
if (db24 > 1) fprintf(stderr, "xi: 0x%p %d %d %d %d -- %d %d\n", xi, xo, yo, w, h, xi->width, xi->height); if (db24 > 1) fprintf(stderr, "xi: 0x%p %d %d %d %d -- %d %d\n", (void *)xi, xo, yo, w, h, xi->width, xi->height);
} }
trapped_xerror = 0; trapped_xerror = 0;
if (xi->depth != 8) { if (xi->depth != 8 && xi->depth != 24) {
X_LOCK; X_LOCK;
XDestroyImage(xi); XDestroyImage(xi);
X_UNLOCK; X_UNLOCK;
if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth);
continue; return;
}
if (xi->depth == 8) {
int ps1, ps2, fac;
if (depth == 8) {
ps1 = 1;
ps2 = 4;
fac = 4;
} else {
ps1 = 1;
ps2 = pixelsize;
fac = 1;
} }
dst = src;
src = xi->data; src = xi->data;
dst = cmap8to24_fb + fac * n_off;
/* line by line ... */ /* line by line ... */
for (line = 0; line < xi->height; line++) { for (line = 0; line < xi->height; line++) {
/* pixel by pixel... */ /* pixel by pixel... */
for (j = 0; j < xi->width; j++) { for (j = 0; j < xi->width; j++) {
unsigned char *uc;
uc = (unsigned char *) (src + ps * j); uc = (unsigned char *) (src + ps1 * j);
ui = (unsigned int *) (dst+pixelsize*j); ui = (unsigned int *) (dst + ps2 * j);
idx = (int) (*uc); idx = (int) (*uc);
hi = (*ui) & 0xff000000; *ui = rgb[best][idx];
*ui = hi | rgb[best][idx];
if (db24 > 2) histo[idx]++;
} }
src += xi->bytes_per_line; src += xi->bytes_per_line;
dst += main_bytes_per_line; dst += main_bytes_per_line * fac;
}
} else if (xi->depth == 24) {
/* line by line ... */
int ps1 = 4, fac;
if (depth == 8) {
fac = 4;
} else {
fac = 1; /* should not happen */
}
src = xi->data;
dst = cmap8to24_fb + fac * n_off;
for (line = 0; line < xi->height; line++) {
memcpy(dst, src, w * ps1);
src += xi->bytes_per_line;
dst += main_bytes_per_line * fac;
}
} }
X_LOCK; X_LOCK;
XDestroyImage(xi); XDestroyImage(xi);
X_UNLOCK; X_UNLOCK;
} else if (! xgetimage_8to24) { } else if (! do_getimage) {
/* normal mode. */ /* normal mode. */
int fac;
if (depth == 8) {
/* cooked up depth 24 TrueColor */
ps = 4;
fac = 4;
src = cmap8to24_fb + 4 * n_off;
} else {
ps = pixelsize; ps = pixelsize;
fac = 1;
src = cmap8to24_fb + n_off;
}
/* line by line ... */ /* line by line ... */
for (line = 0; line < h; line++) { for (line = 0; line < h; line++) {
@ -840,12 +901,162 @@ if (db24 > 2) histo[idx]++;
/* map to lookup index; rewrite pixel */ /* map to lookup index; rewrite pixel */
idx = hi >> 24; idx = hi >> 24;
*ui = hi | rgb[best][idx]; *ui = hi | rgb[best][idx];
}
src += main_bytes_per_line * fac;
}
}
}
void bpp8to24(int x1, int y1, int x2, int y2) {
char *src, *dst;
unsigned char *uc;
unsigned int *ui;
unsigned int hi;
int idx, pixelsize = bpp/8;
int line, i, j, h, w;
int n_off;
sraRegionPtr rect, disp, region8bpp;
int validate = 1;
static int last_map_count = 0, call_count = 0;
if (! cmap8to24 || !cmap8to24_fb) {
/* hmmm, why were we called? */
return;
}
call_count++;
/* clip to display just in case: */
x1 = nfix(x1, dpy_x);
y1 = nfix(y1, dpy_y);
x2 = nfix(x2, dpy_x);
y2 = nfix(y2, dpy_y);
/* create regions for finding overlap, etc. */
disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
rect = sraRgnCreateRect(x1, y1, x2, y2);
region8bpp = sraRgnCreate();
X_LOCK;
XFlush(dpy); /* make sure X server is up to date WRT input, etc */
X_UNLOCK;
if (last_map_count > MAX_8BPP_WINDOWS/4) {
/* table is filling up... skip validating sometimes: */
int skip = 3;
if (last_map_count > MAX_8BPP_WINDOWS/2) {
skip = 6;
} else if (last_map_count > 3*MAX_8BPP_WINDOWS/4) {
skip = 12;
}
if (call_count % skip != 0) {
validate = 0;
}
}
if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}}
last_map_count = get_8pp_region(region8bpp, rect, validate);
/* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */
h = y2 - y1;
w = x2 - x1;
if (depth == 8) {
/* need to cook up to depth 24 TrueColor */
/* pixelsize = 1 */
n_off = main_bytes_per_line * y1 + pixelsize * x1;
src = main_fb + n_off;
dst = cmap8to24_fb + 4 * n_off;
set_root_cmap();
if (get_cmap(0, root_cmap)) {
int ps1 = 1, ps2 = 4;
/* line by line ... */
for (line = 0; line < h; line++) {
/* pixel by pixel... */
for (j = 0; j < w; j++) {
uc = (unsigned char *) (src + ps1 * j);
ui = (unsigned int *) (dst + ps2 * j);
idx = (int) (*uc);
if (do_hibits) {
hi = idx << 24;
*ui = hi | rgb[0][idx];
} else {
*ui = rgb[0][idx];
}
if (db24 > 2) histo[idx]++; if (db24 > 2) histo[idx]++;
} }
src += main_bytes_per_line; src += main_bytes_per_line;
dst += main_bytes_per_line * 4;
}
} }
} else if (depth == 24) {
/* pixelsize = 4 */
n_off = main_bytes_per_line * y1 + pixelsize * x1;
src = main_fb + n_off;
dst = cmap8to24_fb + n_off;
/* otherwise, the pixel data as is */
for (line = 0; line < h; line++) {
memcpy(dst, src, w * pixelsize);
src += main_bytes_per_line;
dst += main_bytes_per_line;
} }
} }
if (db24 > 1) fprintf(stderr, "bpp8to24 w=%d h=%d m=%p c=%p r=%p ncmaps=%d\n", w, h, main_fb, cmap8to24_fb, rfb_fb, ncmaps);
/*
* now go back and tranform and 8bpp regions to TrueColor in
* cmap8to24_fb. we have to guess the best colormap to use if
* there is more than one...
*/
if (! sraRgnEmpty(region8bpp) && (ncmaps || depth == 8)) {
sraRectangleIterator *iter;
sraRect rect;
int j;
/*
* first, grab all of the associated colormaps from the
* X server. Hopefully just 1 or 2...
*/
for (j=0; j<ncmaps; j++) {
if (! get_cmap(j, cmaps[j])) {
cmap_failed[j] = 1;
} else {
cmap_failed[j] = 0;
}
if (db24 > 1) fprintf(stderr, "cmap %d\n", (int) cmaps[j]);
}
/* loop over the rectangles making up region8bpp */
iter = sraRgnGetIterator(region8bpp);
while (sraRgnIteratorNext(iter, &rect)) {
if (rect.x1 > rect.x2) {
int tmp = rect.x2;
rect.x2 = rect.x1;
rect.x1 = tmp;
}
if (rect.y1 > rect.y2) {
int tmp = rect.y2;
rect.y2 = rect.y1;
rect.y1 = tmp;
}
do_8bpp_region(rect);
}
sraRgnReleaseIterator(iter); sraRgnReleaseIterator(iter);
} }
@ -868,14 +1079,27 @@ void mark_8bpp(void) {
for (i=0; i < MAX_8BPP_WINDOWS; i++) { for (i=0; i < MAX_8BPP_WINDOWS; i++) {
int x1, y1, x2, y2, w, h, f = 32; int x1, y1, x2, y2, w, h, f = 32;
f = 0; /* skip fuzz, may bring in other windows... */ f = 0; /* skip fuzz, may bring in other windows... */
if (windows_8bpp[i].win == None) { if (windows_8bpp[i].win == None) {
continue; continue;
} }
if (windows_8bpp[i].map_state != IsViewable) { if (windows_8bpp[i].map_state != IsViewable) {
XWindowAttributes attr;
int vw;
X_LOCK;
vw = valid_window(windows_8bpp[i].win, &attr, 1);
X_UNLOCK;
if (vw) {
if (attr.map_state != IsViewable) {
continue; continue;
} }
} else {
continue;
}
}
x1 = windows_8bpp[i].x; x1 = windows_8bpp[i].x;
y1 = windows_8bpp[i].y; y1 = windows_8bpp[i].y;

@ -4,6 +4,7 @@
/* -- 8to24.h -- */ /* -- 8to24.h -- */
extern int multivis_count; extern int multivis_count;
extern int multivis_24count;
extern void check_for_multivis(void); extern void check_for_multivis(void);
extern void bpp8to24(int, int, int, int); extern void bpp8to24(int, int, int, int);

@ -1,3 +1,6 @@
2006-01-18 Karl Runge <runge@karlrunge.com>
* x11vnc: -8to24 now works on default depth 8 screens.
2006-01-16 Karl Runge <runge@karlrunge.com> 2006-01-16 Karl Runge <runge@karlrunge.com>
* x11vnc: more tweaks to -8to24, add XGETIMAGE_8TO24 mode to call * x11vnc: more tweaks to -8to24, add XGETIMAGE_8TO24 mode to call
XGetImage() on the 8bpp regions. XGetImage() on the 8bpp regions.

File diff suppressed because it is too large Load Diff

@ -943,6 +943,12 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
first = 0; first = 0;
} }
if (cmap8to24 && cmap8to24_fb && depth == 8) {
if (Bpp == 1) {
Bpp = 4;
}
}
if (scaling_cursor && scale_cursor_fac != 1.0) { if (scaling_cursor && scale_cursor_fac != 1.0) {
int W, H; int W, H;
char *pixels_use = (char *) pixels; char *pixels_use = (char *) pixels;

@ -98,6 +98,7 @@ void print_help(int mode) {
"\n" "\n"
"-flashcmap In 8bpp indexed color, let the installed colormap flash\n" "-flashcmap In 8bpp indexed color, let the installed colormap flash\n"
" as the pointer moves from window to window (slow).\n" " as the pointer moves from window to window (slow).\n"
" Also try the -8to24 option to avoid flash altogether.\n"
"-shiftcmap n Rare problem, but some 8bpp displays use less than 256\n" "-shiftcmap n Rare problem, but some 8bpp displays use less than 256\n"
" colorcells (e.g. 16-color grayscale, perhaps the other\n" " colorcells (e.g. 16-color grayscale, perhaps the other\n"
" bits are used for double buffering) *and* also need to\n" " bits are used for double buffering) *and* also need to\n"
@ -150,8 +151,10 @@ void print_help(int mode) {
"-8to24 If -overlay is not supported on your OS, and you have a\n" "-8to24 If -overlay is not supported on your OS, and you have a\n"
" legacy 8bpp app that you want to view on a multi-depth\n" " legacy 8bpp app that you want to view on a multi-depth\n"
" display with default depth 24 (and is 32 bpp), try\n" " display with default depth 24 (and is 32 bpp), try\n"
" this option. This option may not work on all X servers\n" " this option. It will also work for a default depth 8\n"
" and hardware (tested on XFree86/Xorg mga driver).\n" " display with depth 24 overlay windows. This option\n"
" may not work on all X servers and hardware (tested on\n"
" XFree86/Xorg mga driver).\n"
"\n" "\n"
" It enables a hack where x11vnc monitors windows within 3\n" " It enables a hack where x11vnc monitors windows within 3\n"
" levels from the root window. If it finds any that are\n" " levels from the root window. If it finds any that are\n"
@ -159,14 +162,22 @@ void print_help(int mode) {
" these regions where it extracts the 8bpp index color\n" " these regions where it extracts the 8bpp index color\n"
" value from bits 25-32 and maps them on to TrueColor\n" " value from bits 25-32 and maps them on to TrueColor\n"
" values and inserts them into bits 1-24 (i.e. overwrites\n" " values and inserts them into bits 1-24 (i.e. overwrites\n"
" bits 1-24). This method appears to work, but may still\n" " bits 1-24).\n"
" have bugs and note that it does hog resources. If there\n" "\n"
" For default depth 8 displays, everything is tranformed\n"
" to 32bpp (and is potentially a improvement over\n"
" -flashcmap). Also for default depth 8 displays, setting\n"
" the env. var. HIGHBITS_8TO24 may give a speedup for\n"
" transforming 8bpp pixel data.\n"
"\n"
" These schemes appear to work, but may still have\n"
" bugs and note that they do hog resources. If there\n"
" are multiple 8bpp windows using different colormaps,\n" " are multiple 8bpp windows using different colormaps,\n"
" one may have to iconify all but one for the colors to\n" " one may have to iconify all but one for the colors to\n"
" be correct.\n" " be correct.\n"
"\n" "\n"
" There may also be painting errors for clipping\n" " There may also be painting errors for clipping and\n"
" and switching between windows of depths 8 and 24.\n" " switching between windows of depths 8 and 24.\n"
" Heuristics are applied to try to minimize the painting\n" " Heuristics are applied to try to minimize the painting\n"
" errors. One can also press 3 Alt_L's in a row to\n" " errors. One can also press 3 Alt_L's in a row to\n"
" refresh the screen if the error does not repair itself.\n" " refresh the screen if the error does not repair itself.\n"
@ -183,12 +194,8 @@ void print_help(int mode) {
" a scheme were XGetImage() is used to retrieve the 8bpp\n" " a scheme were XGetImage() is used to retrieve the 8bpp\n"
" data instead of assuming that data is in bits 25-32.\n" " data instead of assuming that data is in bits 25-32.\n"
" This mode is significantly slower than the above mode.\n" " This mode is significantly slower than the above mode.\n"
"\n" " For the default depth 8 case, XGetImage() is always\n"
" Note that -8to24 does not work on displays with 8bpp\n" " used to access depth 24 pixel data.\n"
" default visual with depth 24 applications. The Xserver\n"
" -cc option can be used to switch the default depth\n"
" on multidepth setups. It may be possible to handle\n"
" this case.\n"
"\n" "\n"
"-scale fraction Scale the framebuffer by factor \"fraction\". Values\n" "-scale fraction Scale the framebuffer by factor \"fraction\". Values\n"
" less than 1 shrink the fb, larger ones expand it. Note:\n" " less than 1 shrink the fb, larger ones expand it. Note:\n"

@ -984,8 +984,16 @@ char *process_remote_cmd(char *cmd, int stringonly) {
snprintf(buf, bufn, "ans=%s:%d", p, cmap8to24); snprintf(buf, bufn, "ans=%s:%d", p, cmap8to24);
goto qry; goto qry;
} }
if (overlay) {
rfbLog("disabling -overlay in -8to24 mode.\n");
overlay = 0;
}
rfbLog("remote_cmd: turning on -8to24 mode.\n"); rfbLog("remote_cmd: turning on -8to24 mode.\n");
cmap8to24 = 1; cmap8to24 = 1;
if (overlay) {
rfbLog("disabling -overlay in -8to24 mode.\n");
overlay = 0;
}
do_new_fb(0); do_new_fb(0);
} else if (!strcmp(p, "no8to24")) { } else if (!strcmp(p, "no8to24")) {

@ -1160,6 +1160,7 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) { void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
char *src_fb = main_fb; char *src_fb = main_fb;
int Bpp = bpp/8, fac = 1;
if (!screen || !rfb_fb || !main_fb) { if (!screen || !rfb_fb || !main_fb) {
return; return;
@ -1185,10 +1186,13 @@ void scale_and_mark_rect(int X1, int Y1, int X2, int Y2) {
if (cmap8to24 && cmap8to24_fb) { if (cmap8to24 && cmap8to24_fb) {
src_fb = cmap8to24_fb; src_fb = cmap8to24_fb;
if (scaling && depth == 8) {
fac = 4;
}
} }
scale_rect(scale_fac, scaling_blend, scaling_interpolate, bpp/8, scale_rect(scale_fac, scaling_blend, scaling_interpolate, fac * Bpp,
src_fb, main_bytes_per_line, rfb_fb, rfb_bytes_per_line, src_fb, fac * main_bytes_per_line, rfb_fb, rfb_bytes_per_line,
dpy_x, dpy_y, scaled_x, scaled_y, X1, Y1, X2, Y2, 1); dpy_x, dpy_y, scaled_x, scaled_y, X1, Y1, X2, Y2, 1);
} }

@ -1502,11 +1502,39 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
int height = fb->height; int height = fb->height;
int create_screen = screen ? 0 : 1; int create_screen = screen ? 0 : 1;
int bits_per_color; int bits_per_color;
int fb_bpp, fb_Bpl, fb_depth;
bpp = fb->bits_per_pixel;
fb_bpp = (int) fb->bits_per_pixel;
fb_Bpl = (int) fb->bytes_per_line;
fb_depth = (int) fb->depth;
main_bytes_per_line = fb->bytes_per_line; main_bytes_per_line = fb->bytes_per_line;
setup_scaling(&width, &height); if (cmap8to24) {
if (raw_fb) {
if (!quiet) rfbLog("disabling -8to24 mode"
" in raw_fb mode.\n");
cmap8to24 = 0;
} else if (depth == 24) {
if (fb_bpp != 32) {
if (!quiet) rfbLog("disabling -8to24 mode:"
" bpp != 32 with depth == 24\n");
cmap8to24 = 0;
}
} else if (depth == 8) {
/* need to cook up the screen fb to be depth 24 */
fb_bpp = 32;
fb_depth = 24;
} else {
if (!quiet) rfbLog("disabling -8to24 mode:"
" default depth not 24 or 8\n");
cmap8to24 = 0;
}
}
setup_scaling(&width, &height);
if (scaling) { if (scaling) {
rfbLog("scaling screen: %dx%d -> %dx%d scale_fac=%.5f\n", rfbLog("scaling screen: %dx%d -> %dx%d scale_fac=%.5f\n",
@ -1517,32 +1545,35 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
rfb_bytes_per_line = main_bytes_per_line; rfb_bytes_per_line = main_bytes_per_line;
} }
if (cmap8to24 && depth == 8) {
rfb_bytes_per_line *= 4;
}
/* /*
* These are just hints wrt pixel format just to let * These are just hints wrt pixel format just to let
* rfbGetScreen/rfbNewFramebuffer proceed with reasonable * rfbGetScreen/rfbNewFramebuffer proceed with reasonable
* defaults. We manually set them in painful detail below. * defaults. We manually set them in painful detail below.
*/ */
bits_per_color = guess_bits_per_color(fb->bits_per_pixel); bits_per_color = guess_bits_per_color(fb_bpp);
/* n.b. samplesPerPixel (set = 1 here) seems to be unused. */ /* n.b. samplesPerPixel (set = 1 here) seems to be unused. */
if (create_screen) { if (create_screen) {
screen = rfbGetScreen(argc, argv, width, height, screen = rfbGetScreen(argc, argv, width, height,
bits_per_color, 1, (int) fb->bits_per_pixel/8); bits_per_color, 1, fb_bpp/8);
if (screen && http_dir) { if (screen && http_dir) {
http_connections(1); http_connections(1);
} }
} else { } else {
/* set set frameBuffer member below. */ /* set set frameBuffer member below. */
rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n", rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n",
screen, NULL, width, height, screen, NULL, width, height, bits_per_color, 1, fb_bpp/8);
bits_per_color, 1, fb->bits_per_pixel/8);
/* these are probably overwritten, but just to be safe: */ /* these are probably overwritten, but just to be safe: */
screen->bitsPerPixel = fb->bits_per_pixel; screen->bitsPerPixel = fb_bpp;
screen->depth = fb->depth; screen->depth = fb_depth;
rfbNewFramebuffer(screen, NULL, width, height, rfbNewFramebuffer(screen, NULL, width, height,
bits_per_color, 1, (int) fb->bits_per_pixel/8); bits_per_color, 1, (int) fb_bpp/8);
} }
if (! screen) { if (! screen) {
int i; int i;
@ -1583,8 +1614,8 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
/* set up format from scratch: */ /* set up format from scratch: */
screen->paddedWidthInBytes = rfb_bytes_per_line; screen->paddedWidthInBytes = rfb_bytes_per_line;
screen->serverFormat.bitsPerPixel = fb->bits_per_pixel; screen->serverFormat.bitsPerPixel = fb_bpp;
screen->serverFormat.depth = fb->depth; screen->serverFormat.depth = fb_depth;
screen->serverFormat.trueColour = TRUE; screen->serverFormat.trueColour = TRUE;
screen->serverFormat.redShift = 0; screen->serverFormat.redShift = 0;
@ -1605,12 +1636,33 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
main_green_mask = fb->green_mask; main_green_mask = fb->green_mask;
main_blue_mask = fb->blue_mask; main_blue_mask = fb->blue_mask;
have_masks = ((fb->red_mask|fb->green_mask|fb->blue_mask) != 0); have_masks = ((fb->red_mask|fb->green_mask|fb->blue_mask) != 0);
if (force_indexed_color) { if (force_indexed_color) {
have_masks = 0; have_masks = 0;
} }
if (cmap8to24 && depth == 8) {
XVisualInfo vinfo;
/* more cooking up... */
have_masks = 2;
/* need to fetch TrueColor visual */
X_LOCK;
if (XMatchVisualInfo(dpy, scr, 24, TrueColor, &vinfo)) {
main_red_mask = vinfo.red_mask;
main_green_mask = vinfo.green_mask;
main_blue_mask = vinfo.blue_mask;
} else if (fb->byte_order == LSBFirst) {
main_red_mask = 0x00ff0000;
main_green_mask = 0x0000ff00;
main_blue_mask = 0x000000ff;
} else {
main_red_mask = 0x000000ff;
main_green_mask = 0x0000ff00;
main_blue_mask = 0x00ff0000;
}
X_UNLOCK;
}
if (! have_masks && screen->serverFormat.bitsPerPixel == 8 if (! have_masks && screen->serverFormat.bitsPerPixel == 8
&& dpy && CellsOfScreen(ScreenOfDisplay(dpy, scr))) { && dpy && CellsOfScreen(ScreenOfDisplay(dpy, scr))) {
/* indexed color */ /* indexed color */
@ -1641,41 +1693,45 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
if (raw_fb) { if (raw_fb) {
rfbLog("Raw fb at addr %p is %dbpp depth=%d " rfbLog("Raw fb at addr %p is %dbpp depth=%d "
"true color\n", raw_fb_addr, "true color\n", raw_fb_addr,
fb_bpp, fb_depth);
} else if (have_masks == 2) {
rfbLog("X display %s is %dbpp depth=%d indexed "
"color (-8to24 mode)\n", DisplayString(dpy),
fb->bits_per_pixel, fb->depth); fb->bits_per_pixel, fb->depth);
} else { } else {
rfbLog("X display %s is %dbpp depth=%d true " rfbLog("X display %s is %dbpp depth=%d true "
"color\n", DisplayString(dpy), "color\n", DisplayString(dpy),
fb->bits_per_pixel, fb->depth); fb_bpp, fb_depth);
} }
} }
indexed_color = 0; indexed_color = 0;
/* convert masks to bit shifts and max # colors */ /* convert masks to bit shifts and max # colors */
if (fb->red_mask) { if (main_red_mask) {
while (! (fb->red_mask while (! (main_red_mask
& (1 << screen->serverFormat.redShift))) { & (1 << screen->serverFormat.redShift))) {
screen->serverFormat.redShift++; screen->serverFormat.redShift++;
} }
} }
if (fb->green_mask) { if (main_green_mask) {
while (! (fb->green_mask while (! (main_green_mask
& (1 << screen->serverFormat.greenShift))) { & (1 << screen->serverFormat.greenShift))) {
screen->serverFormat.greenShift++; screen->serverFormat.greenShift++;
} }
} }
if (fb->blue_mask) { if (main_blue_mask) {
while (! (fb->blue_mask while (! (main_blue_mask
& (1 << screen->serverFormat.blueShift))) { & (1 << screen->serverFormat.blueShift))) {
screen->serverFormat.blueShift++; screen->serverFormat.blueShift++;
} }
} }
screen->serverFormat.redMax screen->serverFormat.redMax
= fb->red_mask >> screen->serverFormat.redShift; = main_red_mask >> screen->serverFormat.redShift;
screen->serverFormat.greenMax screen->serverFormat.greenMax
= fb->green_mask >> screen->serverFormat.greenShift; = main_green_mask >> screen->serverFormat.greenShift;
screen->serverFormat.blueMax screen->serverFormat.blueMax
= fb->blue_mask >> screen->serverFormat.blueShift; = main_blue_mask >> screen->serverFormat.blueShift;
main_red_max = screen->serverFormat.redMax; main_red_max = screen->serverFormat.redMax;
main_green_max = screen->serverFormat.greenMax; main_green_max = screen->serverFormat.greenMax;
@ -1703,6 +1759,17 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
bitprint(fb->green_mask, 32)); bitprint(fb->green_mask, 32));
fprintf(stderr, " blue_mask: 0x%08lx %s\n", fb->blue_mask, fprintf(stderr, " blue_mask: 0x%08lx %s\n", fb->blue_mask,
bitprint(fb->blue_mask, 32)); bitprint(fb->blue_mask, 32));
if (cmap8to24) {
fprintf(stderr, " 8to24 info:\n");
fprintf(stderr, " fb_bpp: %d\n", fb_bpp);
fprintf(stderr, " fb_depth: %d\n", fb_depth);
fprintf(stderr, " red_mask: 0x%08lx %s\n", main_red_mask,
bitprint(main_red_mask, 32));
fprintf(stderr, " green_mask: 0x%08lx %s\n", main_green_mask,
bitprint(main_green_mask, 32));
fprintf(stderr, " blue_mask: 0x%08lx %s\n", main_blue_mask,
bitprint(main_blue_mask, 32));
}
fprintf(stderr, " red: max: %3d shift: %2d\n", fprintf(stderr, " red: max: %3d shift: %2d\n",
main_red_max, main_red_shift); main_red_max, main_red_shift);
fprintf(stderr, " green: max: %3d shift: %2d\n", fprintf(stderr, " green: max: %3d shift: %2d\n",
@ -1765,16 +1832,11 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
rfb_fb = NULL; rfb_fb = NULL;
cmap8to24_fb = NULL; cmap8to24_fb = NULL;
if (cmap8to24) {
if (screen->serverFormat.bitsPerPixel != 32 ||
screen->serverFormat.depth != 24) {
if (!quiet) rfbLog("disabling -8to24 mode:"
" bpp != 32 or depth != 24\n");
cmap8to24 = 0;
}
}
if (cmap8to24) { if (cmap8to24) {
int n = main_bytes_per_line * fb->height; int n = main_bytes_per_line * fb->height;
if (depth == 8) {
n *= 4;
}
cmap8to24_fb = (char *) malloc(n); cmap8to24_fb = (char *) malloc(n);
memset(cmap8to24_fb, 0, n); memset(cmap8to24_fb, 0, n);
} }
@ -1795,9 +1857,6 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
bpp = screen->serverFormat.bitsPerPixel;
depth = screen->serverFormat.depth;
/* may need, bpp, main_red_max, etc. */ /* may need, bpp, main_red_max, etc. */
parse_wireframe(); parse_wireframe();
parse_scroll_copyrect(); parse_scroll_copyrect();

@ -1729,16 +1729,16 @@ static void get_client_regions(int *req, int *mod, int *cpy, int *num) {
static void do_copyregion(sraRegionPtr region, int dx, int dy) { static void do_copyregion(sraRegionPtr region, int dx, int dy) {
sraRectangleIterator *iter; sraRectangleIterator *iter;
sraRect rect; sraRect rect;
int Bpp = bpp/8; int Bpp0 = bpp/8, Bpp;
int x1, y1, x2, y2, w, stride; int x1, y1, x2, y2, w, stride, stride0;
int sx1, sy1, sx2, sy2, sdx, sdy; int sx1, sy1, sx2, sy2, sdx, sdy;
int req, mod, cpy, ncli; int req, mod, cpy, ncli;
char *dst, *src; char *dst = NULL, *src = NULL;
last_copyrect = dnow(); last_copyrect = dnow();
if (!scaling || rfb_fb == main_fb) { if (rfb_fb == main_fb) {
/* normal case */ /* normal case, no -scale or -8to24 */
get_client_regions(&req, &mod, &cpy, &ncli); get_client_regions(&req, &mod, &cpy, &ncli);
if (debug_scroll > 1) fprintf(stderr, "<<<-rfbDoCopyRect req: %d mod: %d cpy: %d\n", req, mod, cpy); if (debug_scroll > 1) fprintf(stderr, "<<<-rfbDoCopyRect req: %d mod: %d cpy: %d\n", req, mod, cpy);
rfbDoCopyRegion(screen, region, dx, dy); rfbDoCopyRegion(screen, region, dx, dy);
@ -1750,21 +1750,41 @@ if (debug_scroll > 1) fprintf(stderr, ">>>-rfbDoCopyRect req: %d mod: %d cpy: %d
} }
/* rarer case, we need to call rfbDoCopyRect with scaled xy */ /* rarer case, we need to call rfbDoCopyRect with scaled xy */
stride = dpy_x * Bpp; stride0 = dpy_x * Bpp0;
iter = sraRgnGetReverseIterator(region, dx < 0, dy < 0); iter = sraRgnGetReverseIterator(region, dx < 0, dy < 0);
while(sraRgnIteratorNext(iter, &rect)) { while(sraRgnIteratorNext(iter, &rect)) {
int j; int j, c;
x1 = rect.x1; x1 = rect.x1;
y1 = rect.y1; y1 = rect.y1;
x2 = rect.x2; x2 = rect.x2;
y2 = rect.y2; y2 = rect.y2;
w = (x2 - x1)*Bpp;
for (c= 0; c < 2; c++) {
Bpp = Bpp0;
stride = stride0;
if (c == 0) {
dst = main_fb + y1*stride + x1*Bpp; dst = main_fb + y1*stride + x1*Bpp;
src = main_fb + (y1-dy)*stride + (x1-dx)*Bpp; src = main_fb + (y1-dy)*stride + (x1-dx)*Bpp;
} else if (c == 1) {
if (! cmap8to24_fb || cmap8to24_fb == rfb_fb) {
continue;
}
if (cmap8to24 && depth == 8) {
Bpp = 4 * Bpp0;
stride = 4 * stride0;
}
dst = cmap8to24_fb + y1*stride + x1*Bpp;
src = cmap8to24_fb + (y1-dy)*stride + (x1-dx)*Bpp;
}
w = (x2 - x1)*Bpp;
if (dy < 0) { if (dy < 0) {
for (j=y1; j<y2; j++) { for (j=y1; j<y2; j++) {
memmove(dst, src, w); memmove(dst, src, w);
@ -1780,13 +1800,23 @@ if (debug_scroll > 1) fprintf(stderr, ">>>-rfbDoCopyRect req: %d mod: %d cpy: %d
src -= stride; src -= stride;
} }
} }
}
if (scaling) {
sx1 = ((double) x1 / dpy_x) * scaled_x; sx1 = ((double) x1 / dpy_x) * scaled_x;
sy1 = ((double) y1 / dpy_y) * scaled_y; sy1 = ((double) y1 / dpy_y) * scaled_y;
sx2 = ((double) x2 / dpy_x) * scaled_x; sx2 = ((double) x2 / dpy_x) * scaled_x;
sy2 = ((double) y2 / dpy_y) * scaled_y; sy2 = ((double) y2 / dpy_y) * scaled_y;
sdx = ((double) dx / dpy_x) * scaled_x; sdx = ((double) dx / dpy_x) * scaled_x;
sdy = ((double) dy / dpy_y) * scaled_y; sdy = ((double) dy / dpy_y) * scaled_y;
} else {
sx1 = x1;
sy1 = y1;
sx2 = x2;
sy2 = y2;
sdx = dx;
sdy = dy;
}
rfbDoCopyRect(screen, sx1, sy1, sx2, sy2, sdx, sdy); rfbDoCopyRect(screen, sx1, sy1, sx2, sy2, sdx, sdy);
} }
@ -3710,8 +3740,6 @@ if (db) fprintf(stderr, "send_copyrect: %d\n", sent_copyrect);
if (0) fprintf(stderr, "wireframe_in_progress over: %d %d %d %d\n", x1, y1, x2, y2); if (0) fprintf(stderr, "wireframe_in_progress over: %d %d %d %d\n", x1, y1, x2, y2);
check_for_multivis(); check_for_multivis();
if (1) mark_rect_as_modified(x1, y1, x2, y2, 0); if (1) mark_rect_as_modified(x1, y1, x2, y2, 0);
if (0) mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
if (0) rfbPE(-1);
} }
urgent_update = 1; urgent_update = 1;

@ -2,7 +2,7 @@
.TH X11VNC "1" "January 2006" "x11vnc " "User Commands" .TH X11VNC "1" "January 2006" "x11vnc " "User Commands"
.SH NAME .SH NAME
x11vnc - allow VNC connections to real X11 displays x11vnc - allow VNC connections to real X11 displays
version: 0.8, lastmod: 2006-01-16 version: 0.8, lastmod: 2006-01-18
.SH SYNOPSIS .SH SYNOPSIS
.B x11vnc .B x11vnc
[OPTION]... [OPTION]...
@ -110,6 +110,7 @@ of the selected window.
.IP .IP
In 8bpp indexed color, let the installed colormap flash In 8bpp indexed color, let the installed colormap flash
as the pointer moves from window to window (slow). as the pointer moves from window to window (slow).
Also try the \fB-8to24\fR option to avoid flash altogether.
.PP .PP
\fB-shiftcmap\fR \fIn\fR \fB-shiftcmap\fR \fIn\fR
.IP .IP
@ -182,8 +183,10 @@ cursor shape using the overlay mechanism.
If \fB-overlay\fR is not supported on your OS, and you have a If \fB-overlay\fR is not supported on your OS, and you have a
legacy 8bpp app that you want to view on a multi-depth legacy 8bpp app that you want to view on a multi-depth
display with default depth 24 (and is 32 bpp), try display with default depth 24 (and is 32 bpp), try
this option. This option may not work on all X servers this option. It will also work for a default depth 8
and hardware (tested on XFree86/Xorg mga driver). display with depth 24 overlay windows. This option
may not work on all X servers and hardware (tested on
XFree86/Xorg mga driver).
.IP .IP
It enables a hack where x11vnc monitors windows within 3 It enables a hack where x11vnc monitors windows within 3
levels from the root window. If it finds any that are levels from the root window. If it finds any that are
@ -191,14 +194,22 @@ levels from the root window. If it finds any that are
these regions where it extracts the 8bpp index color these regions where it extracts the 8bpp index color
value from bits 25-32 and maps them on to TrueColor value from bits 25-32 and maps them on to TrueColor
values and inserts them into bits 1-24 (i.e. overwrites values and inserts them into bits 1-24 (i.e. overwrites
bits 1-24). This method appears to work, but may still bits 1-24).
have bugs and note that it does hog resources. If there .IP
For default depth 8 displays, everything is tranformed
to 32bpp (and is potentially a improvement over
\fB-flashcmap).\fR Also for default depth 8 displays, setting
the env. var. HIGHBITS_8TO24 may give a speedup for
transforming 8bpp pixel data.
.IP
These schemes appear to work, but may still have
bugs and note that they do hog resources. If there
are multiple 8bpp windows using different colormaps, are multiple 8bpp windows using different colormaps,
one may have to iconify all but one for the colors to one may have to iconify all but one for the colors to
be correct. be correct.
.IP .IP
There may also be painting errors for clipping There may also be painting errors for clipping and
and switching between windows of depths 8 and 24. switching between windows of depths 8 and 24.
Heuristics are applied to try to minimize the painting Heuristics are applied to try to minimize the painting
errors. One can also press 3 Alt_L's in a row to errors. One can also press 3 Alt_L's in a row to
refresh the screen if the error does not repair itself. refresh the screen if the error does not repair itself.
@ -215,12 +226,8 @@ XGETIMAGE_8TO24=1 before starting x11vnc. This enables
a scheme were XGetImage() is used to retrieve the 8bpp a scheme were XGetImage() is used to retrieve the 8bpp
data instead of assuming that data is in bits 25-32. data instead of assuming that data is in bits 25-32.
This mode is significantly slower than the above mode. This mode is significantly slower than the above mode.
.IP For the default depth 8 case, XGetImage() is always
Note that \fB-8to24\fR does not work on displays with 8bpp used to access depth 24 pixel data.
default visual with depth 24 applications. The Xserver
\fB-cc\fR option can be used to switch the default depth
on multidepth setups. It may be possible to handle
this case.
.PP .PP
\fB-scale\fR \fIfraction\fR \fB-scale\fR \fIfraction\fR
.IP .IP

@ -1560,7 +1560,7 @@ int main(int argc, char* argv[]) {
set_wirecopyrect_mode(argv[++i]); set_wirecopyrect_mode(argv[++i]);
got_wirecopyrect = 1; got_wirecopyrect = 1;
} else if (!strcmp(arg, "-nowirecopyrect") } else if (!strcmp(arg, "-nowirecopyrect")
|| !strcmp(arg, "-nowf")) { || !strcmp(arg, "-nowcr")) {
set_wirecopyrect_mode("never"); set_wirecopyrect_mode("never");
} else if (!strcmp(arg, "-debug_wireframe") } else if (!strcmp(arg, "-debug_wireframe")
|| !strcmp(arg, "-dwf")) { || !strcmp(arg, "-dwf")) {
@ -2054,10 +2054,18 @@ int main(int argc, char* argv[]) {
alpha_remove = 0; alpha_remove = 0;
} }
if (cmap8to24 && overlay) {
if (! quiet) {
rfbLog("disabling -overlay in -8to24 mode.\n");
}
overlay = 0;
}
if (filexfer && view_only) { if (filexfer && view_only) {
if (! quiet) { if (! quiet) {
rfbLog("setting -nofilexfer in -viewonly mode.\n"); rfbLog("setting -nofilexfer in -viewonly mode.\n");
} }
/* how to undo via -R? */
filexfer = 0; filexfer = 0;
} }

@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0; int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */ /* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.8 lastmod: 2006-01-16"; char lastmod[] = "0.8 lastmod: 2006-01-18";
/* X display info */ /* X display info */

Loading…
Cancel
Save