diff options
author | runge <runge> | 2006-01-19 03:54:10 +0000 |
---|---|---|
committer | runge <runge> | 2006-01-19 03:54:10 +0000 |
commit | 17e6b6a2bf6def6b380bee2fcc0fb9e8254518f4 (patch) | |
tree | 8a387c278f6b7a66a91fd4e8c5deb5b8b9a14e79 /x11vnc/8to24.c | |
parent | e38c3c224b19775a70c8ee5b8eddbf81be07a0bd (diff) | |
download | libtdevnc-17e6b6a2bf6def6b380bee2fcc0fb9e8254518f4.tar.gz libtdevnc-17e6b6a2bf6def6b380bee2fcc0fb9e8254518f4.zip |
x11vnc: -8to24 now works on default depth 8 displays.
Diffstat (limited to 'x11vnc/8to24.c')
-rw-r--r-- | x11vnc/8to24.c | 870 |
1 files changed, 547 insertions, 323 deletions
diff --git a/x11vnc/8to24.c b/x11vnc/8to24.c index ef3583e..f0d1786 100644 --- a/x11vnc/8to24.c +++ b/x11vnc/8to24.c @@ -6,13 +6,20 @@ #include "win_utils.h" int multivis_count = 0; +int multivis_24count = 0; void check_for_multivis(void); void bpp8to24(int, int, int, int); 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_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: */ typedef struct window8 { @@ -27,12 +34,69 @@ typedef struct window8 { int fetched; } 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 */ #define MAX_8BPP_WINDOWS 64 static window8bpp_t windows_8bpp[MAX_8BPP_WINDOWS]; static int db24 = 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) { XWindowAttributes attr; @@ -61,9 +125,13 @@ void check_for_multivis(void) { if (getenv("XGETIMAGE_8TO24") != NULL) { xgetimage_8to24 = 1; } + if (getenv("HIGHBITS_8TO24") != NULL) { + do_hibits = 1; + } first = 0; doall = 1; /* fetch everything first time */ } + set_root_cmap(); /* * allocate an "old stack" list of all toplevels. we compare @@ -117,9 +185,17 @@ void check_for_multivis(void) { if (diff && multivis_count) { if (db24) fprintf(stderr, "check_for_multivis stack diff: mark_all %f\n", now - x11vnc_start); 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_24count = 0; /* * 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; for (i=0; i < MAX_8BPP_WINDOWS; i++) { 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 (w == None || ! valid_window(w, &attr, 1)) { +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 (! valid_window(w, &attr, 1)) { /* catch windows that went away: */ windows_8bpp[i].win = 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) { - + int store_it = 0; /* * only store windows with depth not equal to the default visual's depth * 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 new = 0; if (attr.map_state == IsViewable) { /* count the visible ones: */ multivis_count++; + if (attr.depth == 24) { + multivis_24count++; + } 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... */ } -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: */ if (j >= 0) { Window w; 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].top = top; 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; - if (new) { -if (db24) fprintf(stderr, "new: 0x%lx\n", win); + if (new || now_vis) { +if (db24) fprintf(stderr, "new/now_vis: 0x%lx %d/%d\n", win, new, now_vis); /* mark it immediately if a new one: */ mark_rect_as_modified(x, y, x + attr.width, y + attr.height, 0); @@ -345,76 +438,26 @@ if (db24 > 1) fprintf(stderr, " ------------ 0x%lx i=%d\n", windows_8bp return 0; } -void bpp8to24(int x1, int y1, int x2, int y2) { - char *src; - char *dst; - 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]; +#define CMAPMAX 64 +Colormap cmaps[CMAPMAX]; +int ncmaps; - if (! cmap8to24 || !cmap8to24_fb) { - /* hmmm, why were we called? */ - return; - } +static int get_8pp_region(sraRegionPtr region8bpp, sraRegionPtr rect, + int validate) { - call_count++; + XWindowAttributes attr; + int i, k, mapcount = 0; /* initialize color map list */ ncmaps = 0; - for (i=0; i < cmap_max; i++) { + for (i=0; i < CMAPMAX; i++) { 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: */ for (i=0; i < MAX_8BPP_WINDOWS; i++) { sraRegionPtr tmp_reg, tmp_reg2; - Window w = windows_8bpp[i].win; - Window c; + Window c, w = windows_8bpp[i].win; int x, y; if (wireframe_in_progress) { @@ -425,13 +468,12 @@ if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} 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) { /* * this could be slow: validating 8bpp windows each * time... */ - last_validate = dnow(); X_LOCK; 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; xtranslate(w, window, 0, 0, &x, &y, &c, 1); X_UNLOCK; + } 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) { 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.colormap = windows_8bpp[i].cmap; } - last_map_count++; + + mapcount++; /* tmp region for this 8bpp rectangle: */ tmp_reg = sraRgnCreateRect(nfix(x, dpy_x), nfix(y, 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: */ sraRgnAnd(tmp_reg, rect); + if (sraRgnEmpty(tmp_reg)) { /* skip if no overlap: */ 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; 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) { /* 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; 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), nfix(sy, dpy_y), nfix(sx + sw, dpy_x), nfix(sy + sh, dpy_y)); - if (0) sraRgnAnd(tmp_reg2, disp); /* subtract it from the 8bpp window region */ sraRgnSubtract(tmp_reg, tmp_reg2); @@ -521,7 +564,7 @@ if (db24 > 1) fprintf(stderr, "Empty tmp_reg\n"); } /* otherwise, store any new colormaps: */ - if (ncmaps < cmap_max && attr.colormap != (Colormap) 0) { + if (ncmaps < CMAPMAX && attr.colormap != (Colormap) 0) { int m, sawit = 0; for (m=0; m < ncmaps; m++) { if (cmaps[m] == attr.colormap) { @@ -529,7 +572,7 @@ if (db24 > 1) fprintf(stderr, "Empty tmp_reg\n"); break; } } - if (! sawit) { + if (! sawit && attr.depth == 8) { /* store only new ones: */ cmaps[ncmaps++] = attr.colormap; } @@ -540,312 +583,480 @@ if (db24 > 1) fprintf(stderr, "Empty tmp_reg\n"); sraRgnDestroy(tmp_reg); } - /* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */ - 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); + return mapcount; +} - /* - * 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 - if (! sraRgnEmpty(region8bpp) && ncmaps) { - sraRectangleIterator *iter; - sraRect rect; - int i, j, ncells; - int cmap_failed[CMAPMAX]; - static XColor color[CMAPMAX][NCOLOR]; - static unsigned int rgb[CMAPMAX][NCOLOR]; - XErrorHandler old_handler = NULL; +static XColor color[CMAPMAX][NCOLOR]; +static unsigned int rgb[CMAPMAX][NCOLOR]; +static int cmap_failed[CMAPMAX]; +int histo[256]; -#if 0 +static int get_cmap(int j, Colormap cmap) { + int i, ncells; + XErrorHandler old_handler = NULL; + + if (0) { /* not working properly for depth 24... */ X_LOCK; ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); X_UNLOCK; -#else + } else { ncells = NCOLOR; -#endif - /* ncells should "always" be 256. */ - if (ncells > NCOLOR) { - ncells = NCOLOR; - } else if (ncells == 8) { - /* hmmm. see set_colormap() */ - ncells = NCOLOR; - } + } +if (db24 > 1) fprintf(stderr, "get_cmap: %d 0x%x\n", j, (unsigned int) cmap); - /* - * 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]); + /* ncells should "always" be 256. */ + if (ncells > NCOLOR) { + ncells = NCOLOR; + } else if (ncells == 8) { + /* hmmm. see set_colormap() */ + ncells = NCOLOR; + } - /* initialize XColor array: */ - for (i=0; i < ncells; i++) { - color[j][i].pixel = i; - color[j][i].pad = 0; - } + /* initialize XColor array: */ + for (i=0; i < ncells; i++) { + color[j][i].pixel = i; + color[j][i].pad = 0; + } - /* try to query the colormap, trap errors */ - X_LOCK; - trapped_xerror = 0; - old_handler = XSetErrorHandler(trap_xerror); - XQueryColors(dpy, cmaps[j], color[j], ncells); - XSetErrorHandler(old_handler); - X_UNLOCK; - if (trapped_xerror) { - /* - * results below will be indefinite... - * need to exclude this one. - */ - trapped_xerror = 0; - cmap_failed[j] = 1; - continue; - } - trapped_xerror = 0; - cmap_failed[j] = 0; + /* try to query the colormap, trap errors */ + X_LOCK; + trapped_xerror = 0; + old_handler = XSetErrorHandler(trap_xerror); + XQueryColors(dpy, cmap, color[j], ncells); + XSetErrorHandler(old_handler); + X_UNLOCK; - /* now map each index to depth 24 RGB */ - for (i=0; i < ncells; i++) { - unsigned int red, green, blue; - /* strip out highest 8 bits of values: */ - red = (color[j][i].red & 0xff00) >> 8; - green = (color[j][i].green & 0xff00) >> 8; - blue = (color[j][i].blue & 0xff00) >> 8; + if (trapped_xerror) { + trapped_xerror = 0; + return 0; + } + trapped_xerror = 0; - /* - * the maxes should be at 255 already, - * but just in case... - */ - red = (main_red_max * red )/255; - green = (main_green_max * green)/255; - blue = (main_blue_max * blue )/255; + /* now map each index to depth 24 RGB */ + for (i=0; i < ncells; i++) { + unsigned int red, green, blue; + /* strip out highest 8 bits of values: */ + red = (color[j][i].red & 0xff00) >> 8; + green = (color[j][i].green & 0xff00) >> 8; + blue = (color[j][i].blue & 0xff00) >> 8; -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)); + /* + * the maxes should be at 255 already, + * but just in case... + */ + red = (main_red_max * red )/255; + green = (main_green_max * green)/255; + blue = (main_blue_max * blue )/255; - /* shift them over and or together for value */ - red = red << main_red_shift; - green = green << main_green_shift; - blue = 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)); - rgb[j][i] = red | green | blue; - } - } + /* shift them over and or together for value */ + red = red << main_red_shift; + green = green << main_green_shift; + blue = blue << main_blue_shift; - /* loop over the rectangles making up region8bpp */ - iter = sraRgnGetIterator(region8bpp); - while (sraRgnIteratorNext(iter, &rect)) { - double score, max_score = -1.0; - int n, m, best; - Window best_win = None; + rgb[j][i] = red | green | blue; + } + return 1; +} - 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; - } +static void do_8bpp_region(sraRect rect) { -if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps); + char *src, *dst; + unsigned int *ui; + unsigned char *uc; + int ps, pixelsize = bpp/8; - /* - * try to pick the "best" colormap to use for - * this rectangle (often wrong... let them - * iconify or move the trouble windows, etc.) - */ - best = -1; + int do_getimage = xgetimage_8to24; + int line, n_off, j, h, w; + unsigned int hi, idx; + XWindowAttributes attr; + XErrorHandler old_handler = NULL; - for (m=0; m < MAX_8BPP_WINDOWS; m++) { - int mx1, my1, mx2, my2; - int k, failed = 0; - if (windows_8bpp[m].win == None) { - continue; - } - if (windows_8bpp[m].map_state != IsViewable) { - continue; - } + double score, max_score = -1.0; + int m, best, best_depth = 0; + Window best_win = None; - /* see if XQueryColors failed: */ - for (k=0; k<ncmaps; k++) { - if (windows_8bpp[m].cmap == cmaps[k] - && cmap_failed[k]) { - failed = 1; - } - } - if (failed) { - continue; - } +if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps); - /* rectangle coords for this 8bpp win: */ - mx1 = windows_8bpp[m].x; - my1 = windows_8bpp[m].y; - mx2 = windows_8bpp[m].x + windows_8bpp[m].w; - my2 = windows_8bpp[m].y + windows_8bpp[m].h; + /* + * try to pick the "best" colormap to use for + * this rectangle (often wrong... let them + * iconify or move the trouble windows, etc.) + */ + best = -1; - /* use overlap as score: */ - score = rect_overlap(mx1, my1, mx2, my2, - rect.x1, rect.y1, rect.x2, rect.y2); + for (m=0; m < MAX_8BPP_WINDOWS; m++) { + int mx1, my1, mx2, my2; + int k, failed = 0; + if (windows_8bpp[m].win == None) { + continue; + } + if (windows_8bpp[m].map_state != IsViewable) { + continue; + } - if (score > max_score) { - max_score = score; - best = m; - best_win = windows_8bpp[m].win; - } + /* see if XQueryColors failed: */ + for (k=0; k<ncmaps; k++) { + if (windows_8bpp[m].cmap == cmaps[k] && cmap_failed[k]) { + failed = 1; + } + } + if (windows_8bpp[m].depth == 8 && failed) { + continue; + } + /* rectangle coords for this 8bpp win: */ + mx1 = windows_8bpp[m].x; + my1 = windows_8bpp[m].y; + mx2 = windows_8bpp[m].x + windows_8bpp[m].w; + my2 = windows_8bpp[m].y + windows_8bpp[m].h; + + /* use overlap as score: */ + score = rect_overlap(mx1, my1, mx2, my2, rect.x1, rect.y1, + rect.x2, rect.y2); + + if (score > max_score) { + max_score = score; + best = m; + 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 (best < 0) { - /* hmmm, use the first one then... */ - best = 0; - } else { - int ok = 0; - /* - * find the cmap corresponding to best window - * note we reset best from the windows_8bpp - * index to the cmaps[]. - */ - for (m=0; m < ncmaps; m++) { - if (cmaps[m] == windows_8bpp[best].cmap) { - ok = 1; - best = m; - } - } - if (! ok) { - best = 0; - } + if (best < 0) { + /* hmmm, use the first one then... */ + best = 0; + } else { + int ok = 0; + /* + * find the cmap corresponding to best window + * note we reset best from the windows_8bpp + * index to the cmaps[]. + */ + for (m=0; m < ncmaps; m++) { + if (cmaps[m] == windows_8bpp[best].cmap) { + ok = 1; + best = m; } + } + if (! ok) { + best = 0; + } + } 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: */ - n = main_bytes_per_line * rect.y1 + pixelsize * rect.x1; + /* now tranform the pixels in this rectangle: */ + n_off = main_bytes_per_line * rect.y1 + pixelsize * rect.x1; - src = cmap8to24_fb + n; - h = rect.y2 - rect.y1; - w = rect.x2 - rect.x1; + h = rect.y2 - rect.y1; + w = rect.x2 - rect.x1; - if (xgetimage_8to24 && best_win != None && - valid_window(best_win, &attr, 1)) { - /* experimental mode. */ - XImage *xi; - Window c; - XErrorHandler old_handler = NULL; - unsigned int wu, hu; - int xo, yo; - ps = 1; /* assume 8bpp */ + if (depth == 8) { + /* + * 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; + } + } - wu = (unsigned int) w; - hu = (unsigned int) h; + if (do_getimage && valid_window(best_win, &attr, 1)) { + XImage *xi; + Window c; + unsigned int wu, hu; + int xo, yo; - X_LOCK; - xtranslate(best_win, window, 0, 0, &xo, &yo, - &c, 1); - xo = rect.x1 - xo; - yo = rect.y1 - yo; + wu = (unsigned int) w; + hu = (unsigned int) h; + + X_LOCK; + xtranslate(best_win, window, 0, 0, &xo, &yo, &c, 1); + xo = rect.x1 - xo; + 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 (xo < 0 || yo < 0 || w > attr.width || - h > attr.height) { + + if (xo < 0 || yo < 0 || w > attr.width || h > attr.height) { + X_UNLOCK; if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n"); - X_UNLOCK; - continue; - } + return; + } - trapped_xerror = 0; - old_handler = XSetErrorHandler(trap_xerror); - xi = XGetImage(dpy, best_win, xo, yo, wu, hu, - AllPlanes, ZPixmap); - XSetErrorHandler(old_handler); - X_UNLOCK; + trapped_xerror = 0; + old_handler = XSetErrorHandler(trap_xerror); + /* FIXME: XGetSubImage? */ + xi = XGetImage(dpy, best_win, xo, yo, wu, hu, + AllPlanes, ZPixmap); + XSetErrorHandler(old_handler); + X_UNLOCK; - if (! xi || trapped_xerror) { - 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); - continue; - } 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); - } - trapped_xerror = 0; + if (! xi || trapped_xerror) { + trapped_xerror = 0; +if (db24 > 1) fprintf(stderr, "xi-fail: 0x%p trap=%d %d %d %d %d\n", (void *)xi, trapped_xerror, xo, yo, w, h); + return; + } else { +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; - if (xi->depth != 8) { - X_LOCK; - XDestroyImage(xi); - X_UNLOCK; + if (xi->depth != 8 && xi->depth != 24) { + X_LOCK; + XDestroyImage(xi); + X_UNLOCK; 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 ... */ - for (line = 0; line < xi->height; line++) { - /* pixel by pixel... */ - for (j = 0; j < xi->width; j++) { - unsigned char *uc; - uc = (unsigned char *) (src + ps * j); - ui = (unsigned int *) (dst+pixelsize*j); + /* line by line ... */ + for (line = 0; line < xi->height; line++) { + /* pixel by pixel... */ + for (j = 0; j < xi->width; j++) { + + uc = (unsigned char *) (src + ps1 * j); + ui = (unsigned int *) (dst + ps2 * j); idx = (int) (*uc); - hi = (*ui) & 0xff000000; - *ui = hi | rgb[best][idx]; -if (db24 > 2) histo[idx]++; - } - src += xi->bytes_per_line; - dst += main_bytes_per_line; + *ui = rgb[best][idx]; } + src += xi->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 */ + } - X_LOCK; - XDestroyImage(xi); - X_UNLOCK; + 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; + XDestroyImage(xi); + X_UNLOCK; + + } else if (! do_getimage) { + /* 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; + fac = 1; + src = cmap8to24_fb + n_off; + } + + /* line by line ... */ + for (line = 0; line < h; line++) { + /* pixel by pixel... */ + for (j = 0; j < w; j++) { + + /* grab 32 bit value */ + ui = (unsigned int *) (src + ps * j); + + /* extract top 8 bits (FIXME: masks?) */ + hi = (*ui) & 0xff000000; + + /* map to lookup index; rewrite pixel */ + idx = hi >> 24; + *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); - } else if (! xgetimage_8to24) { - /* normal mode. */ + /* create regions for finding overlap, etc. */ + disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y); + rect = sraRgnCreateRect(x1, y1, x2, y2); + region8bpp = sraRgnCreate(); - ps = pixelsize; - - /* line by line ... */ - for (line = 0; line < h; line++) { - /* pixel by pixel... */ - for (j = 0; j < w; j++) { + X_LOCK; + XFlush(dpy); /* make sure X server is up to date WRT input, etc */ + X_UNLOCK; - /* grab 32 bit value */ - ui = (unsigned int *) (src + ps * j); + 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; + } + } - /* extract top 8 bits (FIXME: masks?) */ - hi = (*ui) & 0xff000000; +if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} - /* map to lookup index; rewrite pixel */ - idx = hi >> 24; - *ui = hi | rgb[best][idx]; + 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]++; - } - 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); } @@ -868,13 +1079,26 @@ void mark_8bpp(void) { for (i=0; i < MAX_8BPP_WINDOWS; i++) { int x1, y1, x2, y2, w, h, f = 32; + f = 0; /* skip fuzz, may bring in other windows... */ if (windows_8bpp[i].win == None) { continue; } if (windows_8bpp[i].map_state != IsViewable) { - continue; + 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; + } + } else { + continue; + } } x1 = windows_8bpp[i].x; |