diff options
Diffstat (limited to 'x11vnc/8to24.c')
-rw-r--r-- | x11vnc/8to24.c | 2155 |
1 files changed, 0 insertions, 2155 deletions
diff --git a/x11vnc/8to24.c b/x11vnc/8to24.c deleted file mode 100644 index 30c3da2..0000000 --- a/x11vnc/8to24.c +++ /dev/null @@ -1,2155 +0,0 @@ -/* - Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com> - All rights reserved. - -This file is part of x11vnc. - -x11vnc is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or (at -your option) any later version. - -x11vnc is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with x11vnc; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA -or see <http://www.gnu.org/licenses/>. - -In addition, as a special exception, Karl J. Runge -gives permission to link the code of its release of x11vnc with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. -*/ - -/* -- 8to24.c -- */ -#include "x11vnc.h" -#include "cleanup.h" -#include "scan.h" -#include "util.h" -#include "win_utils.h" -#include "xwrappers.h" - -int multivis_count = 0; -int multivis_24count = 0; - -void check_for_multivis(void); -void bpp8to24(int, int, int, int); -void mark_8bpp(int); - -#if SKIP_8TO24 -void check_for_multivis(void) {} -void bpp8to24(int x, int y, int z, int t) {} -void mark_8bpp(int x) {} -#else -/* lots... */ - -static void set_root_cmap(void); -static int check_pointer_in_depth24(void); -static void parse_cmap8to24(void); -static void set_poll_fb(void); -static int check_depth(Window win, Window top, int doall); -static int check_depth_win(Window win, Window top, XWindowAttributes *attr); -static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w); -static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod); -static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod); -static int poll_8bpp(sraRegionPtr, int); -static void poll_8bpp_complement(sraRegionPtr); -static void mark_rgn_rects(sraRegionPtr mod); -static int get_8bpp_regions(int validate); -static int get_cmap(int j, Colormap cmap); -static void do_8bpp_region(int n, sraRegionPtr mark); -static XImage *cmap_xi(XImage *xi, Window win, int win_depth); -static void transform_rect(sraRect rect, Window win, int win_depth, int cm); - -/* struct for keeping info about the 8bpp windows: */ -typedef struct window8 { - Window win; - Window top; - int depth; - int x, y; - int w, h; - int map_state; - Colormap cmap; - Bool map_installed; - int fetched; - double last_fetched; - sraRegionPtr clip_region; -} window8bpp_t; - -enum mark_8bpp_modes { - MARK_8BPP_ALL = 0, - MARK_8BPP_POINTER, - MARK_8BPP_TOP -}; - - -#define NCOLOR 256 - -static Colormap root_cmap = 0; -static unsigned int *root_rgb = NULL; - -static void set_root_cmap(void) { -#if NO_X11 - RAWFB_RET_VOID - return; -#else - static time_t last_set = 0; - time_t now = time(NULL); - XWindowAttributes attr; - static XColor *color = NULL; - int redo = 0; - int ncolor = 0; - - RAWFB_RET_VOID - - if (depth > 16) { - ncolor = NCOLOR; - } else if (depth > 8) { - ncolor = 1 << depth; - } else { - ncolor = NCOLOR; - } - - if (!root_rgb) { - root_rgb = (unsigned int *) malloc(ncolor * sizeof(unsigned int)); - } - if (!color) { - color = (XColor *) malloc(ncolor * sizeof(XColor)); - } - - if (now > last_set + 10) { - redo = 1; - } - if (! root_cmap || redo) { - X_LOCK; - if (! valid_window(window, &attr, 1)) { - X_UNLOCK; - return; - } - if (attr.colormap) { - int i, ncells = ncolor; - - if (depth < 8) { - ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); - } - for (i=0; i < ncells; i++) { - color[i].pixel = i; - color[i].pad = 0; - } - last_set = now; - root_cmap = attr.colormap; - XQueryColors(dpy, root_cmap, color, ncells); - for (i=0; i < ncells; i++) { - unsigned int red, green, blue; - /* strip out highest 8 bits of values: */ - red = (color[i].red & 0xff00) >> 8; - green = (color[i].green & 0xff00) >> 8; - blue = (color[i].blue & 0xff00) >> 8; - - /* - * 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; - - /* store it in the array to be used later */ - root_rgb[i] = red | green | blue; - } - } - X_UNLOCK; - } -#endif /* NO_X11 */ -} - -/* 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 = 1; -static double poll_8to24_delay = POLL_8TO24_DELAY; -static double cache_win = 0.0; -static int level2_8to24 = 0; - -static int check_pointer_in_depth24(void) { - int tries = 0, in_24 = 0; - XWindowAttributes attr; - Window c, w; - double now = dnow(); - - c = window; - - RAWFB_RET(0) - - if (now > last_keyboard_time + 1.0 && now > last_pointer_time + 1.0) { - return 0; - } - - 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+1); - y2 = nfix(y2, dpy_y+1); - mark_rect_as_modified(x1, y1, x2, y2, 0); - -if (db24 > 1) fprintf(stderr, "check_pointer_in_depth24 %d %d %d %d\n", x1, y1, x2, y2); - - return 1; - } - return 0; -} - -static void parse_cmap8to24(void) { - if (cmap8to24_str) { - char *p, *str = strdup(cmap8to24_str); - p = strtok(str, ","); - /* defaults: */ - db24 = 0; - xgetimage_8to24 = 1; - poll_8to24_delay = POLL_8TO24_DELAY; - level2_8to24 = 0; - cache_win = 0.0; - while (p) { - if (strstr(p, "dbg=") == p) { - db24 = atoi(p + strlen("dbg=")); - } else if (strstr(p, "poll=") == p) { - poll_8to24_delay = atof(p + strlen("poll=")); - } else if (strstr(p, "cachewin=") == p) { - cache_win = atof(p + strlen("cachewin=")); - } else if (!strcmp(p, "nogetimage")) { - xgetimage_8to24 = 0; - } else if (!strcmp(p, "level2")) { - level2_8to24 = 1; - } - p = strtok(NULL, ","); - } - free(str); - } else { - if (getenv("DEBUG_8TO24") != NULL) { - db24 = atoi(getenv("DEBUG_8TO24")); - } - if (getenv("NOXGETIMAGE_8TO24") != NULL) { - xgetimage_8to24 = 0; - } - } -} - -static char *poll8_fb = NULL, *poll24_fb = NULL; -static int poll8_fb_w = 0, poll8_fb_h = 0; -static int poll24_fb_w = 0, poll24_fb_h = 0; - -static void pfb(int fac, char **fb, int *w, int *h) { - if (! *fb || *w != dpy_x || *h != dpy_y) { - if (*fb) { - free(*fb); - } - *fb = (char *) calloc(fac * dpy_x * dpy_y, 1); - *w = dpy_x; - *h = dpy_y; - } -} - -static void set_poll_fb(void) { - /* create polling framebuffers or recreate if too small. */ - - if (! xgetimage_8to24) { - return; /* this saves a bit of RAM */ - } - pfb(4, &poll24_fb, &poll24_fb_w, &poll24_fb_h); - if (depth > 8 && depth <= 16) { - pfb(2, &poll8_fb, &poll8_fb_w, &poll8_fb_h); /* 2X for rare 16bpp colormap case */ - } else { - pfb(1, &poll8_fb, &poll8_fb_w, &poll8_fb_h); - } -} - -int MV_glob = 0; -int MV_count; -int MV_hit; -double MV_start; - -void check_for_multivis(void) { -#if NO_X11 - RAWFB_RET_VOID - return; -#else - XWindowAttributes attr; - int doall = 0; - int k, i, cnt, diff; - static int first = 1; - static Window *stack_old = NULL; - static int stack_old_len = 0; - static double last_parse = 0.0; - static double last_update = 0.0; - static double last_clear = 0.0; - static double last_poll = 0.0; - static double last_fixup = 0.0; - static double last_call = 0.0; - static double last_query = 0.0; - double now = dnow(); - double delay; - - RAWFB_RET_VOID - - if (now > last_parse + 1.0) { - last_parse = now; - parse_cmap8to24(); - } -if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); - last_call = now; - - if (first) { - int i; - /* initialize 8bpp window table: */ - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - windows_8bpp[i].win = None; - windows_8bpp[i].top = None; - windows_8bpp[i].map_state = IsUnmapped; - windows_8bpp[i].cmap = (Colormap) 0; - windows_8bpp[i].fetched = 0; - windows_8bpp[i].last_fetched = -1.0; - windows_8bpp[i].clip_region = NULL; - } - set_poll_fb(); - - first = 0; - doall = 1; /* fetch everything first time */ - } - - if (wireframe_in_progress) { - return; - } - - set_root_cmap(); - - /* - * allocate an "old stack" list of all toplevels. we compare - * this to the current stack to guess stacking order changes. - */ - if (!stack_old || stack_old_len < stack_list_len) { - int n = stack_list_len; - if (n < 256) { - n = 256; - } - if (stack_old) { - free(stack_old); - } - stack_old = (Window *) calloc(n*sizeof(Window), 1); - stack_old_len = n; - } - - /* fill the old stack with visible windows: */ - cnt = 0; - for (k=0; k < stack_list_num; k++) { - if (stack_list[k].valid && - stack_list[k].map_state == IsViewable) { - stack_old[cnt++] = stack_list[k].win; - } - } - - /* snapshot + update the current stacking order: */ - /* TUNABLE */ - if (poll_8to24_delay >= POLL_8TO24_DELAY) { - delay = 3.0 * poll_8to24_delay; - } else { - delay = 3.0 * POLL_8TO24_DELAY; /* 0.15 */ - } - if (doall || now > last_update + delay) { - snapshot_stack_list(0, 0.0); - update_stack_list(); - last_update = now; - } - - /* look for differences in the visible toplevels: */ - diff = 0; - cnt = 0; - for (k=0; k < stack_list_num; k++) { - if (stack_list[k].valid && stack_list[k].map_state == - IsViewable) { - if (stack_old[cnt] != stack_list[k].win) { - diff = 1; - break; - } - cnt++; - } - } - - multivis_count = 0; - multivis_24count = 0; - - /* - * every 10 seconds we try to clean out and also refresh the window - * info in the 8bpp window table: - */ - if (now > last_clear + 10) { - last_clear = now; - X_LOCK; - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - Window w = windows_8bpp[i].win; - if (! valid_window(w, &attr, 1)) { - /* catch windows that went away: */ - windows_8bpp[i].win = None; - windows_8bpp[i].top = None; - windows_8bpp[i].map_state = IsUnmapped; - windows_8bpp[i].cmap = (Colormap) 0; - windows_8bpp[i].fetched = 0; - windows_8bpp[i].last_fetched = -1.0; - } - } - X_UNLOCK; - } - - MV_count = 0; - MV_hit = 0; - MV_start = dnow(); - - set_root_cmap(); - - /* loop over all toplevels, both 8 and 24 depths: */ - - X_LOCK; /* a giant lock around the whole activity */ - - for (k=0; k < stack_list_num; k++) { - Window r, parent; - Window *list0; - Status rc; - unsigned int nc0; - int i1; - XErrorHandler old_handler; - double delay; - - Window win = stack_list[k].win; - - /* TUNABLE */ - if (poll_8to24_delay >= POLL_8TO24_DELAY) { - delay = 1.5 * poll_8to24_delay; - } else { - delay = 1.5 * POLL_8TO24_DELAY; /* 0.075 */ - } - - if (now < last_query + delay) { - break; - } - - if (win == None) { - continue; - } - - if (stack_list[k].map_state != IsViewable) { - int i; - /* - * if the toplevel became unmapped, mark it - * for the children as well... - */ - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - if (windows_8bpp[i].top == win) { - windows_8bpp[i].map_state = - stack_list[k].map_state; - } - } - } - - if (check_depth(win, win, doall)) { - /* - * returns 1 if no need to recurse down e.g. It - * is 8bpp and we assume all lower ones are too. - */ - continue; - } - - /* we recurse up to two levels down from stack_list windows */ - - old_handler = XSetErrorHandler(trap_xerror); - trapped_xerror = 0; - rc = XQueryTree_wr(dpy, win, &r, &parent, &list0, &nc0); - XSetErrorHandler(old_handler); - - if (! rc || trapped_xerror) { - trapped_xerror = 0; - continue; - } - trapped_xerror = 0; - - /* loop over grandchildren of rootwin: */ - for (i1=0; i1 < (int) nc0; i1++) { - Window win1 = list0[i1]; - Window *list1; - unsigned int nc1; - int i2; - - if (check_depth(win1, win, doall)) { - continue; - } - - if (level2_8to24) { - continue; - } - - old_handler = XSetErrorHandler(trap_xerror); - trapped_xerror = 0; - rc = XQueryTree_wr(dpy, win1, &r, &parent, &list1, &nc1); - XSetErrorHandler(old_handler); - - if (! rc || trapped_xerror) { - trapped_xerror = 0; - continue; - } - trapped_xerror = 0; - - /* loop over great-grandchildren of rootwin: */ - for (i2=0; i2< (int) nc1; i2++) { - Window win2 = list1[i2]; - - if (check_depth(win2, win, doall)) { - continue; - } - /* more? Which wm does this? */ - } - if (nc1) { - XFree_wr(list1); - } - } - if (nc0) { - XFree_wr(list0); - } - } - X_UNLOCK; - - last_query = dnow(); - -MV_glob += MV_count; -if (0) fprintf(stderr, "MV_count: %d hit: %d %.4f %10.2f\n", MV_count, MV_hit, last_query - MV_start, MV_glob / (last_query - x11vnc_start)); - - if (screen_fixup_8 > 0.0 && now > last_fixup + screen_fixup_8) { - last_fixup = now; - mark_8bpp(MARK_8BPP_ALL); - last_poll = now; - - } else if (poll_8to24_delay > 0.0) { - int area = -1; - int validate = 0; - - if (diff && multivis_count) { - validate = 1; - } - if (now > last_poll + poll_8to24_delay) { - sraRegionPtr mod; - - last_poll = now; - mod = sraRgnCreate(); - area = poll_8bpp(mod, validate); - if (depth == 24) { - poll_8bpp_complement(mod); - } - mark_rgn_rects(mod); - sraRgnDestroy(mod); - } - if (0 && area < dpy_x * dpy_y / 2 && diff && multivis_count) { - mark_8bpp(MARK_8BPP_POINTER); - last_poll = now; - } - - } else if (diff && multivis_count) { - mark_8bpp(MARK_8BPP_ALL); - last_poll = now; - - } else if (depth <= 16 && multivis_24count) { - static double last_check = 0.0; - if (now > last_check + 0.4) { - last_check = now; - if (check_pointer_in_depth24()) { - last_poll = now; - } - } - } -if (0) fprintf(stderr, "done: %.4f\n", dnow() - last_query); -#endif /* NO_X11 */ -} - -#define VW_CACHE_MAX 1024 -static XWindowAttributes vw_cache_attr[VW_CACHE_MAX]; -static Window vw_cache_win[VW_CACHE_MAX]; - -static void set_attr(XWindowAttributes *attr, int j) { - memcpy((void *) (vw_cache_attr+j), (void *) attr, - sizeof(XWindowAttributes)); -} -#if 0 -static int get_attr(XWindowAttributes *attr, int j) { - memcpy((void *) attr, (void *) (vw_cache_attr+j), - sizeof(XWindowAttributes)); - return 1; -} -#endif - -static XWindowAttributes wattr; - -static XWindowAttributes *vw_lookup(Window win) { - static double last_purge = 0.0; - double now; - int i, j, k; - - if (win == None) { - return NULL; - } - - now = dnow(); - if (now > last_purge + cache_win) { - last_purge = now; - for (i=0; i<VW_CACHE_MAX; i++) { - vw_cache_win[i] = None; - } - } - - j = -1; - k = -1; - for (i=0; i<VW_CACHE_MAX; i++) { - if (vw_cache_win[i] == win) { - j = i; - break; - } else if (vw_cache_win[i] == None) { - k = i; - break; - } - } - - if (j >= 0) { -MV_hit++; - return vw_cache_attr+j; - - } else if (k >= 0) { - XWindowAttributes attr2; - int rc = valid_window(win, &attr2, 1); - if (rc) { - vw_cache_win[k] = win; - set_attr(&attr2, k); - return vw_cache_attr+k; - } else { - return NULL; - } - } else { - /* Full */ - int rc = valid_window(win, &wattr, 1); - if (rc) { - return &wattr; - } else { - return NULL; - } - } -} - -static int check_depth(Window win, Window top, int doall) { - XWindowAttributes attr, *pattr; - - /* first see if it is (still) a valid window: */ -MV_count++; - - if (cache_win > 0.0) { - pattr = vw_lookup(win); - if (pattr == NULL) { - return 1; /* indicate done */ - } - } else { - if (! valid_window(win, &attr, 1)) { - return 1; /* indicate done */ - } - pattr = &attr; - } - - if (! doall && pattr->map_state != IsViewable) { - /* - * store results anyway... this may lead to table - * filling up, but currently this allows us to update - * state of onetime mapped windows. - */ - check_depth_win(win, top, pattr); - return 1; /* indicate done */ - } else if (check_depth_win(win, top, pattr)) { - return 1; /* indicate done */ - } else { - return 0; /* indicate not done */ - } -} - -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 > 0) { - if (depth == 24 && attr->depth != 24) { - store_it = 1; - } else if (depth <= 16 && root_cmap && attr->colormap != root_cmap) { - store_it = 1; - } - } - - if (store_it) { - int i, j = -1, none = -1, nomap = -1; - int newc = 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); - } - - /* try to find a table slot for this window: */ - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - if (none < 0 && windows_8bpp[i].win == None) { - /* found first None */ - none = i; - } - if (windows_8bpp[i].win == win) { - /* found myself */ - j = i; - break; - } - if (nomap < 0 && windows_8bpp[i].win != None && - windows_8bpp[i].map_state != IsViewable) { - /* found first unmapped */ - nomap = i; - } - } - if (j < 0) { - if (attr->map_state != IsViewable) { - /* no slot and not visible: not worth keeping */ - return 1; - } else if (none >= 0) { - /* put it in the first None slot */ - j = none; - newc = 1; - } else if (nomap >=0) { - /* put it in the first unmapped slot */ - j = nomap; - } - /* otherwise we cannot store it... */ - } - -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 (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; - windows_8bpp[j].map_state = attr->map_state; - windows_8bpp[j].cmap = attr->colormap; - windows_8bpp[j].map_installed = attr->map_installed; - windows_8bpp[j].w = attr->width; - windows_8bpp[j].h = attr->height; - windows_8bpp[j].fetched = 1; - windows_8bpp[j].last_fetched = dnow(); - - /* translate x y to be WRT the root window (not parent) */ - xtranslate(win, window, 0, 0, &x, &y, &w, 1); - windows_8bpp[j].x = x; - windows_8bpp[j].y = y; - - if (newc || now_vis) { -if (db24) fprintf(stderr, "new/now_vis: 0x%lx %d/%d\n", win, newc, now_vis); - /* mark it immediately if a new one: */ - X_UNLOCK; /* dont forget the giant lock */ - mark_rect_as_modified(x, y, x + attr->width, - y + attr->height, 0); - X_LOCK; - } - } else { - /* - * Error: could not find a slot. - * perhaps keep age and expire old ones?? - */ -if (db24) fprintf(stderr, "multivis: CANNOT STORE 0x%lx j=%d\n", win, j); - for (i=0; i < MAX_8BPP_WINDOWS; i++) { -if (db24 > 1) fprintf(stderr, " ------------ 0x%lx i=%d\n", windows_8bpp[i].win, i); - } - - } - return 1; - } - return 0; -} - -/* polling line XImage */ -static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w) { - RAWFB_RET(NULL) - -#if NO_X11 - if (!xi || !visual || !win_depth || !w) {} - return NULL; -#else - if (xi == NULL || *w < dpy_x) { - char *d; - if (xi) { - XDestroyImage(xi); - } - if (win_depth != 24) { - if (win_depth > 8) { - d = (char *) malloc(dpy_x * 2); - } else { - d = (char *) malloc(dpy_x * 1); - } - } else { - d = (char *) malloc(dpy_x * 4); - } - *w = dpy_x; - xi = XCreateImage(dpy, visual, win_depth, ZPixmap, 0, d, - dpy_x, 1, 8, 0); - } - return xi; -#endif /* NO_X11 */ -} - -static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) { -#if NO_X11 - RAWFB_RET(1) - if (!x1 || !x2 || !y1 || !n || !mod) {} - return 1; -#else - int fac, n_off, w, xo, yo; - char *poll_fb, *dst, *src; - int w2, xl, xh, stride = 32; - int inrun = 0, rx1 = -1, rx2 = -1; - - static XImage *xi8 = NULL, *xi24 = NULL, *xi_r; - static int xi8_w = 0, xi24_w = 0; - - XErrorHandler old_handler = NULL; - XImage *xi; - Window c, win = windows_8bpp[n].win; - - static XWindowAttributes attr; - static Window last_win = None; - static double last_time = 0.0; - double now; - - sraRegionPtr rect; - int mx1, mx2, my1, my2; - int ns = NSCAN/2; - - RAWFB_RET(1) - - if (win == None) { - return 1; - } - if (windows_8bpp[n].map_state != IsViewable) { - return 1; - } - if (! xgetimage_8to24) { - return 1; - } - - X_LOCK; - now = dnow(); - if (last_win != None && win == last_win && now < last_time + 0.5) { - ; /* use previous attr */ - } else { - if (! valid_window(win, &attr, 1)) { - X_UNLOCK; - last_win = None; - return 0; - } - last_time = now; - last_win = win; - } - - if (attr.depth > 16 && attr.depth != 24) { - X_UNLOCK; - return 1; - } else if (attr.depth <= 16) { - xi = xi8 = p_xi(xi8, attr.visual, attr.depth, &xi8_w); - - poll_fb = poll8_fb; - if (attr.depth > 8) { - fac = 2; - } else { - fac = 1; - } - n_off = poll8_fb_w * y1 + x1; - } else { - xi = xi24 = p_xi(xi24, attr.visual, 24, &xi24_w); - - poll_fb = poll24_fb; - fac = 4; - n_off = poll24_fb_w * y1 + x1; - } - - old_handler = XSetErrorHandler(trap_xerror); - trapped_xerror = 0; - - /* xtranslate() not used to save two XSetErrorHandler calls */ - XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c); - - xo = x1 - xo; - yo = y1 - yo; - w = x2 - x1; - - if (trapped_xerror || xo < 0 || yo < 0 || xo + w > attr.width) { -if (db24 > 2) fprintf(stderr, "avoid bad match...\n"); - XSetErrorHandler(old_handler); - trapped_xerror = 0; - X_UNLOCK; - return 0; - } - - trapped_xerror = 0; - xi_r = XGetSubImage(dpy, win, xo, yo, w, 1, AllPlanes, ZPixmap, xi, - 0, 0); - XSetErrorHandler(old_handler); - - X_UNLOCK; - - if (! xi_r || trapped_xerror) { - trapped_xerror = 0; - return 0; - } - trapped_xerror = 0; - - src = xi->data; - dst = poll_fb + fac * n_off; - - inrun = 0; - - xl = x1; - while (xl < x2) { - xh = xl + stride; - if (xh > x2) { - xh = x2; - } - w2 = xh - xl; - if (memcmp(dst, src, fac * w2)) { - if (inrun) { - rx2 = xh; - } else { - rx1 = xl; - rx2 = xh; - inrun = 1; - } - } else { - if (inrun) { - mx1 = rx1; - mx2 = rx2; - my1 = nfix(y1 - ns, dpy_y); - my2 = nfix(y1 + ns, dpy_y+1); - - rect = sraRgnCreateRect(mx1, my1, mx2, my2); - sraRgnOr(mod, rect); - sraRgnDestroy(rect); - inrun = 0; - } - } - - xl += stride; - dst += fac * stride; - src += fac * stride; - } - - if (inrun) { - mx1 = rx1; - mx2 = rx2; - my1 = nfix(y1 - ns, dpy_y); - my2 = nfix(y1 + ns, dpy_y+1); - - rect = sraRgnCreateRect(mx1, my1, mx2, my2); - sraRgnOr(mod, rect); - sraRgnDestroy(rect); - } - return 1; -#endif /* NO_X11 */ -} - -static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod) { - int n_off, w, xl, xh, stride = 32; - char *dst, *src; - int inrun = 0, rx1 = -1, rx2 = -1; - sraRegionPtr rect; - int mx1, mx2, my1, my2; - int ns = NSCAN/2; - - if (depth != 24) { - return; - } - if (! cmap8to24_fb) { - return; - } - if (! xgetimage_8to24) { - return; - } - - n_off = main_bytes_per_line * y1 + 4 * x1; - - src = main_fb + n_off; - dst = cmap8to24_fb + n_off; - - inrun = 0; - - xl = x1; - while (xl < x2) { - xh = xl + stride; - if (xh > x2) { - xh = x2; - } - w = xh - xl; - if (memcmp(dst, src, 4 * w)) { - if (inrun) { - rx2 = xh; - } else { - rx1 = xl; - rx2 = xh; - inrun = 1; - } - } else { - if (inrun) { - mx1 = rx1; - mx2 = rx2; - my1 = nfix(y1 - ns, dpy_y); - my2 = nfix(y1 + ns, dpy_y+1); - - rect = sraRgnCreateRect(mx1, my1, mx2, my2); - sraRgnOr(mod, rect); - sraRgnDestroy(rect); - - inrun = 0; - } - } - - xl += stride; - dst += 4 * stride; - src += 4 * stride; - } - - if (inrun) { - mx1 = rx1; - mx2 = rx2; - my1 = nfix(y1 - ns, dpy_y); - my2 = nfix(y1 + ns, dpy_y+1); - - rect = sraRgnCreateRect(mx1, my1, mx2, my2); - sraRgnOr(mod, rect); - sraRgnDestroy(rect); - - inrun = 0; - } -} - -#define CMAPMAX 64 -static Colormap cmaps[CMAPMAX]; -static int ncmaps; - -static int poll_8bpp(sraRegionPtr mod, int validate) { - int i, y, ysh, map_count; - static int ycnt = 0; - sraRegionPtr line; - sraRect rect; - sraRectangleIterator *iter; - int br = 0, area = 0; - static double last_call = 0.0; - - map_count = get_8bpp_regions(validate); - -if (db24 > 1) fprintf(stderr, "poll_8bpp mc: %d\n", map_count); - - if (! map_count) { - return 0; - } - - set_poll_fb(); - - ysh = scanlines[(ycnt++) % NSCAN]; -if (db24 > 2) fprintf(stderr, "poll_8bpp: ysh: %2d %.4f\n", ysh, dnow() - last_call); - last_call = dnow(); - - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - sraRegionPtr reg = windows_8bpp[i].clip_region; - - if (! reg || sraRgnEmpty(reg)) { - continue; - } - y = ysh; - while (y < dpy_y) { - line = sraRgnCreateRect(0, y, dpy_x, y+1); - - if (sraRgnAnd(line, reg)) { - iter = sraRgnGetIterator(line); - while (sraRgnIteratorNext(iter, &rect)) { - if (! poll_line(rect.x1, rect.x2, - rect.y1, i, mod)) { - br = 1; - break; /* exception */ - } - } - sraRgnReleaseIterator(iter); - } - - sraRgnDestroy(line); - y += NSCAN; - if (br) break; - } - if (br) break; - } - - iter = sraRgnGetIterator(mod); - while (sraRgnIteratorNext(iter, &rect)) { - area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1)); - } - sraRgnReleaseIterator(iter); - - return area; -} - -static void poll_8bpp_complement(sraRegionPtr mod) { - int i, y, ysh; - static int ycnt = 0; - sraRegionPtr disp, line; - sraRect rect; - sraRectangleIterator *iter; - - disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - - ysh = scanlines[(ycnt++) % NSCAN]; - - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - sraRegionPtr reg = windows_8bpp[i].clip_region; - - if (! reg) { - continue; - } - if (windows_8bpp[i].map_state != IsViewable) { - continue; - } - sraRgnSubtract(disp, reg); - } - - y = ysh; - while (y < dpy_y) { - line = sraRgnCreateRect(0, y, dpy_x, y+1); - - if (sraRgnAnd(line, disp)) { - iter = sraRgnGetIterator(line); - while (sraRgnIteratorNext(iter, &rect)) { - poll_line_complement(rect.x1, rect.x2, - rect.y1, mod); - } - sraRgnReleaseIterator(iter); - } - - sraRgnDestroy(line); - - y += NSCAN; - } - - sraRgnDestroy(disp); -} - -static void mark_rgn_rects(sraRegionPtr mod) { - sraRect rect; - sraRectangleIterator *iter; - int area = 0; - - if (sraRgnEmpty(mod)) { - return; - } - - iter = sraRgnGetIterator(mod); - while (sraRgnIteratorNext(iter, &rect)) { - mark_rect_as_modified(rect.x1, rect.y1, rect.x2, rect.y2, 0); - area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1)); - } - sraRgnReleaseIterator(iter); - -if (db24 > 1) fprintf(stderr, " mark_rgn_rects area: %d\n", area); -} - -static int get_8bpp_regions(int validate) { - - XWindowAttributes attr; - int i, k, mapcount = 0; - - /* initialize color map list */ - ncmaps = 0; - for (i=0; i < CMAPMAX; i++) { - cmaps[i] = (Colormap) 0; - } - - /* loop over the table of 8bpp windows: */ - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - sraRegionPtr tmp_reg, tmp_reg2; - Window c, w = windows_8bpp[i].win; - int x, y; - - if (windows_8bpp[i].clip_region) { - sraRgnDestroy(windows_8bpp[i].clip_region); - } - windows_8bpp[i].clip_region = NULL; - - if (w == None) { - continue; - } - -if (db24 > 1) fprintf(stderr, "get_8bpp_regions: 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... - */ - - X_LOCK; - if (! valid_window(w, &attr, 1)) { - X_UNLOCK; - windows_8bpp[i].win = None; - windows_8bpp[i].top = None; - windows_8bpp[i].map_state = IsUnmapped; - windows_8bpp[i].cmap = (Colormap) 0; - windows_8bpp[i].fetched = 0; - windows_8bpp[i].last_fetched = -1.0; - continue; - } - X_UNLOCK; - - windows_8bpp[i].depth = attr.depth; - windows_8bpp[i].map_state = attr.map_state; - windows_8bpp[i].cmap = attr.colormap; - windows_8bpp[i].map_installed = attr.map_installed; - windows_8bpp[i].w = attr.width; - windows_8bpp[i].h = attr.height; - windows_8bpp[i].fetched = 1; - windows_8bpp[i].last_fetched = dnow(); - - if (attr.map_state != IsViewable) { - continue; - } - - X_LOCK; - xtranslate(w, window, 0, 0, &x, &y, &c, 1); - X_UNLOCK; - windows_8bpp[i].x = x; - windows_8bpp[i].y = y; - - } else { - /* this will be faster: no call to X server: */ - if (windows_8bpp[i].map_state != IsViewable) { - continue; - } - attr.depth = windows_8bpp[i].depth; - attr.map_state = windows_8bpp[i].map_state; - attr.colormap = windows_8bpp[i].cmap; - attr.map_installed = windows_8bpp[i].map_installed; - attr.width = windows_8bpp[i].w; - attr.height = windows_8bpp[i].h; - - x = windows_8bpp[i].x; - y = windows_8bpp[i].y; - } - - mapcount++; - - /* tmp region for this 8bpp rectangle: */ - tmp_reg = sraRgnCreateRect(nfix(x, dpy_x), nfix(y, dpy_y), - nfix(x + attr.width, dpy_x+1), nfix(y + attr.height, dpy_y+1)); - - /* loop over all toplevels, top to bottom clipping: */ - for (k = stack_list_num - 1; k >= 0; k--) { - Window swin = stack_list[k].win; - int sx, sy, sw, sh; - -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 skip the rest. */ -if (db24 > 1) fprintf(stderr, "found top: 0x%lx %d iv=%d\n", swin, k, stack_list[k].map_state); - break; - } - if (stack_list[k].map_state != IsViewable) { - /* skip unmapped ones: */ - continue; - } - - /* make a temp rect for this toplevel: */ - sx = stack_list[k].x; - sy = stack_list[k].y; - 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+1), - nfix(sy + sh, dpy_y+1)); - - /* subtract it from the 8bpp window region */ - sraRgnSubtract(tmp_reg, tmp_reg2); - - sraRgnDestroy(tmp_reg2); - - if (sraRgnEmpty(tmp_reg)) { - break; - } - } - - if (sraRgnEmpty(tmp_reg)) { - /* skip this 8bpp if completely clipped away: */ - sraRgnDestroy(tmp_reg); - continue; - } - - /* otherwise, store any new colormaps: */ - if (ncmaps < CMAPMAX && attr.colormap != (Colormap) 0) { - int m, seen = 0; - for (m=0; m < ncmaps; m++) { - if (cmaps[m] == attr.colormap) { - seen = 1; - break; - } - } - if (!seen && attr.depth <= 16) { - /* store only new ones: */ - cmaps[ncmaps++] = attr.colormap; - } - } - - windows_8bpp[i].clip_region = tmp_reg; - } - - return mapcount; -} - -static XColor *color[CMAPMAX]; -static unsigned int *rgb[CMAPMAX]; -static int cmap_failed[CMAPMAX]; -static int color_init = 0; -int histo[65536]; - -static int get_cmap(int j, Colormap cmap) { -#if NO_X11 - RAWFB_RET(0) - if (!j || !cmap) {} - return 0; -#else - int i, ncells, ncolor; - XErrorHandler old_handler = NULL; - - RAWFB_RET(0) - - if (depth > 16) { - /* 24 */ - ncolor = NCOLOR; - } else if (depth > 8) { - ncolor = 1 << depth; - } else { - ncolor = NCOLOR; - } - if (!color_init) { - int cm; - for (cm = 0; cm < CMAPMAX; cm++) { - color[cm] = (XColor *) malloc(ncolor * sizeof(XColor)); - rgb[cm] = (unsigned int *) malloc(ncolor * sizeof(unsigned int)); - } - color_init = 1; - } - - if (depth <= 16) { - /* not working properly for depth 24... */ - X_LOCK; - ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); - X_UNLOCK; - } else { - ncells = NCOLOR; - } - - if (depth > 16) { - ; - } else if (ncells > ncolor) { - ncells = ncolor; - } else if (ncells == 8 && depth != 3) { - /* XXX. see set_colormap() */ - ncells = 1 << depth; - } - - /* initialize XColor array: */ - for (i=0; i < ncells; i++) { - color[j][i].pixel = i; - color[j][i].pad = 0; - } -if (db24 > 1) fprintf(stderr, "get_cmap: %d 0x%x ncolor=%d ncells=%d\n", j, (unsigned int) cmap, ncolor, ncells); - - /* 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; - - if (trapped_xerror) { - trapped_xerror = 0; - return 0; - } - trapped_xerror = 0; - - /* 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; - - /* - * 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; - -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 */ - red = red << main_red_shift; - green = green << main_green_shift; - blue = blue << main_blue_shift; - - /* store it in the array to be used later */ - rgb[j][i] = red | green | blue; - } - return 1; -#endif /* NO_X11 */ -} - -static void do_8bpp_region(int n, sraRegionPtr mark) { - int k, cm = -1, failed = 0; - sraRectangleIterator *iter; - sraRegionPtr clip; - sraRect rect; - - if (! windows_8bpp[n].clip_region) { - return; - } - if (windows_8bpp[n].win == None) { - return; - } - if (windows_8bpp[n].map_state != IsViewable) { - return; - } -if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps); - - /* see if XQueryColors failed: */ - for (k=0; k<ncmaps; k++) { - if (windows_8bpp[n].cmap == cmaps[k]) { - cm = k; - if (cmap_failed[k]) { - failed = 1; - } - break; - } - } - - if (windows_8bpp[n].depth != 24) { /* 24 won't have a cmap */ - if (failed || cm == -1) { - return; - } - } - - clip = sraRgnCreateRgn(mark); - sraRgnAnd(clip, windows_8bpp[n].clip_region); - - /* loop over the rectangles making up region */ - iter = sraRgnGetIterator(clip); - 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; - } - - transform_rect(rect, windows_8bpp[n].win, - windows_8bpp[n].depth, cm); - } - sraRgnReleaseIterator(iter); - sraRgnDestroy(clip); -} - -static XImage *cmap_xi(XImage *xi, Window win, int win_depth) { -#if NO_X11 - if (!xi || !win || !win_depth) {} - return NULL; -#else - XWindowAttributes attr; - char *d; - - if (xi) { - XDestroyImage(xi); - } - if (! dpy || ! valid_window(win, &attr, 1)) { - return (XImage *) NULL; - } - if (win_depth == 24) { - d = (char *) malloc(dpy_x * dpy_y * 4); - } else if (win_depth <= 16) { - if (win_depth > 8) { - d = (char *) malloc(dpy_x * dpy_y * 2); - } else { - d = (char *) malloc(dpy_x * dpy_y * 1); - } - } else { - return (XImage *) NULL; - } - return XCreateImage(dpy, attr.visual, win_depth, ZPixmap, 0, d, dpy_x, dpy_y, 8, 0); -#endif /* NO_X11 */ -} - - -static void transform_rect(sraRect rect, Window win, int win_depth, int cm) { -#if NO_X11 - RAWFB_RET_VOID - if (!rect.x1 || !win || !win_depth || !cm) {} - return; -#else - - char *src, *dst, *poll; - unsigned int *ui; - unsigned short *us; - unsigned char *uc; - int ps, pixelsize = bpp/8; - int poll_Bpl; - - int do_getimage = xgetimage_8to24; - int line, n_off, j, h, w; - unsigned int hi, idx; - XWindowAttributes attr; - XErrorHandler old_handler = NULL; - -if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rect.y1, rect.x2, rect.y2, cm); - - RAWFB_RET_VOID - - attr.width = 0; - attr.height = 0; - - /* now transform the pixels in this rectangle: */ - n_off = main_bytes_per_line * rect.y1 + pixelsize * rect.x1; - - h = rect.y2 - rect.y1; - w = rect.x2 - rect.x1; - - if (depth != 24) { - /* need to fetch depth 24 data. */ - do_getimage = 1; - } - -#if 0 - if (do_getimage) { - X_LOCK; - vw = valid_window(win, &attr, 1); - X_UNLOCK; - } - - if (do_getimage && vw) { -#else - if (do_getimage) { -#endif - static XImage *xi_8 = NULL; - static XImage *xi_24 = NULL; - XImage *xi = NULL, *xi_r; - Window c; - unsigned int wu, hu; - int xo, yo; - - wu = (unsigned int) w; - hu = (unsigned int) h; - - X_LOCK; -#define GETSUBIMAGE -#ifdef GETSUBIMAGE - if (win_depth == 24) { - if (xi_24 == NULL || xi_24->width != dpy_x || - xi_24->height != dpy_y) { - xi_24 = cmap_xi(xi_24, win, 24); - } - xi = xi_24; - } else if (win_depth <= 16) { - if (xi_8 == NULL || xi_8->width != dpy_x || - xi_8->height != dpy_y) { - if (win_depth > 8) { - /* XXX */ - xi_8 = cmap_xi(xi_8, win, 16); - } else { - xi_8 = cmap_xi(xi_8, win, 8); - } - } - xi = xi_8; - } -#endif - - if (xi == NULL) { - rfbLog("transform_rect: xi is NULL\n"); - X_UNLOCK; - clean_up_exit(1); - } - - old_handler = XSetErrorHandler(trap_xerror); - trapped_xerror = 0; - - XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c); - - 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 (trapped_xerror || xo < 0 || yo < 0) { - /* w > attr.width || h > attr.height */ - XSetErrorHandler(old_handler); - X_UNLOCK; - trapped_xerror = 0; -if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n"); - return; - } - trapped_xerror = 0; - -#ifndef GETSUBIMAGE - xi = XGetImage(dpy, win, xo, yo, wu, hu, AllPlanes, ZPixmap); - xi_r = xi; -#else - xi_r = XGetSubImage(dpy, win, xo, yo, wu, hu, AllPlanes, - ZPixmap, xi, 0, 0); -#endif - XSetErrorHandler(old_handler); - - X_UNLOCK; - - if (! xi_r || 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 > 16 && xi->depth != 24) { -#ifndef GETSUBIMAGE - X_LOCK; - XDestroyImage(xi); - X_UNLOCK; -#endif -if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); - return; - } - - set_poll_fb(); - - if (xi->depth == 24) { - /* line by line ... */ - int ps1 = 4, fac; - if (depth <= 8) { - fac = 4; - } else if (depth <= 16) { - fac = 2; - } else { - fac = 1; /* will not happen 24 on 24 */ - } - - src = xi->data; - dst = cmap8to24_fb + fac * n_off; - - poll = poll24_fb + (poll24_fb_w * rect.y1 + rect.x1) * 4; - poll_Bpl = poll24_fb_w * 4; - - for (line = 0; line < h; line++) { - memcpy(dst, src, w * ps1); - memcpy(poll, src, w * ps1); - - src += xi->bytes_per_line; - dst += main_bytes_per_line * fac; - poll += poll_Bpl; - } - } else if (xi->depth <= 16) { - int ps1, ps2, fac; - - if (depth <= 8) { - ps1 = 1; - ps2 = 4; - fac = 4; - } else if (depth <= 16) { - ps1 = 2; - ps2 = 4; - fac = 4; - } else { - /* should be 24 case */ - ps1 = 1; - ps2 = pixelsize; - fac = 1; - } - - src = xi->data; - dst = cmap8to24_fb + (fac/ps1) * n_off; - - poll = poll8_fb + poll8_fb_w * rect.y1 * ps1 + rect.x1 * ps1; - poll_Bpl = poll8_fb_w * ps1; - - /* line by line ... */ - for (line = 0; line < h; line++) { - /* pixel by pixel... */ - for (j = 0; j < w; j++) { - if (ps1 == 2) { - unsigned short *ptmp; - us = (unsigned short *) (src + ps1 * j); - idx = (int) (*us); - ptmp = (unsigned short *) (poll + ps1 * j); - *ptmp = *us; - } else { - uc = (unsigned char *) (src + ps1 * j); - idx = (int) (*uc); - *(poll + ps1 * j) = *uc; - } - ui = (unsigned int *) (dst + ps2 * j); - *ui = rgb[cm][idx]; - - } - src += xi->bytes_per_line; - dst += main_bytes_per_line * (fac/ps1); - poll += poll_Bpl; - } - } - -#ifndef GETSUBIMAGE - X_LOCK; - XDestroyImage(xi); - X_UNLOCK; -#endif - - } else if (! do_getimage) { - int fac; - - if (depth <= 16) { - /* cooked up depth 24 TrueColor */ - /* but currently disabled (high bits no useful?) */ - ps = 4; - fac = 4; - /* XXX not correct for depth > 8, but do we ever come here in that case? */ - 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[cm][idx]; - } - src += main_bytes_per_line * fac; - } - } -#endif /* NO_X11 */ -} - -void bpp8to24(int x1, int y1, int x2, int y2) { - char *src, *dst; - unsigned char *uc; - unsigned short *us; - unsigned int *ui; - int idx, pixelsize = bpp/8; - int line, k, i, j, h, w; - int n_off; - sraRegionPtr rect; - int validate = 1; - static int last_map_count = 0, call_count = 0; - static double last_get_8bpp_validate = 0.0; - static double last_snapshot = 0.0; - double now; - double dt, d0 = 0.0, t2; - - RAWFB_RET_VOID - - if (! cmap8to24 || ! cmap8to24_fb) { - /* hmmm, why were we called? */ - return; - } - -if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, dnow() - last_get_8bpp_validate); - - call_count++; - - /* clip to display just in case: */ - if (!ncache) { - x1 = nfix(x1, dpy_x); - y1 = nfix(y1, dpy_y); - x2 = nfix(x2, dpy_x+1); - y2 = nfix(y2, dpy_y+1); - } - - if (wireframe_in_progress) { - /* - * draw_box() manages cmap8to24_fb for us so we get out as - * soon as we can. No need to cp main_fb -> cmap8to24_fb. - */ - return; - } - - /* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */ - - h = y2 - y1; - w = x2 - x1; - - 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; - } - } else if (depth <= 16) { - /* need to cook up to depth 24 TrueColor */ - int ps1 = 1, ps2 = 4; - if (depth > 8) { - ps1 = 2; - } - - /* pixelsize = 1, 2 */ - n_off = main_bytes_per_line * y1 + pixelsize * x1; - - src = main_fb + n_off; - dst = cmap8to24_fb + (4/ps1) * n_off; - - set_root_cmap(); - if (root_cmap) { -#if 0 - unsigned int hi; -#endif - - /* line by line ... */ - for (line = 0; line < h; line++) { - /* pixel by pixel... */ - for (j = 0; j < w; j++) { - if (ps1 == 2) { - us = (unsigned short *) (src + ps1 * j); - idx = (int) (*us); - } else { - uc = (unsigned char *) (src + ps1 * j); - idx = (int) (*uc); - } - ui = (unsigned int *) (dst + ps2 * j); - -if (0 && line % 100 == 0 && j % 32 == 0) fprintf(stderr, "%d %d %u x1=%d y1=%d\n", line, j, root_rgb[idx], x1, y1); -#if 0 - if (do_hibits) { - hi = idx << 24; - *ui = hi | rgb[0][idx]; - } else { - } -#endif - *ui = root_rgb[idx]; -if (db24 > 2) histo[idx]++; - } - src += main_bytes_per_line; - dst += main_bytes_per_line * (4/ps1); - } - } - - } - - 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;}} - - now = dnow(); - dt = now - last_get_8bpp_validate; - /* TUNABLES */ - if (dt < 0.003) { - ; /* XXX does this still give painting errors? */ - } else { - int snapit = 0; - double delay1, delay2, delay3; - if (poll_8to24_delay >= POLL_8TO24_DELAY) { - delay1 = 1.0 * poll_8to24_delay; - delay2 = 2.0 * poll_8to24_delay; - delay3 = 10. * poll_8to24_delay; - } else { - delay1 = 1.0 * POLL_8TO24_DELAY; /* 0.05 */ - delay2 = 2.0 * POLL_8TO24_DELAY; /* 0.1 */ - delay3 = 10. * POLL_8TO24_DELAY; /* 0.5 */ - } - if (cache_win > 1.0) { - delay2 *= 2; - delay3 *= 2; - } - if (dt < delay1) { - validate = 0; - } - if (last_map_count) { - if (now > last_snapshot + delay2) { - snapit = 1; - } - } else { - if (now > last_snapshot + delay3) { - snapit = 1; - } - } - - if (snapit) { - /* less problems if we update the stack frequently */ - snapshot_stack_list(0, 0.0); -if (0) fprintf(stderr, "SNAP time: %.4f\n", dnow() - now); - update_stack_list(); - last_snapshot = dnow(); -if (0) fprintf(stderr, "UPDA time: %.4f\n", last_snapshot - now); - } - -if (0) t2 = dnow(); - last_map_count = get_8bpp_regions(validate); - if (validate) { - last_get_8bpp_validate = dnow(); - } -if (0) fprintf(stderr, "get8bpp-%d: %.4f\n", validate, dnow() - t2); - } -if (db24) d0 = dnow(); - -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 transform and 8bpp regions to TrueColor in - * cmap8to24_fb. - */ - if (last_map_count && (ncmaps || depth <= 16)) { - int i, j; - int win[MAX_8BPP_WINDOWS]; - int did[MAX_8BPP_WINDOWS]; - int count = 0; - - /* - * 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 > 2) fprintf(stderr, "cmap %d %.4f\n", (int) cmaps[j], dnow() - d0); - } - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - sraRegionPtr reg = windows_8bpp[i].clip_region; - if (reg) { - rect = sraRgnCreateRect(x1, y1, x2, y2); - if (sraRgnAnd(rect, reg)) { - win[count] = i; - did[count++] = 0; - } - sraRgnDestroy(rect); - } - } - - if (count) { - - rect = sraRgnCreateRect(x1, y1, x2, y2); - /* try to apply lower windows first */ - for (k=0; k < stack_list_num; k++) { - Window swin = stack_list[k].win; - for (j=0; j<count; j++) { - i = win[j]; - if (did[j]) { - continue; - } - if (windows_8bpp[i].top == swin) { - do_8bpp_region(i, rect); - did[j] = 1; - break; - } - } - } - for (j=0; j<count; j++) { - if (! did[j]) { - i = win[j]; - do_8bpp_region(i, rect); - did[j] = 1; - } - } - sraRgnDestroy(rect); - } - } -if (0) fprintf(stderr, "done time: %.4f\n", dnow() - d0); - -if (db24 > 2) {for(i=0; i<256;i++) {fprintf(stderr, " cmap histo[%03d] %d\n", i, histo[i]);}} -} - -void mark_8bpp(int mode) { - int i, cnt = 0; - Window top = None; - - RAWFB_RET_VOID - - if (! cmap8to24 || !cmap8to24_fb) { - return; - } - - if (mode == MARK_8BPP_TOP) { - int k; - for (k = stack_list_num - 1; k >= 0; k--) { - Window swin = stack_list[k].win; - for (i=0; i < MAX_8BPP_WINDOWS; i++) { - if (windows_8bpp[i].win == None) { - continue; - } - if (windows_8bpp[i].map_state != IsViewable) { - continue; - } - if (swin == windows_8bpp[i].top) { - top = swin; - break; - } - } - if (top != None) { - break; - } - } - } - - /* for each mapped 8bpp window, mark it changed: */ - - 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 (mode == MARK_8BPP_TOP) { - if (windows_8bpp[i].top != top) { - continue; - } - } - if (windows_8bpp[i].map_state != IsViewable) { - XWindowAttributes attr; - int vw = 0; - - 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; - y1 = windows_8bpp[i].y; - w = windows_8bpp[i].w; - h = windows_8bpp[i].h; - - x2 = x1 + w; - y2 = y1 + h; - - if (mode == MARK_8BPP_POINTER) { - int b = 32; /* apply some fuzz for wm border */ - if (cursor_x < x1 - b || cursor_y < y1 - b) { - continue; - } - if (cursor_x > x2 + b || cursor_y > y2 + b) { - continue; - } - } - - /* apply fuzz f around each one; constrain to screen */ - x1 = nfix(x1 - f, dpy_x); - y1 = nfix(y1 - f, dpy_y); - x2 = nfix(x2 + f, dpy_x+1); - y2 = nfix(y2 + f, dpy_y+1); - -if (db24 > 1) fprintf(stderr, "mark_8bpp: 0x%lx %d %d %d %d\n", windows_8bpp[i].win, x1, y1, x2, y2); - - mark_rect_as_modified(x1, y1, x2, y2, 0); - cnt++; - } - if (cnt) { - /* push it to viewers if possible. */ - rfbPE(-1); - } -} - -#endif /* SKIP_8TO24 */ - |