diff --git a/x11vnc/8to24.c b/x11vnc/8to24.c index bfe9292..88b923c 100644 --- a/x11vnc/8to24.c +++ b/x11vnc/8to24.c @@ -17,7 +17,7 @@ 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 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); @@ -27,7 +27,7 @@ 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, Visual *visual, int win_depth); +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: */ @@ -41,6 +41,7 @@ typedef struct window8 { Colormap cmap; Bool map_installed; int fetched; + double last_fetched; sraRegionPtr clip_region; } window8bpp_t; @@ -50,21 +51,59 @@ enum mark_8bpp_modes { MARK_8BPP_TOP }; +#define NCOLOR 256 + static Colormap root_cmap = 0; +static unsigned int root_rgb[NCOLOR]; static void set_root_cmap(void) { static time_t last_set = 0; time_t now = time(0); XWindowAttributes attr; + static XColor color[NCOLOR]; + int redo = 0; - if (now > last_set + 5) { - root_cmap = 0; + if (now > last_set + 10) { + redo = 1; } - if (! root_cmap) { + if (! root_cmap || redo) { X_LOCK; - if (valid_window(window, &attr, 1)) { + if (! valid_window(window, &attr, 1)) { + X_UNLOCK; + return; + } + if (attr.colormap) { + int i, ncells = NCOLOR; + 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; } @@ -77,6 +116,8 @@ 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; @@ -129,13 +170,19 @@ static void parse_cmap8to24(void) { 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, ","); } @@ -175,6 +222,11 @@ static void set_poll_fb(void) { 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) { XWindowAttributes attr; int doall = 0; @@ -190,8 +242,9 @@ void check_for_multivis(void) { static double last_call = 0.0; static double last_query = 0.0; double now = dnow(); + double delay; - if (now > last_parse + 0.75) { + if (now > last_parse + 1.0) { last_parse = now; parse_cmap8to24(); } @@ -207,6 +260,7 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); 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(); @@ -215,6 +269,10 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); doall = 1; /* fetch everything first time */ } + if (wireframe_in_progress) { + return; + } + set_root_cmap(); /* @@ -243,7 +301,13 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); } /* snapshot + update the current stacking order: */ - if (doall || now > last_update + 0.15) { + /* 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; @@ -282,22 +346,41 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); 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; - if (now < last_query + 0.05) { + /* 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; } @@ -328,12 +411,17 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); } /* we recurse up to two levels down from stack_list windows */ - X_LOCK; + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; rc = XQueryTree(dpy, win, &r, &parent, &list0, &nc0); - X_UNLOCK; - if (! rc) { + 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++) { @@ -345,12 +433,22 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); if (check_depth(win1, win, doall)) { continue; } - X_LOCK; + + if (level2_8to24) { + continue; + } + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; rc = XQueryTree(dpy, win1, &r, &parent, &list1, &nc1); - X_UNLOCK; - if (! rc) { + 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]; @@ -361,19 +459,20 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); /* more? Which wm does this? */ } if (nc1) { - X_LOCK; XFree(list1); - X_UNLOCK; } } if (nc0) { - X_LOCK; XFree(list0); - X_UNLOCK; } } + 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); @@ -416,44 +515,124 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); } } } +if (0) fprintf(stderr, "done: %.4f\n", dnow() - last_query); +} + +#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= 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; + XWindowAttributes attr, *pattr; - X_LOCK; /* first see if it is (still) a valid window: */ - if (! valid_window(win, &attr, 1)) { - X_UNLOCK; - return 1; /* indicate done */ +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; } - X_UNLOCK; - if (! doall && attr.map_state != IsViewable) { + + 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, attr); + check_depth_win(win, top, pattr); return 1; /* indicate done */ - } else if (check_depth_win(win, top, attr)) { + } 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) { +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) { - set_root_cmap(); - if (depth == 24 && attr.depth != 24) { + if (attr->depth > 0) { + if (depth == 24 && attr->depth != 24) { store_it = 1; - } else if (depth == 8 && root_cmap && attr.colormap != + } else if (depth == 8 && root_cmap && attr->colormap != root_cmap) { store_it = 1; } @@ -462,13 +641,13 @@ static int check_depth_win(Window win, Window top, XWindowAttributes attr) { if (store_it) { int i, j = -1, none = -1, nomap = -1; int new = 0; - if (attr.map_state == IsViewable) { + if (attr->map_state == IsViewable) { /* count the visible ones: */ multivis_count++; - if (attr.depth == 24) { + 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); } /* try to find a table slot for this window: */ @@ -489,7 +668,7 @@ if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr.depth); } } if (j < 0) { - if (attr.map_state != IsViewable) { + if (attr->map_state != IsViewable) { /* no slot and not visible: not worth keeping */ return 1; } else if (none >= 0) { @@ -503,7 +682,7 @@ 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 dep=%d\n", win, attr.map_state, j, none, nomap, attr.depth); +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) { @@ -511,33 +690,34 @@ if (db24 > 1) fprintf(stderr, "multivis: 0x%lx ms: %d j: %d no: %d nm: %d dep=%d int x, y; int now_vis = 0; - if (attr.map_state == IsViewable && + 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); +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].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) */ - X_LOCK; xtranslate(win, window, 0, 0, &x, &y, &w, 1); - X_UNLOCK; windows_8bpp[j].x = x; windows_8bpp[j].y = y; 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); + X_UNLOCK; /* dont forget the giant lock */ + mark_rect_as_modified(x, y, x + attr->width, + y + attr->height, 0); + X_LOCK; } } else { /* @@ -583,10 +763,14 @@ static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) { static int xi8_w = 0, xi24_w = 0; XErrorHandler old_handler = NULL; - XWindowAttributes attr; 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; @@ -602,9 +786,17 @@ static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) { } X_LOCK; - if (! valid_window(windows_8bpp[n].win, &attr, 1)) { - X_UNLOCK; - return 0; + 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 != 8 && attr.depth != 24) { @@ -624,19 +816,25 @@ static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) { n_off = poll24_fb_w * y1 + x1; } - xtranslate(win, window, 0, 0, &xo, &yo, &c, 1); + 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 (xo < 0 || yo < 0 || xo + w > attr.width) { + 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; - old_handler = XSetErrorHandler(trap_xerror); xi_r = XGetSubImage(dpy, win, xo, yo, w, 1, AllPlanes, ZPixmap, xi, 0, 0); XSetErrorHandler(old_handler); @@ -943,6 +1141,7 @@ if (db24 > 1) fprintf(stderr, "get_8bpp_regions: 0x%lx ms=%d dep=%d i=%d\n", w, 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; @@ -954,6 +1153,7 @@ if (db24 > 1) fprintf(stderr, "get_8bpp_regions: 0x%lx ms=%d dep=%d i=%d\n", w, 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; @@ -1053,7 +1253,6 @@ if (db24 > 1) fprintf(stderr, "subtract: 0x%lx %d -- %d %d %d %d\n", swin, k, s return mapcount; } -#define NCOLOR 256 static XColor color[CMAPMAX][NCOLOR]; static unsigned int rgb[CMAPMAX][NCOLOR]; static int cmap_failed[CMAPMAX]; @@ -1188,19 +1387,26 @@ if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps); sraRgnDestroy(clip); } -static XImage *cmap_xi(XImage *xi, Visual *visual, int win_depth) { +static XImage *cmap_xi(XImage *xi, Window win, int win_depth) { + XWindowAttributes attr; char *d; + if (xi) { XDestroyImage(xi); } - if (win_depth == 8) { + if (! valid_window(win, &attr, 1)) { + return (XImage *) NULL; + } + if (attr.depth != win_depth) { + return (XImage *) NULL; + } else if (win_depth == 8) { d = (char *) malloc(dpy_x * dpy_y * 1); } else if (win_depth == 24) { d = (char *) malloc(dpy_x * dpy_y * 4); } else { return (XImage *) NULL; } - return XCreateImage(dpy, visual, win_depth, ZPixmap, 0, d, dpy_x, + return XCreateImage(dpy, attr.visual, win_depth, ZPixmap, 0, d, dpy_x, dpy_y, 8, 0); } @@ -1214,7 +1420,7 @@ static void transform_rect(sraRect rect, Window win, int win_depth, int cm) { int poll_Bpl; int do_getimage = xgetimage_8to24; - int line, n_off, j, h, w, vw; + int line, n_off, j, h, w; unsigned int hi, idx; XWindowAttributes attr; XErrorHandler old_handler = NULL; @@ -1232,6 +1438,7 @@ if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rec do_getimage = 1; } +#if 0 if (do_getimage) { X_LOCK; vw = valid_window(win, &attr, 1); @@ -1239,6 +1446,9 @@ if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rec } if (do_getimage && vw) { +#else + if (do_getimage) { +#endif static XImage *xi_8 = NULL; static XImage *xi_24 = NULL; XImage *xi = NULL, *xi_r; @@ -1250,37 +1460,43 @@ if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rec hu = (unsigned int) h; X_LOCK; - xtranslate(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) { - X_UNLOCK; -if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n"); - return; - } - #define GETSUBIMAGE #ifdef GETSUBIMAGE if (win_depth == 8) { if (xi_8 == NULL || xi_8->width != dpy_x || xi_8->height != dpy_y) { - xi_8 = cmap_xi(xi_8, attr.visual, attr.depth); + xi_8 = cmap_xi(xi_8, win, 8); } xi = xi_8; } else if (win_depth == 24) { if (xi_24 == NULL || xi_24->width != dpy_x || xi_24->height != dpy_y) { - xi_24 = cmap_xi(xi_24, attr.visual, attr.depth); + xi_24 = cmap_xi(xi_24, win, 24); } xi = xi_24; } #endif - trapped_xerror = 0; 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; @@ -1427,15 +1643,15 @@ void bpp8to24(int x1, int y1, int x2, int y2) { 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, dt, d0; + double now; + double dt, d0 = 0.0, t2; if (! cmap8to24 || ! cmap8to24_fb) { /* hmmm, why were we called? */ return; } - now = dnow(); -if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, now - last_get_8bpp_validate); +if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, dnow() - last_get_8bpp_validate); call_count++; @@ -1453,10 +1669,6 @@ if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, now return; } - X_LOCK; - XFlush(dpy); /* make sure X server is up to date WRT input, etc */ - X_UNLOCK; - /* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */ h = y2 - y1; @@ -1465,7 +1677,6 @@ if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, now if (depth == 8) { /* need to cook up to depth 24 TrueColor */ /* pixelsize = 1 */ - int tcm = CMAPMAX - 1; n_off = main_bytes_per_line * y1 + pixelsize * x1; @@ -1473,7 +1684,7 @@ if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, now dst = cmap8to24_fb + 4 * n_off; set_root_cmap(); - if (get_cmap(tcm, root_cmap)) { + if (root_cmap) { int ps1 = 1, ps2 = 4; #if 0 unsigned int hi; @@ -1496,7 +1707,7 @@ if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, now } else { } #endif - *ui = rgb[tcm][idx]; + *ui = root_rgb[idx]; if (db24 > 2) histo[idx]++; } src += main_bytes_per_line; @@ -1534,21 +1745,36 @@ if (db24 > 2) histo[idx]++; if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} + now = dnow(); dt = now - last_get_8bpp_validate; - d0 = dnow(); - if (dt < 0.0025) { + /* TUNABLES */ + if (dt < 0.003) { ; /* XXX does this still give painting errors? */ } else { int snapit = 0; - if (dt < 0.04) { + 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 + 0.05) { + if (now > last_snapshot + delay2) { snapit = 1; } } else { - if (now > last_snapshot + 0.4) { + if (now > last_snapshot + delay3) { snapit = 1; } } @@ -1556,15 +1782,20 @@ if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} 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 = now; + 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 = now; + 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); @@ -1630,6 +1861,7 @@ if (db24 > 2) fprintf(stderr, "cmap %d %.4f\n", (int) cmaps[j], dnow() - d0); 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]);}} } diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 8a5f81b..9b9f3c1 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,6 @@ +2006-02-06 Karl Runge + * x11vnc: -8to24 more speedups; tunables for very slow machines. + 2006-02-04 Karl Runge * x11vnc: -8to24 speedups and improvements. diff --git a/x11vnc/README b/x11vnc/README index a34b6bd..299e0fc 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Sat Feb 4 22:21:00 EST 2006 +x11vnc README file Date: Mon Feb 6 00:16:18 EST 2006 The following information is taken from these URLs: @@ -4898,7 +4898,7 @@ x11vnc: a VNC server for real X displays Here are all of x11vnc command line options: % x11vnc -opts (see below for -help long descriptions) -x11vnc: allow VNC connections to real X11 displays. 0.8 lastmod: 2006-02-04 +x11vnc: allow VNC connections to real X11 displays. 0.8 lastmod: 2006-02-06 x11vnc options: -display disp -auth file @@ -5009,7 +5009,7 @@ libvncserver-tight-extension options: % x11vnc -help -x11vnc: allow VNC connections to real X11 displays. 0.8 lastmod: 2006-02-04 +x11vnc: allow VNC connections to real X11 displays. 0.8 lastmod: 2006-02-06 Typical usage is: @@ -5201,6 +5201,18 @@ Options: "poll=t" where "t" is a floating point time. (default: 0.05) + Setting the option "level2" will limit the search + for non-default visual windows to two levels from the + root window. Do this on slow machines where you know + the window manager only imposes one extra window between + the app window and the root window. + + Also for very slow machines use "cachewin=t" + where t is a floating point amount of time to cache + XGetWindowAttributes results. E.g. cachewin=5.0. + This may lead to the windows being unnoticed for this + amount of time when deiconifying, painting errors, etc. + Debugging for this mode can be enabled by setting "dbg=1", "dbg=2", or "dbg=3". diff --git a/x11vnc/help.c b/x11vnc/help.c index 3a558cd..692276a 100644 --- a/x11vnc/help.c +++ b/x11vnc/help.c @@ -209,6 +209,18 @@ void print_help(int mode) { " \"poll=t\" where \"t\" is a floating point time.\n" " (default: %.2f)\n" "\n" +" Setting the option \"level2\" will limit the search\n" +" for non-default visual windows to two levels from the\n" +" root window. Do this on slow machines where you know\n" +" the window manager only imposes one extra window between\n" +" the app window and the root window.\n" +"\n" +" Also for very slow machines use \"cachewin=t\"\n" +" where t is a floating point amount of time to cache\n" +" XGetWindowAttributes results. E.g. cachewin=5.0.\n" +" This may lead to the windows being unnoticed for this\n" +" amount of time when deiconifying, painting errors, etc.\n" +"\n" " Debugging for this mode can be enabled by setting \n" " \"dbg=1\", \"dbg=2\", or \"dbg=3\".\n" "\n" diff --git a/x11vnc/win_utils.c b/x11vnc/win_utils.c index 327daae..aad1362 100644 --- a/x11vnc/win_utils.c +++ b/x11vnc/win_utils.c @@ -25,15 +25,25 @@ Window descend_pointer(int depth, Window start, char *name_info, int len); Window parent_window(Window win, char **name) { Window r, parent; Window *list; + XErrorHandler old_handler; unsigned int nchild; + int rc; if (name != NULL) { *name = NULL; } - if (! XQueryTree(dpy, win, &r, &parent, &list, &nchild)) { + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + rc = XQueryTree(dpy, win, &r, &parent, &list, &nchild); + XSetErrorHandler(old_handler); + + if (! rc || trapped_xerror) { + trapped_xerror = 0; return None; } + trapped_xerror = 0; + if (list) { XFree(list); } @@ -59,8 +69,8 @@ int valid_window(Window win, XWindowAttributes *attr_ret, int bequiet) { return 0; } - trapped_xerror = 0; old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; if (XGetWindowAttributes(dpy, win, pattr)) { ok = 1; } @@ -148,6 +158,7 @@ void snapshot_stack_list(int free_only, double allowed_age) { last_free = now; X_LOCK; + /* no need to trap error since rootwin */ rc = XQueryTree(dpy, rootwin, &r, &w, &list, &ui); num = (int) ui; diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index fb99e80..ca48b79 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -2,7 +2,7 @@ .TH X11VNC "1" "February 2006" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.8, lastmod: 2006-02-04 + version: 0.8, lastmod: 2006-02-06 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -241,6 +241,18 @@ non-default visual regions for changes, use the option "poll=t" where "t" is a floating point time. (default: 0.05) .IP +Setting the option "level2" will limit the search +for non-default visual windows to two levels from the +root window. Do this on slow machines where you know +the window manager only imposes one extra window between +the app window and the root window. +.IP +Also for very slow machines use "cachewin=t" +where t is a floating point amount of time to cache +XGetWindowAttributes results. E.g. cachewin=5.0. +This may lead to the windows being unnoticed for this +amount of time when deiconifying, painting errors, etc. +.IP Debugging for this mode can be enabled by setting "dbg=1", "dbg=2", or "dbg=3". .PP diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index d4bc860..a73b8e0 100644 --- a/x11vnc/x11vnc_defs.c +++ b/x11vnc/x11vnc_defs.c @@ -15,7 +15,7 @@ int xtrap_base_event_type = 0; int xdamage_base_event_type = 0; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.8 lastmod: 2006-02-04"; +char lastmod[] = "0.8 lastmod: 2006-02-06"; /* X display info */