diff options
author | runge <runge> | 2006-02-05 04:46:57 +0000 |
---|---|---|
committer | runge <runge> | 2006-02-05 04:46:57 +0000 |
commit | d0ef1285b8fe0f8efd0e1d75fcfcbad175411e0f (patch) | |
tree | 70a0c8ca556ac5a3b2420dae98adb3ddf5960969 | |
parent | 1967913e9530139eb355b7b3108bb12314ba47da (diff) | |
download | libtdevnc-d0ef1285b8fe0f8efd0e1d75fcfcbad175411e0f.tar.gz libtdevnc-d0ef1285b8fe0f8efd0e1d75fcfcbad175411e0f.zip |
x11vnc: -8to24 speedups and improvements.
-rw-r--r-- | x11vnc/8to24.c | 1065 | ||||
-rw-r--r-- | x11vnc/8to24.h | 2 | ||||
-rw-r--r-- | x11vnc/ChangeLog | 3 | ||||
-rw-r--r-- | x11vnc/README | 130 | ||||
-rw-r--r-- | x11vnc/help.c | 121 | ||||
-rw-r--r-- | x11vnc/options.c | 3 | ||||
-rw-r--r-- | x11vnc/options.h | 1 | ||||
-rw-r--r-- | x11vnc/params.h | 4 | ||||
-rw-r--r-- | x11vnc/rates.c | 2 | ||||
-rw-r--r-- | x11vnc/scan.c | 4 | ||||
-rw-r--r-- | x11vnc/scan.h | 1 | ||||
-rw-r--r-- | x11vnc/userinput.c | 48 | ||||
-rw-r--r-- | x11vnc/x11vnc.1 | 124 | ||||
-rw-r--r-- | x11vnc/x11vnc.c | 3 | ||||
-rw-r--r-- | x11vnc/x11vnc_defs.c | 2 | ||||
-rw-r--r-- | x11vnc/xinerama.c | 3 |
16 files changed, 1052 insertions, 464 deletions
diff --git a/x11vnc/8to24.c b/x11vnc/8to24.c index 873ba25..bfe9292 100644 --- a/x11vnc/8to24.c +++ b/x11vnc/8to24.c @@ -10,17 +10,25 @@ int multivis_24count = 0; void check_for_multivis(void); void bpp8to24(int, int, int, int); -void mark_8bpp(void); +void mark_8bpp(int); static void set_root_cmap(void); -static void check_pointer_in_depth24(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 int get_8pp_region(sraRegionPtr region8bpp, sraRegionPtr rect, - int validate); +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(sraRect rect); +static void do_8bpp_region(int n, sraRegionPtr mark); +static XImage *cmap_xi(XImage *xi, Visual *visual, 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 { @@ -33,9 +41,17 @@ typedef struct window8 { Colormap cmap; Bool map_installed; int fetched; + sraRegionPtr clip_region; } window8bpp_t; +enum mark_8bpp_modes { + MARK_8BPP_ALL = 0, + MARK_8BPP_POINTER, + MARK_8BPP_TOP +}; + static Colormap root_cmap = 0; + static void set_root_cmap(void) { static time_t last_set = 0; time_t now = time(0); @@ -59,11 +75,10 @@ static void set_root_cmap(void) { static window8bpp_t windows_8bpp[MAX_8BPP_WINDOWS]; static int db24 = 0; -static int xgetimage_8to24 = 0; -static int do_hibits = 0; -static double poll_8to24_delay = 0.0; +static int xgetimage_8to24 = 1; +static double poll_8to24_delay = POLL_8TO24_DELAY; -static void check_pointer_in_depth24(void) { +static int check_pointer_in_depth24(void) { int tries = 0, in_24 = 0; XWindowAttributes attr; Window c, w; @@ -72,7 +87,7 @@ static void check_pointer_in_depth24(void) { c = window; if (now > last_keyboard_time + 1.0 && now > last_pointer_time + 1.0) { - return; + return 0; } X_LOCK; @@ -95,27 +110,32 @@ static void check_pointer_in_depth24(void) { 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); + 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 = 0; - do_hibits = 0; + xgetimage_8to24 = 1; + poll_8to24_delay = POLL_8TO24_DELAY; while (p) { if (strstr(p, "dbg=") == p) { db24 = atoi(p + strlen("dbg=")); - } else if (!strcmp(p, "highbits")) { - do_hibits = 1; - } else if (!strcmp(p, "getimage")) { - xgetimage_8to24 = 1; + } else if (strstr(p, "poll=") == p) { + poll_8to24_delay = atof(p + strlen("poll=")); + } else if (!strcmp(p, "nogetimage")) { + xgetimage_8to24 = 0; } p = strtok(NULL, ","); } @@ -124,17 +144,35 @@ static void parse_cmap8to24(void) { if (getenv("DEBUG_8TO24") != NULL) { db24 = atoi(getenv("DEBUG_8TO24")); } - if (getenv("XGETIMAGE_8TO24") != NULL) { - xgetimage_8to24 = 1; + if (getenv("NOXGETIMAGE_8TO24") != NULL) { + xgetimage_8to24 = 0; } - if (getenv("HIGHBITS_8TO24") != NULL) { - do_hibits = 1; + } +} + +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; } } -void poll_8bpp(void) { - +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); + pfb(1, &poll8_fb, &poll8_fb_w, &poll8_fb_h); } void check_for_multivis(void) { @@ -142,13 +180,23 @@ void check_for_multivis(void) { 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(); - static Window *stack_old = NULL; - static int stack_old_len = 0; + + if (now > last_parse + 0.75) { + 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; @@ -159,16 +207,14 @@ void check_for_multivis(void) { windows_8bpp[i].map_state = IsUnmapped; windows_8bpp[i].cmap = (Colormap) 0; windows_8bpp[i].fetched = 0; + windows_8bpp[i].clip_region = NULL; } + set_poll_fb(); + first = 0; doall = 1; /* fetch everything first time */ } - if (now > last_parse + 0.75) { - last_parse = now; - parse_cmap8to24(); - } - set_root_cmap(); /* @@ -197,8 +243,8 @@ void check_for_multivis(void) { } /* snapshot + update the current stacking order: */ - snapshot_stack_list(0, 0.25); - if (doall || now > last_update + 0.25) { + if (doall || now > last_update + 0.15) { + snapshot_stack_list(0, 0.0); update_stack_list(); last_update = now; } @@ -207,7 +253,8 @@ void check_for_multivis(void) { 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_list[k].valid && stack_list[k].map_state == + IsViewable) { if (stack_old[cnt] != stack_list[k].win) { diff = 1; break; @@ -216,26 +263,6 @@ void check_for_multivis(void) { } } - if (poll_8to24_delay > 0.0 && now > last_poll + poll_8to24_delay) { - last_poll = now; - } - - /* - * if there are 8bpp visible and a stacking order change - * refresh vnc with coverage of the 8bpp regions: - */ - 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; @@ -248,7 +275,6 @@ 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 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; @@ -271,6 +297,10 @@ if ((db24) && w != None) fprintf(stderr, " windows_8bpp: 0x%lx i=%02d ms: %d d Window win = stack_list[k].win; + if (now < last_query + 0.05) { + break; + } + if (win == None) { continue; } @@ -291,7 +321,7 @@ if ((db24) && w != None) fprintf(stderr, " windows_8bpp: 0x%lx i=%02d ms: %d d if (check_depth(win, win, doall)) { /* - * returns 1 if no need to recurse down e.g. IT + * returns 1 if no need to recurse down e.g. It * is 8bpp and we assume all lower one are too. */ continue; @@ -342,6 +372,50 @@ if ((db24) && w != None) fprintf(stderr, " windows_8bpp: 0x%lx i=%02d ms: %d d X_UNLOCK; } } + last_query = dnow(); + + 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 == 8 && 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; + } + } + } } static int check_depth(Window win, Window top, int doall) { @@ -356,9 +430,9 @@ static int check_depth(Window win, Window top, int doall) { X_UNLOCK; if (! doall && attr.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. + * 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); return 1; /* indicate done */ @@ -372,8 +446,8 @@ 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). + * 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(); @@ -384,8 +458,8 @@ static int check_depth_win(Window win, Window top, XWindowAttributes attr) { store_it = 1; } } - if (store_it) { + if (store_it) { int i, j = -1, none = -1, nomap = -1; int new = 0; if (attr.map_state == IsViewable) { @@ -450,6 +524,7 @@ if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d dep=%d\n", wi 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; /* translate x y to be WRT the root window (not parent) */ X_LOCK; @@ -458,8 +533,6 @@ if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d dep=%d\n", wi windows_8bpp[j].x = x; windows_8bpp[j].y = y; - windows_8bpp[j].fetched = 1; - 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: */ @@ -482,12 +555,354 @@ if (db24 > 1) fprintf(stderr, " ------------ 0x%lx i=%d\n", windows_8bp return 0; } +static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w) { + if (xi == NULL || *w < dpy_x) { + char *d; + if (xi) { + XDestroyImage(xi); + } + if (win_depth == 8) { + 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; +} + +static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) { + 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; + XWindowAttributes attr; + XImage *xi; + Window c, win = windows_8bpp[n].win; + + sraRegionPtr rect; + int mx1, mx2, my1, my2; + int ns = NSCAN/2; + + if (win == None) { + return 1; + } + if (windows_8bpp[n].map_state != IsViewable) { + return 1; + } + if (! xgetimage_8to24) { + return 1; + } + + X_LOCK; + if (! valid_window(windows_8bpp[n].win, &attr, 1)) { + X_UNLOCK; + return 0; + } + + if (attr.depth != 8 && attr.depth != 24) { + X_UNLOCK; + return 1; + } else if (attr.depth == 8) { + xi = xi8 = p_xi(xi8, attr.visual, 8, &xi8_w); + + poll_fb = poll8_fb; + 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; + } + + xtranslate(win, window, 0, 0, &xo, &yo, &c, 1); + xo = x1 - xo; + yo = y1 - yo; + w = x2 - x1; + + if (xo < 0 || yo < 0 || xo + w > attr.width) { +if (db24 > 2) fprintf(stderr, "avoid bad match...\n"); + 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); + 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; +} + +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 -Colormap cmaps[CMAPMAX]; -int ncmaps; +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); + } -static int get_8pp_region(sraRegionPtr region8bpp, sraRegionPtr rect, - int validate) { + 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; @@ -504,15 +919,16 @@ static int get_8pp_region(sraRegionPtr region8bpp, sraRegionPtr rect, Window c, w = windows_8bpp[i].win; int x, y; - if (wireframe_in_progress) { - break; /* skip updates during wireframe drag */ + 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_8pp_region: 0x%lx ms=%d dep=%d i=%d\n", w, windows_8bpp[i].map_state, windows_8bpp[i].depth, i); +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 @@ -530,6 +946,15 @@ if (db24 > 1) fprintf(stderr, "get_8pp_region: 0x%lx ms=%d dep=%d i=%d\n", w, wi 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; + if (attr.map_state != IsViewable) { continue; } @@ -537,34 +962,30 @@ if (db24 > 1) fprintf(stderr, "get_8pp_region: 0x%lx ms=%d dep=%d i=%d\n", w, wi 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; } - x = windows_8bpp[i].x; - y = windows_8bpp[i].y; - attr.width = windows_8bpp[i].w; - attr.height = windows_8bpp[i].h; + 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), nfix(y + attr.height, dpy_y)); - - /* find overlap with mark region in rect: */ - sraRgnAnd(tmp_reg, rect); - - if (sraRgnEmpty(tmp_reg)) { - /* skip if no overlap: */ - sraRgnDestroy(tmp_reg); - continue; - } + 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--) { @@ -574,7 +995,7 @@ if (db24 > 1) fprintf(stderr, "get_8pp_region: 0x%lx ms=%d dep=%d i=%d\n", w, wi 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. */ + /* 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; } @@ -592,39 +1013,41 @@ if (db24 > 1) fprintf(stderr, "found top: 0x%lx %d iv=%d\n", swin, k, stack_list 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)); + 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); -if (db24 > 1) fprintf(stderr, "Empty tmp_reg\n"); continue; } /* otherwise, store any new colormaps: */ if (ncmaps < CMAPMAX && attr.colormap != (Colormap) 0) { - int m, sawit = 0; + int m, seen = 0; for (m=0; m < ncmaps; m++) { if (cmaps[m] == attr.colormap) { - sawit = 1; + seen = 1; break; } } - if (! sawit && attr.depth == 8) { + if (! seen && attr.depth == 8) { /* store only new ones: */ cmaps[ncmaps++] = attr.colormap; } } - /* now include this region with the full 8bpp region: */ - sraRgnOr(region8bpp, tmp_reg); - sraRgnDestroy(tmp_reg); + windows_8bpp[i].clip_region = tmp_reg; } return mapcount; @@ -701,131 +1124,125 @@ if (db24 > 2) fprintf(stderr, " cmap[%02d][%03d]: %03d %03d %03d 0x%08x \n", j, 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; } -static void do_8bpp_region(sraRect rect) { - - char *src, *dst; - unsigned int *ui; - unsigned char *uc; - int ps, pixelsize = bpp/8; - - int do_getimage = xgetimage_8to24; - int line, n_off, j, h, w, vw; - unsigned int hi, idx; - XWindowAttributes attr; - XErrorHandler old_handler = NULL; - - double score, max_score = -1.0; - int m, best, best_depth = 0; - Window best_win = None; +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); - /* - * try to pick the "best" colormap to use for - * this rectangle (often wrong... let them - * iconify or move the trouble windows, etc.) - */ - best = -1; - - 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; - } - - /* see if XQueryColors failed: */ - for (k=0; k<ncmaps; k++) { - if (windows_8bpp[m].cmap == cmaps[k] && cmap_failed[k]) { + /* 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[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; + if (windows_8bpp[n].depth == 8) { /* 24 won't have a cmap */ + if (failed || cm == -1) { + return; + } + } - /* use overlap as score: */ - score = rect_overlap(mx1, my1, mx2, my2, rect.x1, rect.y1, - rect.x2, rect.y2); + clip = sraRgnCreateRgn(mark); + sraRgnAnd(clip, windows_8bpp[n].clip_region); - if (score > max_score) { - max_score = score; - best = m; - best_win = windows_8bpp[m].win; - best_depth = windows_8bpp[m].depth; + /* 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; } -if (db24 > 1) fprintf(stderr, "cmap_score: 0x%x %.3f %.3f\n", (int) windows_8bpp[m].cmap, score, max_score); + transform_rect(rect, windows_8bpp[n].win, + windows_8bpp[n].depth, cm); } + sraRgnReleaseIterator(iter); + sraRgnDestroy(clip); +} - if (best < 0) { - /* hmmm, use the first one then... */ - best = 0; +static XImage *cmap_xi(XImage *xi, Visual *visual, int win_depth) { + char *d; + if (xi) { + XDestroyImage(xi); + } + 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 { - 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; - } + return (XImage *) NULL; } + return XCreateImage(dpy, visual, win_depth, ZPixmap, 0, d, dpy_x, + dpy_y, 8, 0); +} + + +static void transform_rect(sraRect rect, Window win, int win_depth, int cm) { + + char *src, *dst, *poll; + unsigned int *ui; + unsigned char *uc; + int ps, pixelsize = bpp/8; + int poll_Bpl; + int do_getimage = xgetimage_8to24; + int line, n_off, j, h, w, vw; + unsigned int hi, idx; + XWindowAttributes attr; + XErrorHandler old_handler = NULL; -if (db24 > 1) fprintf(stderr, "transform %d %d %d %d\n", rect.x1, rect.y1, rect.x2, rect.y2); +if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rect.y1, rect.x2, rect.y2, cm); - /* now tranform the pixels in this rectangle: */ + /* 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 == 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; - } + /* need to fetch depth 24 data. */ + do_getimage = 1; } if (do_getimage) { X_LOCK; - vw = valid_window(best_win, &attr, 1); + vw = valid_window(win, &attr, 1); X_UNLOCK; } if (do_getimage && vw) { static XImage *xi_8 = NULL; static XImage *xi_24 = NULL; - XImage *xi = NULL; + XImage *xi = NULL, *xi_r; Window c; - char *d; unsigned int wu, hu; int xo, yo; @@ -833,7 +1250,7 @@ if (db24 > 1) fprintf(stderr, "transform %d %d %d %d\n", rect.x1, rect.y1, rect. hu = (unsigned int) h; X_LOCK; - xtranslate(best_win, window, 0, 0, &xo, &yo, &c, 1); + xtranslate(win, window, 0, 0, &xo, &yo, &c, 1); xo = rect.x1 - xo; yo = rect.y1 - yo; @@ -847,46 +1264,34 @@ if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n"); #define GETSUBIMAGE #ifdef GETSUBIMAGE - if (best_depth == 8) { - if (xi_8 == NULL || xi_8->width != dpy_x || xi_8->height != dpy_y) { - if (xi_8) { - XDestroyImage(xi_8); + 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); } - d = (char *) malloc(dpy_x * dpy_y * attr.depth/8); - xi_8 = XCreateImage(dpy, attr.visual, attr.depth, - ZPixmap, 0, d, dpy_x, dpy_y, 8, 0); -if (db24) fprintf(stderr, "xi_8: %p\n", (void *) xi_8); - } - xi = xi_8; - } else if (best_depth == 24) { - if (xi_24 == NULL || xi_24->width != dpy_x || xi_24->height != dpy_y) { - if (xi_24) { - XDestroyImage(xi_24); + 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); } - d = (char *) malloc(dpy_x * dpy_y * attr.depth/8); - xi_24 = XCreateImage(dpy, attr.visual, attr.depth, - ZPixmap, 0, d, dpy_x, dpy_y, 8, 0); -if (db24) fprintf(stderr, "xi_24: %p\n", (void *) xi_24); - } - xi = xi_24; + xi = xi_24; } #endif - trapped_xerror = 0; old_handler = XSetErrorHandler(trap_xerror); - /* FIXME: XGetSubImage? */ #ifndef GETSUBIMAGE - xi = XGetImage(dpy, best_win, xo, yo, wu, hu, - AllPlanes, ZPixmap); + xi = XGetImage(dpy, win, xo, yo, wu, hu, AllPlanes, ZPixmap); + xi_r = xi; #else - XGetSubImage(dpy, best_win, xo, yo, wu, hu, AllPlanes, + xi_r = XGetSubImage(dpy, win, xo, yo, wu, hu, AllPlanes, ZPixmap, xi, 0, 0); #endif XSetErrorHandler(old_handler); X_UNLOCK; - if (! xi || trapped_xerror) { + 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; @@ -905,6 +1310,8 @@ if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); return; } + set_poll_fb(); + if (xi->depth == 8) { int ps1, ps2, fac; @@ -921,6 +1328,8 @@ if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); src = xi->data; dst = cmap8to24_fb + fac * n_off; + poll = poll8_fb + poll8_fb_w * rect.y1 + rect.x1; + poll_Bpl = poll8_fb_w * 1; /* line by line ... */ for (line = 0; line < h; line++) { @@ -932,10 +1341,13 @@ if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); idx = (int) (*uc); - *ui = rgb[best][idx]; + *ui = rgb[cm][idx]; + + *(poll + ps1 * j) = *uc; } src += xi->bytes_per_line; dst += main_bytes_per_line * fac; + poll += poll_Bpl; } } else if (xi->depth == 24) { /* line by line ... */ @@ -943,16 +1355,22 @@ if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); if (depth == 8) { fac = 4; } else { - fac = 1; /* should not happen */ + fac = 1; /* will not happen */ } 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(dst, src, w * ps1); + memcpy(poll, src, w * ps1); + src += xi->bytes_per_line; dst += main_bytes_per_line * fac; + poll += poll_Bpl; } } @@ -963,11 +1381,11 @@ if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); #endif } else if (! do_getimage) { - /* normal mode. */ int fac; if (depth == 8) { /* cooked up depth 24 TrueColor */ + /* but currently disabled (high bits no useful?) */ ps = 4; fac = 4; src = cmap8to24_fb + 4 * n_off; @@ -990,7 +1408,7 @@ if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); /* map to lookup index; rewrite pixel */ idx = hi >> 24; - *ui = hi | rgb[best][idx]; + *ui = hi | rgb[cm][idx]; } src += main_bytes_per_line * fac; } @@ -1001,55 +1419,44 @@ 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 line, k, i, j, h, w; int n_off; - - sraRegionPtr rect, disp, region8bpp; - + 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, dt, d0; - if (! cmap8to24 || !cmap8to24_fb) { + 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); + 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); + x2 = nfix(x2, dpy_x+1); + y2 = nfix(y2, dpy_y+1); - /* create regions for finding overlap, etc. */ - disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y); - rect = sraRgnCreateRect(x1, y1, x2, y2); - region8bpp = sraRgnCreate(); + 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; + } X_LOCK; XFlush(dpy); /* make sure X server is up to date WRT input, etc */ X_UNLOCK; - if (last_map_count > MAX_8BPP_WINDOWS/4) { - /* table is filling up... skip validating sometimes: */ - int skip = 3; - if (last_map_count > MAX_8BPP_WINDOWS/2) { - skip = 6; - } else if (last_map_count > 3*MAX_8BPP_WINDOWS/4) { - skip = 12; - } - if (call_count % skip != 0) { - validate = 0; - } - } - -if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} - - last_map_count = get_8pp_region(region8bpp, rect, validate); - /* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */ h = y2 - y1; @@ -1058,6 +1465,7 @@ if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} 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; @@ -1065,8 +1473,11 @@ if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} dst = cmap8to24_fb + 4 * n_off; set_root_cmap(); - if (get_cmap(0, root_cmap)) { + if (get_cmap(tcm, root_cmap)) { int ps1 = 1, ps2 = 4; +#if 0 + unsigned int hi; +#endif /* line by line ... */ for (line = 0; line < h; line++) { @@ -1078,12 +1489,14 @@ if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} idx = (int) (*uc); +#if 0 if (do_hibits) { hi = idx << 24; *ui = hi | rgb[0][idx]; } else { - *ui = rgb[0][idx]; } +#endif + *ui = rgb[tcm][idx]; if (db24 > 2) histo[idx]++; } src += main_bytes_per_line; @@ -1106,17 +1519,64 @@ if (db24 > 2) histo[idx]++; } } + 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;}} + + dt = now - last_get_8bpp_validate; + d0 = dnow(); + if (dt < 0.0025) { + ; /* XXX does this still give painting errors? */ + } else { + int snapit = 0; + if (dt < 0.04) { + validate = 0; + } + if (last_map_count) { + if (now > last_snapshot + 0.05) { + snapit = 1; + } + } else { + if (now > last_snapshot + 0.4) { + snapit = 1; + } + } + + if (snapit) { + /* less problems if we update the stack frequently */ + snapshot_stack_list(0, 0.0); + update_stack_list(); + last_snapshot = now; + } + + last_map_count = get_8bpp_regions(validate); + if (validate) { + last_get_8bpp_validate = now; + } + } + 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... + * now go back and transform and 8bpp regions to TrueColor in + * cmap8to24_fb. */ - if (! sraRgnEmpty(region8bpp) && (ncmaps || depth == 8)) { - sraRectangleIterator *iter; - sraRect rect; - int j; + if (last_map_count && (ncmaps || depth == 8)) { + 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 @@ -1128,42 +1588,81 @@ if (db24 > 1) fprintf(stderr, "bpp8to24 w=%d h=%d m=%p c=%p r=%p ncmaps=%d\n", w } else { cmap_failed[j] = 0; } -if (db24 > 1) fprintf(stderr, "cmap %d\n", (int) cmaps[j]); +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); + } } - /* 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 (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; + } + } } - if (rect.y1 > rect.y2) { - int tmp = rect.y2; - rect.y2 = rect.y1; - rect.y1 = tmp; + for (j=0; j<count; j++) { + if (! did[j]) { + i = win[j]; + do_8bpp_region(i, rect); + did[j] = 1; + } } - - do_8bpp_region(rect); + sraRgnDestroy(rect); } - sraRgnReleaseIterator(iter); } if (db24 > 2) {for(i=0; i<256;i++) {fprintf(stderr, " cmap histo[%03d] %d\n", i, histo[i]);}} - - /* cleanup */ - sraRgnDestroy(disp); - sraRgnDestroy(rect); - sraRgnDestroy(region8bpp); } -void mark_8bpp(void) { +void mark_8bpp(int mode) { int i, cnt = 0; + Window top = None; 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: */ @@ -1175,6 +1674,11 @@ void mark_8bpp(void) { 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; @@ -1196,13 +1700,24 @@ void mark_8bpp(void) { w = windows_8bpp[i].w; h = windows_8bpp[i].h; - /* apply a fuzz f around each one... constrain to screen */ 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); - y2 = nfix(y2 + 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); diff --git a/x11vnc/8to24.h b/x11vnc/8to24.h index 9777bf3..7c6a885 100644 --- a/x11vnc/8to24.h +++ b/x11vnc/8to24.h @@ -8,6 +8,6 @@ extern int multivis_24count; extern void check_for_multivis(void); extern void bpp8to24(int, int, int, int); -extern void mark_8bpp(void); +extern void mark_8bpp(int); #endif /* _X11VNC_8TO24_H */ diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index e3d171a..8a5f81b 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,6 @@ +2006-02-04 Karl Runge <runge@karlrunge.com> + * x11vnc: -8to24 speedups and improvements. + 2006-01-21 Karl Runge <runge@karlrunge.com> * x11vnc: -8to24 opts, use XGetSubImage. fix -threads deadlocks and -rawfb crash. diff --git a/x11vnc/README b/x11vnc/README index 1e97c14..a34b6bd 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -1,5 +1,5 @@ -x11vnc README file Date: Sat Jan 21 20:25:28 EST 2006 +x11vnc README file Date: Sat Feb 4 22:21:00 EST 2006 The following information is taken from these URLs: @@ -585,7 +585,7 @@ make I'd appreciate any additional testing very much! Please help test and debug the 0.8 version for release sometime in - Jan/2006. + Feb/2006. [53]x11vnc-0.8.tar.gz @@ -4289,7 +4289,7 @@ ied) Based on the bpp x11vnc will try to guess the red, green, and blue masks (these indicate which bits correspond to each color). It if gets it wrong you can specify them manually via the optional ":R/G/B" - field. E.g. ":0xff000/0x00ff00/0x0000ff" (this is the default for + field. E.g. ":0xff0000/0x00ff00/0x0000ff" (this is the default for 32bpp). Finally, the framebuffer may not begin at the beginning of the memory @@ -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-01-21 +x11vnc: allow VNC connections to real X11 displays. 0.8 lastmod: 2006-02-04 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-01-21 +x11vnc: allow VNC connections to real X11 displays. 0.8 lastmod: 2006-02-04 Typical usage is: @@ -5143,55 +5143,66 @@ Options: -8to24 [opts] Try this option if -overlay is not supported on your OS, and you have a legacy 8bpp app that you want to view on a multi-depth display with default depth 24 - (and is 32 bpp) or have default depth 8 display with + (and is 32 bpp) OR have a default depth 8 display with depth 24 overlay windows for some apps. This option - may not work on all X servers and hardware (tested on - XFree86/Xorg mga driver). The "opts" string is not - required and is described below. + may not work on all X servers and hardware (tested + on XFree86/Xorg mga driver and Xsun). The "opts" + string is not required and is described below. This mode enables a hack where x11vnc monitors windows within 3 levels from the root window. If it finds - any that are 8bpp it will apply a transformation for - pixel data in these regions where it extracts the 8bpp - index color value from bits 25-32 and maps them on - to TrueColor values and inserts them into bits 1-24 - (i.e. overwrites bits 1-24). Whereas for default - depth 8 displays, everything is tranformed to 32bpp - (and is potentially a improvement over -flashcmap). - - These schemes appear to work, but may still have - bugs and note that they do hog resources. If there - are multiple 8bpp windows using different colormaps, - one may have to iconify all but one for the colors to - be correct. - - There may also be painting errors for clipping and - switching between windows of depths 8 and 24. - Heuristics are applied to try to minimize the painting - errors. One can also press 3 Alt_L's in a row to - refresh the screen if the error does not repair itself. - Also the option, say, -fixscreen V=3.0 may be use - to periodically refresh the screen (at the cost of - bandwidth). + any that are 8bpp it extracts the indexed color + pixel values using XGetImage() and then applies a + transformation using the colormap(s) to create TrueColor + RGB values that it in turn inserts into bits 1-24 of + the framebuffer. This creates a depth 24 "view" + of the display that is then exported via VNC. + + Conversely, for default depth 8 displays, the depth + 24 regions are read by XGetImage() and everything is + transformed and inserted into a depth 24 TrueColor + framebuffer. + + Note that even if there are *no* depth 24 visuals or + windows (i.e. pure 8bpp), this mode is potentially + a improvement over -flashcmap because it avoids the + flashing and shows each window in the correct color. + + This method appear to work, but may still have bugs + and it does hog resources. If there are multiple 8bpp + windows using different colormaps, one may have to + iconify all but one for the colors to be correct. + + There may be painting errors for clipping and switching + between windows of depths 8 and 24. Heuristics are + applied to try to minimize the painting errors. + One can also press 3 Alt_L's in a row to refresh the + screen if the error does not repair itself. Also the + option -fixscreen 8=3.0 or -fixscreen V=3.0 may be + use to periodically refresh the screen at the cost of + bandwidth (every 3 sec for this example). The [opts] string can contain the following settings. Multiple settings are separated by commas. - For when there are still color problems, enable an even - more experimental mode via the option "getimage". - This enables a scheme were XGetImage() is used to - retrieve the 8bpp data instead of assuming that data - is in bits 25-32. This mode is significantly slower - than the above mode. For the default depth 8 case, - XGetImage() is always used to access depth 24 pixel - data. - - For default depth 8 displays, setting option - "highbits" may give a speedup for transforming 8bpp - pixel data. + For for some X servers with default depth 24 a + speedup may be achieved via the option "nogetimage". + This enables a scheme were XGetImage() is not used + to retrieve the 8bpp data. Instead, it assumes that + the 8bpp data is in bits 25-32 of the 32bit X pixels. + There is no reason the X server should put the data + there for our poll requests, but some do and so the + extra steps to retrieve it can be skipped. Tested with + mga driver with XFree86/Xorg. For the default depth + 8 case this option is ignored. + + To adjust how often XGetImage() is used to poll the + non-default visual regions for changes, use the option + "poll=t" where "t" is a floating point time. + (default: 0.05) Debugging for this mode can be enabled by setting - "dbg=1", "dbg=2", or "dbg=3" + "dbg=1", "dbg=2", or "dbg=3". -scale fraction Scale the framebuffer by factor "fraction". Values less than 1 shrink the fb, larger ones expand it. Note: @@ -6185,22 +6196,25 @@ Options: but it can be used for any scenario. This option periodically performs costly operations and so interactive response may be reduced when it is on. - You can use 3 Alt_L's (the Left "Alt" key) taps in a - row described under -scrollcopyrect instead to manually - request a screen repaint when it is needed. + You can use 3 Alt_L's (the Left "Alt" key) taps in + a row (as described under -scrollcopyrect) instead to + manually request a screen repaint when it is needed. "string" is a comma separated list of one or more of - the following: "V=t", "C=t", and "X=t". In these - "t" stands for a time in seconds (it is a floating - point even though one should usually use values > 2 to - avoid wasting resources). V sets how frequently the - entire screen should be sent to viewers (it is like the - 3 Alt_L's). C sets how long to wait after a CopyRect - to repaint the full screen. X sets how frequently - to reread the full X11 framebuffer from the X server - and push it out to connected viewers. Use of X should - be rare, please report a bug if you find you need it. - Examples: -fixscreen V=10 -fixscreen C=10 + the following: "V=t", "C=t", "X=t", and "8=t". + In these "t" stands for a time in seconds (it is + a floating point even though one should usually use + values > 2 to avoid wasting resources). V sets how + frequently the entire screen should be sent to viewers + (it is like the 3 Alt_L's). C sets how long to wait + after a CopyRect to repaint the full screen. X sets + how frequently to reread the full X11 framebuffer from + the X server and push it out to connected viewers. + Use of X should be rare, please report a bug if you + find you need it. 8= applies only for -8to24 mode: it + sets how often the non-default visual regions of the + screen (e.g. 8bpp windows) are refreshed. Examples: + -fixscreen V=10 -fixscreen C=10 -debug_scroll Turn on debugging info printout for the scroll heuristics. "-ds" is an alias. Specify it multiple diff --git a/x11vnc/help.c b/x11vnc/help.c index 3e1d019..3a558cd 100644 --- a/x11vnc/help.c +++ b/x11vnc/help.c @@ -151,55 +151,66 @@ void print_help(int mode) { "-8to24 [opts] Try this option if -overlay is not supported on your\n" " OS, and you have a legacy 8bpp app that you want to\n" " view on a multi-depth display with default depth 24\n" -" (and is 32 bpp) or have default depth 8 display with\n" +" (and is 32 bpp) OR have a default depth 8 display with\n" " depth 24 overlay windows for some apps. This option\n" -" may not work on all X servers and hardware (tested on\n" -" XFree86/Xorg mga driver). The \"opts\" string is not\n" -" required and is described below.\n" +" may not work on all X servers and hardware (tested\n" +" on XFree86/Xorg mga driver and Xsun). The \"opts\"\n" +" string is not required and is described below.\n" "\n" " This mode enables a hack where x11vnc monitors windows\n" " within 3 levels from the root window. If it finds\n" -" any that are 8bpp it will apply a transformation for\n" -" pixel data in these regions where it extracts the 8bpp\n" -" index color value from bits 25-32 and maps them on\n" -" to TrueColor values and inserts them into bits 1-24\n" -" (i.e. overwrites bits 1-24). Whereas for default\n" -" depth 8 displays, everything is tranformed to 32bpp\n" -" (and is potentially a improvement over -flashcmap).\n" -"\n" -" These schemes appear to work, but may still have\n" -" bugs and note that they do hog resources. If there\n" -" are multiple 8bpp windows using different colormaps,\n" -" one may have to iconify all but one for the colors to\n" -" be correct.\n" -"\n" -" There may also be painting errors for clipping and\n" -" switching between windows of depths 8 and 24.\n" -" Heuristics are applied to try to minimize the painting\n" -" errors. One can also press 3 Alt_L's in a row to\n" -" refresh the screen if the error does not repair itself.\n" -" Also the option, say, -fixscreen V=3.0 may be use\n" -" to periodically refresh the screen (at the cost of\n" -" bandwidth).\n" +" any that are 8bpp it extracts the indexed color\n" +" pixel values using XGetImage() and then applies a\n" +" transformation using the colormap(s) to create TrueColor\n" +" RGB values that it in turn inserts into bits 1-24 of\n" +" the framebuffer. This creates a depth 24 \"view\"\n" +" of the display that is then exported via VNC.\n" +"\n" +" Conversely, for default depth 8 displays, the depth\n" +" 24 regions are read by XGetImage() and everything is\n" +" transformed and inserted into a depth 24 TrueColor\n" +" framebuffer.\n" +"\n" +" Note that even if there are *no* depth 24 visuals or\n" +" windows (i.e. pure 8bpp), this mode is potentially\n" +" a improvement over -flashcmap because it avoids the\n" +" flashing and shows each window in the correct color.\n" +"\n" +" This method appear to work, but may still have bugs\n" +" and it does hog resources. If there are multiple 8bpp\n" +" windows using different colormaps, one may have to\n" +" iconify all but one for the colors to be correct.\n" +"\n" +" There may be painting errors for clipping and switching\n" +" between windows of depths 8 and 24. Heuristics are\n" +" applied to try to minimize the painting errors.\n" +" One can also press 3 Alt_L's in a row to refresh the\n" +" screen if the error does not repair itself. Also the\n" +" option -fixscreen 8=3.0 or -fixscreen V=3.0 may be\n" +" use to periodically refresh the screen at the cost of\n" +" bandwidth (every 3 sec for this example).\n" "\n" " The [opts] string can contain the following settings.\n" " Multiple settings are separated by commas.\n" "\n" -" For when there are still color problems, enable an even\n" -" more experimental mode via the option \"getimage\".\n" -" This enables a scheme were XGetImage() is used to\n" -" retrieve the 8bpp data instead of assuming that data\n" -" is in bits 25-32. This mode is significantly slower\n" -" than the above mode. For the default depth 8 case,\n" -" XGetImage() is always used to access depth 24 pixel\n" -" data.\n" -"\n" -" For default depth 8 displays, setting option\n" -" \"highbits\" may give a speedup for transforming 8bpp\n" -" pixel data.\n" +" For for some X servers with default depth 24 a\n" +" speedup may be achieved via the option \"nogetimage\".\n" +" This enables a scheme were XGetImage() is not used\n" +" to retrieve the 8bpp data. Instead, it assumes that\n" +" the 8bpp data is in bits 25-32 of the 32bit X pixels.\n" +" There is no reason the X server should put the data\n" +" there for our poll requests, but some do and so the\n" +" extra steps to retrieve it can be skipped. Tested with\n" +" mga driver with XFree86/Xorg. For the default depth\n" +" 8 case this option is ignored.\n" +"\n" +" To adjust how often XGetImage() is used to poll the\n" +" non-default visual regions for changes, use the option\n" +" \"poll=t\" where \"t\" is a floating point time.\n" +" (default: %.2f)\n" "\n" " Debugging for this mode can be enabled by setting \n" -" \"dbg=1\", \"dbg=2\", or \"dbg=3\"\n" +" \"dbg=1\", \"dbg=2\", or \"dbg=3\".\n" "\n" "-scale fraction Scale the framebuffer by factor \"fraction\". Values\n" " less than 1 shrink the fb, larger ones expand it. Note:\n" @@ -1202,22 +1213,25 @@ void print_help(int mode) { " but it can be used for any scenario. This option\n" " periodically performs costly operations and so\n" " interactive response may be reduced when it is on.\n" -" You can use 3 Alt_L's (the Left \"Alt\" key) taps in a\n" -" row described under -scrollcopyrect instead to manually\n" -" request a screen repaint when it is needed.\n" +" You can use 3 Alt_L's (the Left \"Alt\" key) taps in\n" +" a row (as described under -scrollcopyrect) instead to\n" +" manually request a screen repaint when it is needed.\n" "\n" " \"string\" is a comma separated list of one or more of\n" -" the following: \"V=t\", \"C=t\", and \"X=t\". In these\n" -" \"t\" stands for a time in seconds (it is a floating\n" -" point even though one should usually use values > 2 to\n" -" avoid wasting resources). V sets how frequently the\n" -" entire screen should be sent to viewers (it is like the\n" -" 3 Alt_L's). C sets how long to wait after a CopyRect\n" -" to repaint the full screen. X sets how frequently\n" -" to reread the full X11 framebuffer from the X server\n" -" and push it out to connected viewers. Use of X should\n" -" be rare, please report a bug if you find you need it.\n" -" Examples: -fixscreen V=10 -fixscreen C=10\n" +" the following: \"V=t\", \"C=t\", \"X=t\", and \"8=t\".\n" +" In these \"t\" stands for a time in seconds (it is\n" +" a floating point even though one should usually use\n" +" values > 2 to avoid wasting resources). V sets how\n" +" frequently the entire screen should be sent to viewers\n" +" (it is like the 3 Alt_L's). C sets how long to wait\n" +" after a CopyRect to repaint the full screen. X sets\n" +" how frequently to reread the full X11 framebuffer from\n" +" the X server and push it out to connected viewers.\n" +" Use of X should be rare, please report a bug if you\n" +" find you need it. 8= applies only for -8to24 mode: it\n" +" sets how often the non-default visual regions of the\n" +" screen (e.g. 8bpp windows) are refreshed. Examples:\n" +" -fixscreen V=10 -fixscreen C=10\n" "\n" "-debug_scroll Turn on debugging info printout for the scroll\n" " heuristics. \"-ds\" is an alias. Specify it multiple\n" @@ -2062,6 +2076,7 @@ void print_help(int mode) { exit(1); } fprintf(stderr, help, lastmod, + POLL_8TO24_DELAY, scaling_copyrect ? ":cr":":nocr", view_only ? "on":"off", shared ? "on":"off", diff --git a/x11vnc/options.c b/x11vnc/options.c index 7514452..dc3901e 100644 --- a/x11vnc/options.c +++ b/x11vnc/options.c @@ -24,7 +24,7 @@ char *solid_default = "cyan4"; char *wmdt_str = NULL; /* -wmdt */ -char *speeds_str = NULL; /* -speeds TBD */ +char *speeds_str = NULL; /* -speeds */ char *rc_rcfile = NULL; /* -rc */ int rc_rcfile_default = 0; @@ -208,6 +208,7 @@ char* screen_fixup_str = NULL; double screen_fixup_V = 0.0; double screen_fixup_C = 0.0; double screen_fixup_X = 0.0; +double screen_fixup_8 = 0.0; #ifndef NOREPEAT #define NOREPEAT 1 diff --git a/x11vnc/options.h b/x11vnc/options.h index 19e1db1..203ad5f 100644 --- a/x11vnc/options.h +++ b/x11vnc/options.h @@ -154,6 +154,7 @@ extern char* screen_fixup_str; extern double screen_fixup_V; extern double screen_fixup_C; extern double screen_fixup_X; +extern double screen_fixup_8; extern int no_autorepeat; extern int no_repeat_countdown; diff --git a/x11vnc/params.h b/x11vnc/params.h index fca526b..ad10d14 100644 --- a/x11vnc/params.h +++ b/x11vnc/params.h @@ -13,6 +13,10 @@ #define SCROLL_COPYRECT_PARMS "0+64+32+32,0.02+0.10+0.9,0.03+0.06+0.5+0.1+5.0" #endif +#ifndef POLL_8TO24_DELAY +#define POLL_8TO24_DELAY 0.05 +#endif + #define LATENCY0 20 /* 20ms */ #define NETRATE0 20 /* 20KB/sec */ diff --git a/x11vnc/rates.c b/x11vnc/rates.c index 24a145b..aa12f77 100644 --- a/x11vnc/rates.c +++ b/x11vnc/rates.c @@ -200,7 +200,7 @@ void initialize_speeds(void) { int n = 0; double dt, timer; dtime0(&timer); - if (raw_fb && ! dpy) { /* raw_fb hack */ + if (0 && raw_fb && ! dpy) { /* raw_fb hack */ n = 0; } else if (fullscreen) { copy_image(fullscreen, 0, 0, 0, 0); diff --git a/x11vnc/scan.c b/x11vnc/scan.c index 3b0afe6..fd408ce 100644 --- a/x11vnc/scan.c +++ b/x11vnc/scan.c @@ -2379,7 +2379,7 @@ static int scan_display(int ystart, int rescan) { } -static int scanlines[NSCAN] = { +int scanlines[NSCAN] = { 0, 16, 8, 24, 4, 20, 12, 28, 10, 26, 18, 2, 22, 6, 30, 14, 1, 17, 9, 25, 7, 23, 15, 31, @@ -2435,7 +2435,7 @@ int scan_for_updates(int count_only) { /* check for changed colormap */ set_colormap(0); } - if (cmap8to24 && scan_count % 4 == 0) { + if (cmap8to24 && scan_count % 1 == 0) { check_for_multivis(); } if (use_xdamage) { diff --git a/x11vnc/scan.h b/x11vnc/scan.h index 55f45f1..f2765e1 100644 --- a/x11vnc/scan.h +++ b/x11vnc/scan.h @@ -4,6 +4,7 @@ /* -- scan.h -- */ extern int nap_ok; +extern int scanlines[]; extern void initialize_tiles(void); extern void free_tiles(void); diff --git a/x11vnc/userinput.c b/x11vnc/userinput.c index ef2a765..9c75ef8 100644 --- a/x11vnc/userinput.c +++ b/x11vnc/userinput.c @@ -211,6 +211,7 @@ void parse_fixscreen(void) { screen_fixup_V = 0.0; screen_fixup_C = 0.0; screen_fixup_X = 0.0; + screen_fixup_8 = 0.0; if (! screen_fixup_str) { return; @@ -227,6 +228,8 @@ void parse_fixscreen(void) { screen_fixup_C = t; } else if (*p == 'X' && sscanf(p, "X=%lf", &t) == 1) { screen_fixup_X = t; + } else if (*p == 'X' && sscanf(p, "8=%lf", &t) == 1) { + screen_fixup_8 = t; } p = strtok(NULL, ","); } @@ -235,6 +238,7 @@ void parse_fixscreen(void) { if (screen_fixup_V < 0.0) screen_fixup_V = 0.0; if (screen_fixup_C < 0.0) screen_fixup_C = 0.0; if (screen_fixup_X < 0.0) screen_fixup_X = 0.0; + if (screen_fixup_8 < 0.0) screen_fixup_8 = 0.0; } /* @@ -716,11 +720,11 @@ typedef struct saveline { */ static void draw_box(int x, int y, int w, int h, int restore) { int x0, y0, x1, y1, i, pixelsize = bpp/8; - char *dst, *src; + char *dst, *src, *use_fb; static saveline_t *save[4]; static int first = 1, len = 0; int max = dpy_x > dpy_y ? dpy_x : dpy_y; - int sz, lw = wireframe_lw; + int use_Bpl, lw = wireframe_lw; unsigned long shade = wireframe_shade; int color = 0; unsigned short us = 0; @@ -730,7 +734,18 @@ static void draw_box(int x, int y, int w, int h, int restore) { x -= coff_x; y -= coff_y; } - /* no subwin for wireframe */ + + /* handle -8to24 mode: use 2nd fb only */ + use_fb = main_fb; + use_Bpl = main_bytes_per_line; + + if (cmap8to24 && cmap8to24_fb) { + use_fb = cmap8to24_fb; + pixelsize = 4; + if (depth == 8) { + use_Bpl *= 4; + } + } if (max > len) { /* create/resize storage lines: */ @@ -745,8 +760,7 @@ static void draw_box(int x, int y, int w, int h, int restore) { } save[i] = (saveline_t *) malloc(sizeof(saveline_t)); save[i]->saved = 0; - sz = (LW_MAX+1)*len*pixelsize; - save[i]->data = (char *) malloc(sz); + save[i]->data = (char *) malloc( (LW_MAX+1)*len*4 ); /* * Four types of lines: @@ -813,8 +827,7 @@ static void draw_box(int x, int y, int w, int h, int restore) { y_max = yu; } src = save[i]->data + (yu-y_start)*y_step; - dst = main_fb + yu*main_bytes_per_line + - x0*pixelsize; + dst = use_fb + yu*use_Bpl + x0*pixelsize; memcpy(dst, src, (x1-x0)*pixelsize); } if (y_min >= 0) { @@ -917,10 +930,9 @@ if (0) fprintf(stderr, " DrawBox: %dx%d+%d+%d\n", w, h, x, y); /* save fb data for this line: */ save[i]->saved = 1; - src = main_fb + yu*main_bytes_per_line + - x0*pixelsize; + src = use_fb + yu*use_Bpl + x0*pixelsize; dst = save[i]->data + (yu-y_start)*y_step; - memcpy(dst, src, (x1-x0)*pixelsize); + memcpy(dst, src, (x1-x0)*pixelsize); /* apply the shade/color to make the wireframe line: */ if (! color) { @@ -1577,6 +1589,7 @@ if (0) fprintf(stderr, " try_copyrect dt: %.4f\n", dt); win_area += (tx2 - tx1)*(ty2 - ty1); } sraRgnReleaseIterator(iter); + sraRgnDestroy(tmpregion); @@ -1634,6 +1647,7 @@ if (db) fprintf(stderr, " DFC(%d,%d-%d,%d)", tx1, ty1, tx2, ty2); PUSH_TEST(0); } sraRgnReleaseIterator(iter); + dt = dtime(&tm); if (db) fprintf(stderr, " dfc---- dt: %.4f", dt); @@ -3726,20 +3740,22 @@ if (db) fprintf(stderr, "send_copyrect: %d\n", sent_copyrect); rfbPE(1000); wireframe_in_progress = 0; - if (frame_changed && cmap8to24 && multivis_count) { - /* handle -8to24 tweak, mark area and check 8bpp... */ + if (0) { + /* No longer needed. see draw_box() */ + if (frame_changed && cmap8to24 && multivis_count) { + /* handle -8to24 kludge, mark area and check 8bpp... */ int x1, x2, y1, y2, f = 16; x1 = nmin(box_x, orig_x) - f; y1 = nmin(box_y, orig_y) - f; x2 = nmax(box_x + box_w, orig_x + orig_w) + f; y2 = nmax(box_y + box_h, orig_y + orig_h) + f; x1 = nfix(x1, dpy_x); - x2 = nfix(x2, dpy_x); + x2 = nfix(x2, dpy_x+1); y1 = nfix(y1, dpy_y); - y2 = nfix(y2, dpy_y); -if (0) fprintf(stderr, "wireframe_in_progress over: %d %d %d %d\n", x1, y1, x2, y2); + y2 = nfix(y2, dpy_y+1); check_for_multivis(); - if (1) mark_rect_as_modified(x1, y1, x2, y2, 0); + mark_rect_as_modified(x1, y1, x2, y2, 0); + } } urgent_update = 1; diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index 78cc379..fb99e80 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -1,8 +1,8 @@ .\" This file was automatically generated from x11vnc -help output. -.TH X11VNC "1" "January 2006" "x11vnc " "User Commands" +.TH X11VNC "1" "February 2006" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.8, lastmod: 2006-01-21 + version: 0.8, lastmod: 2006-02-04 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -183,55 +183,66 @@ cursor shape using the overlay mechanism. Try this option if \fB-overlay\fR is not supported on your OS, and you have a legacy 8bpp app that you want to view on a multi-depth display with default depth 24 -(and is 32 bpp) or have default depth 8 display with +(and is 32 bpp) OR have a default depth 8 display with depth 24 overlay windows for some apps. This option -may not work on all X servers and hardware (tested on -XFree86/Xorg mga driver). The "opts" string is not -required and is described below. +may not work on all X servers and hardware (tested +on XFree86/Xorg mga driver and Xsun). The "opts" +string is not required and is described below. .IP This mode enables a hack where x11vnc monitors windows within 3 levels from the root window. If it finds -any that are 8bpp it will apply a transformation for -pixel data in these regions where it extracts the 8bpp -index color value from bits 25-32 and maps them on -to TrueColor values and inserts them into bits 1-24 -(i.e. overwrites bits 1-24). Whereas for default -depth 8 displays, everything is tranformed to 32bpp -(and is potentially a improvement over \fB-flashcmap).\fR -.IP -These schemes appear to work, but may still have -bugs and note that they do hog resources. If there -are multiple 8bpp windows using different colormaps, -one may have to iconify all but one for the colors to -be correct. -.IP -There may also be painting errors for clipping and -switching between windows of depths 8 and 24. -Heuristics are applied to try to minimize the painting -errors. One can also press 3 Alt_L's in a row to -refresh the screen if the error does not repair itself. -Also the option, say, \fB-fixscreen\fR V=3.0 may be use -to periodically refresh the screen (at the cost of -bandwidth). +any that are 8bpp it extracts the indexed color +pixel values using XGetImage() and then applies a +transformation using the colormap(s) to create TrueColor +RGB values that it in turn inserts into bits 1-24 of +the framebuffer. This creates a depth 24 "view" +of the display that is then exported via VNC. +.IP +Conversely, for default depth 8 displays, the depth +24 regions are read by XGetImage() and everything is +transformed and inserted into a depth 24 TrueColor +framebuffer. +.IP +Note that even if there are *no* depth 24 visuals or +windows (i.e. pure 8bpp), this mode is potentially +a improvement over \fB-flashcmap\fR because it avoids the +flashing and shows each window in the correct color. +.IP +This method appear to work, but may still have bugs +and it does hog resources. If there are multiple 8bpp +windows using different colormaps, one may have to +iconify all but one for the colors to be correct. +.IP +There may be painting errors for clipping and switching +between windows of depths 8 and 24. Heuristics are +applied to try to minimize the painting errors. +One can also press 3 Alt_L's in a row to refresh the +screen if the error does not repair itself. Also the +option \fB-fixscreen\fR 8=3.0 or \fB-fixscreen\fR V=3.0 may be +use to periodically refresh the screen at the cost of +bandwidth (every 3 sec for this example). .IP The [opts] string can contain the following settings. Multiple settings are separated by commas. .IP -For when there are still color problems, enable an even -more experimental mode via the option "getimage". -This enables a scheme were XGetImage() is used to -retrieve the 8bpp data instead of assuming that data -is in bits 25-32. This mode is significantly slower -than the above mode. For the default depth 8 case, -XGetImage() is always used to access depth 24 pixel -data. -.IP -For default depth 8 displays, setting option -"highbits" may give a speedup for transforming 8bpp -pixel data. +For for some X servers with default depth 24 a +speedup may be achieved via the option "nogetimage". +This enables a scheme were XGetImage() is not used +to retrieve the 8bpp data. Instead, it assumes that +the 8bpp data is in bits 25-32 of the 32bit X pixels. +There is no reason the X server should put the data +there for our poll requests, but some do and so the +extra steps to retrieve it can be skipped. Tested with +mga driver with XFree86/Xorg. For the default depth +8 case this option is ignored. +.IP +To adjust how often XGetImage() is used to poll the +non-default visual regions for changes, use the option +"poll=t" where "t" is a floating point time. +(default: 0.05) .IP Debugging for this mode can be enabled by setting -"dbg=1", "dbg=2", or "dbg=3" +"dbg=1", "dbg=2", or "dbg=3". .PP \fB-scale\fR \fIfraction\fR .IP @@ -1477,22 +1488,25 @@ it is intended for cases when the \fB-scrollcopyrect\fR or but it can be used for any scenario. This option periodically performs costly operations and so interactive response may be reduced when it is on. -You can use 3 Alt_L's (the Left "Alt" key) taps in a -row described under \fB-scrollcopyrect\fR instead to manually -request a screen repaint when it is needed. +You can use 3 Alt_L's (the Left "Alt" key) taps in +a row (as described under \fB-scrollcopyrect)\fR instead to +manually request a screen repaint when it is needed. .IP \fIstring\fR is a comma separated list of one or more of -the following: "V=t", "C=t", and "X=t". In these -"t" stands for a time in seconds (it is a floating -point even though one should usually use values > 2 to -avoid wasting resources). V sets how frequently the -entire screen should be sent to viewers (it is like the -3 Alt_L's). C sets how long to wait after a CopyRect -to repaint the full screen. X sets how frequently -to reread the full X11 framebuffer from the X server -and push it out to connected viewers. Use of X should -be rare, please report a bug if you find you need it. -Examples: \fB-fixscreen\fR V=10 \fB-fixscreen\fR C=10 +the following: "V=t", "C=t", "X=t", and "8=t". +In these "t" stands for a time in seconds (it is +a floating point even though one should usually use +values > 2 to avoid wasting resources). V sets how +frequently the entire screen should be sent to viewers +(it is like the 3 Alt_L's). C sets how long to wait +after a CopyRect to repaint the full screen. X sets +how frequently to reread the full X11 framebuffer from +the X server and push it out to connected viewers. +Use of X should be rare, please report a bug if you +find you need it. 8= applies only for \fB-8to24\fR mode: it +sets how often the non-default visual regions of the +screen (e.g. 8bpp windows) are refreshed. Examples: +\fB-fixscreen\fR V=10 \fB-fixscreen\fR C=10 .PP \fB-debug_scroll\fR .IP diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 020df6e..36e0ff9 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -908,6 +908,8 @@ static void print_settings(int try_http, int bg, char *gui_str) { fprintf(stderr, " shiftcmap: %d\n", shift_cmap); fprintf(stderr, " force_idx: %d\n", force_indexed_color); fprintf(stderr, " cmap8to24: %d\n", cmap8to24); + fprintf(stderr, " 8to24_opts: %s\n", cmap8to24_str ? cmap8to24_str + : "null"); fprintf(stderr, " visual: %s\n", visual_str ? visual_str : "null"); fprintf(stderr, " overlay: %d\n", overlay); @@ -1277,6 +1279,7 @@ int main(int argc, char* argv[]) { char *s = argv[i+1]; if (s[0] != '-') { cmap8to24_str = strdup(s); + i++; } } } else if (!strcmp(arg, "-visual")) { diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index a4ec2ec..d4bc860 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-01-21"; +char lastmod[] = "0.8 lastmod: 2006-02-04"; /* X display info */ diff --git a/x11vnc/xinerama.c b/x11vnc/xinerama.c index 975298b..229816f 100644 --- a/x11vnc/xinerama.c +++ b/x11vnc/xinerama.c @@ -213,8 +213,8 @@ static void blackout_tiles(void) { break; } } - sraRgnReleaseIterator(iter); + sraRgnDestroy(black_reg); sraRgnDestroy(tile_reg); @@ -322,6 +322,7 @@ static void initialize_xinerama (void) { sprintf(tstr, "%dx%d+%d+%d,", w, h, x, y); strcat(bstr, tstr); } + sraRgnReleaseIterator(iter); initialize_blackouts(bstr); free(bstr); |