9
int multivis_count = 0;
10
int multivis_24count = 0;
12
void check_for_multivis(void);
13
void bpp8to24(int, int, int, int);
17
void check_for_multivis(void) {}
18
void bpp8to24(int x, int y, int z, int t) {}
19
void mark_8bpp(int x) {}
23
static void set_root_cmap(void);
24
static int check_pointer_in_depth24(void);
25
static void parse_cmap8to24(void);
26
static void set_poll_fb(void);
27
static int check_depth(Window win, Window top, int doall);
28
static int check_depth_win(Window win, Window top, XWindowAttributes *attr);
29
static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w);
30
static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod);
31
static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod);
32
static int poll_8bpp(sraRegionPtr, int);
33
static void poll_8bpp_complement(sraRegionPtr);
34
static void mark_rgn_rects(sraRegionPtr mod);
35
static int get_8bpp_regions(int validate);
36
static int get_cmap(int j, Colormap cmap);
37
static void do_8bpp_region(int n, sraRegionPtr mark);
38
static XImage *cmap_xi(XImage *xi, Window win, int win_depth);
39
static void transform_rect(sraRect rect, Window win, int win_depth, int cm);
41
/* struct for keeping info about the 8bpp windows: */
42
typedef struct window8 {
53
sraRegionPtr clip_region;
56
enum mark_8bpp_modes {
64
static Colormap root_cmap = 0;
65
static unsigned int root_rgb[NCOLOR];
67
static void set_root_cmap(void) {
72
static time_t last_set = 0;
73
time_t now = time(NULL);
74
XWindowAttributes attr;
75
static XColor color[NCOLOR];
80
if (now > last_set + 10) {
83
if (! root_cmap || redo) {
85
if (! valid_window(window, &attr, 1)) {
90
int i, ncells = NCOLOR;
91
for (i=0; i < ncells; i++) {
96
root_cmap = attr.colormap;
97
XQueryColors(dpy, root_cmap, color, ncells);
98
for (i=0; i < ncells; i++) {
99
unsigned int red, green, blue;
100
/* strip out highest 8 bits of values: */
101
red = (color[i].red & 0xff00) >> 8;
102
green = (color[i].green & 0xff00) >> 8;
103
blue = (color[i].blue & 0xff00) >> 8;
106
* the maxes should be at 255 already,
107
* but just in case...
109
red = (main_red_max * red )/255;
110
green = (main_green_max * green)/255;
111
blue = (main_blue_max * blue )/255;
113
/* shift them over and or together for value */
114
red = red << main_red_shift;
115
green = green << main_green_shift;
116
blue = blue << main_blue_shift;
118
/* store it in the array to be used later */
119
root_rgb[i] = red | green | blue;
127
/* fixed size array. Will primarily hold visible 8bpp windows */
128
#define MAX_8BPP_WINDOWS 64
129
static window8bpp_t windows_8bpp[MAX_8BPP_WINDOWS];
132
static int xgetimage_8to24 = 1;
133
static double poll_8to24_delay = POLL_8TO24_DELAY;
134
static double cache_win = 0.0;
135
static int level2_8to24 = 0;
137
static int check_pointer_in_depth24(void) {
138
int tries = 0, in_24 = 0;
139
XWindowAttributes attr;
147
if (now > last_keyboard_time + 1.0 && now > last_pointer_time + 1.0) {
152
while (c && tries++ < 3) {
153
c = query_pointer(c);
154
if (valid_window(c, &attr, 1)) {
155
if (attr.depth == 24) {
165
xtranslate(c, window, 0, 0, &x1, &y1, &w, 1);
167
x2 = x1 + attr.width;
168
y2 = y1 + attr.height;
169
x1 = nfix(x1, dpy_x);
170
y1 = nfix(y1, dpy_y);
171
x2 = nfix(x2, dpy_x+1);
172
y2 = nfix(y2, dpy_y+1);
173
mark_rect_as_modified(x1, y1, x2, y2, 0);
175
if (db24 > 1) fprintf(stderr, "check_pointer_in_depth24 %d %d %d %d\n", x1, y1, x2, y2);
182
static void parse_cmap8to24(void) {
184
char *p, *str = strdup(cmap8to24_str);
185
p = strtok(str, ",");
189
poll_8to24_delay = POLL_8TO24_DELAY;
193
if (strstr(p, "dbg=") == p) {
194
db24 = atoi(p + strlen("dbg="));
195
} else if (strstr(p, "poll=") == p) {
196
poll_8to24_delay = atof(p + strlen("poll="));
197
} else if (strstr(p, "cachewin=") == p) {
198
cache_win = atof(p + strlen("cachewin="));
199
} else if (!strcmp(p, "nogetimage")) {
201
} else if (!strcmp(p, "level2")) {
204
p = strtok(NULL, ",");
208
if (getenv("DEBUG_8TO24") != NULL) {
209
db24 = atoi(getenv("DEBUG_8TO24"));
211
if (getenv("NOXGETIMAGE_8TO24") != NULL) {
217
static char *poll8_fb = NULL, *poll24_fb = NULL;
218
static int poll8_fb_w = 0, poll8_fb_h = 0;
219
static int poll24_fb_w = 0, poll24_fb_h = 0;
221
static void pfb(int fac, char **fb, int *w, int *h) {
222
if (! *fb || *w != dpy_x || *h != dpy_y) {
226
*fb = (char *) calloc(fac * dpy_x * dpy_y, 1);
232
static void set_poll_fb(void) {
233
/* create polling framebuffers or recreate if too small. */
235
if (! xgetimage_8to24) {
236
return; /* this saves a bit of RAM */
238
pfb(4, &poll24_fb, &poll24_fb_w, &poll24_fb_h);
239
pfb(1, &poll8_fb, &poll8_fb_w, &poll8_fb_h);
247
void check_for_multivis(void) {
252
XWindowAttributes attr;
255
static int first = 1;
256
static Window *stack_old = NULL;
257
static int stack_old_len = 0;
258
static double last_parse = 0.0;
259
static double last_update = 0.0;
260
static double last_clear = 0.0;
261
static double last_poll = 0.0;
262
static double last_fixup = 0.0;
263
static double last_call = 0.0;
264
static double last_query = 0.0;
270
if (now > last_parse + 1.0) {
274
if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call);
279
/* initialize 8bpp window table: */
280
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
281
windows_8bpp[i].win = None;
282
windows_8bpp[i].top = None;
283
windows_8bpp[i].map_state = IsUnmapped;
284
windows_8bpp[i].cmap = (Colormap) 0;
285
windows_8bpp[i].fetched = 0;
286
windows_8bpp[i].last_fetched = -1.0;
287
windows_8bpp[i].clip_region = NULL;
292
doall = 1; /* fetch everything first time */
295
if (wireframe_in_progress) {
302
* allocate an "old stack" list of all toplevels. we compare
303
* this to the current stack to guess stacking order changes.
305
if (!stack_old || stack_old_len < stack_list_len) {
306
int n = stack_list_len;
313
stack_old = (Window *) malloc(n*sizeof(Window));
317
/* fill the old stack with visible windows: */
319
for (k=0; k < stack_list_num; k++) {
320
if (stack_list[k].valid &&
321
stack_list[k].map_state == IsViewable) {
322
stack_old[cnt++] = stack_list[k].win;
326
/* snapshot + update the current stacking order: */
328
if (poll_8to24_delay >= POLL_8TO24_DELAY) {
329
delay = 3.0 * poll_8to24_delay;
331
delay = 3.0 * POLL_8TO24_DELAY; /* 0.15 */
333
if (doall || now > last_update + delay) {
334
snapshot_stack_list(0, 0.0);
339
/* look for differences in the visible toplevels: */
342
for (k=0; k < stack_list_num; k++) {
343
if (stack_list[k].valid && stack_list[k].map_state ==
345
if (stack_old[cnt] != stack_list[k].win) {
354
multivis_24count = 0;
357
* every 10 seconds we try to clean out and also refresh the window
358
* info in the the 8bpp window table:
360
if (now > last_clear + 10) {
363
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
364
Window w = windows_8bpp[i].win;
365
if (! valid_window(w, &attr, 1)) {
366
/* catch windows that went away: */
367
windows_8bpp[i].win = None;
368
windows_8bpp[i].top = None;
369
windows_8bpp[i].map_state = IsUnmapped;
370
windows_8bpp[i].cmap = (Colormap) 0;
371
windows_8bpp[i].fetched = 0;
372
windows_8bpp[i].last_fetched = -1.0;
384
/* loop over all toplevels, both 8 and 24 depths: */
386
X_LOCK; /* a giant lock around the whole activity */
388
for (k=0; k < stack_list_num; k++) {
394
XErrorHandler old_handler;
397
Window win = stack_list[k].win;
400
if (poll_8to24_delay >= POLL_8TO24_DELAY) {
401
delay = 1.5 * poll_8to24_delay;
403
delay = 1.5 * POLL_8TO24_DELAY; /* 0.075 */
406
if (now < last_query + delay) {
414
if (stack_list[k].map_state != IsViewable) {
417
* if the toplevel became unmapped, mark it
418
* for the children as well...
420
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
421
if (windows_8bpp[i].top == win) {
422
windows_8bpp[i].map_state =
423
stack_list[k].map_state;
428
if (check_depth(win, win, doall)) {
430
* returns 1 if no need to recurse down e.g. It
431
* is 8bpp and we assume all lower one are too.
436
/* we recurse up to two levels down from stack_list windows */
438
old_handler = XSetErrorHandler(trap_xerror);
440
rc = XQueryTree_wr(dpy, win, &r, &parent, &list0, &nc0);
441
XSetErrorHandler(old_handler);
443
if (! rc || trapped_xerror) {
449
/* loop over grandchildren of rootwin: */
450
for (i1=0; i1 < (int) nc0; i1++) {
451
Window win1 = list0[i1];
456
if (check_depth(win1, win, doall)) {
464
old_handler = XSetErrorHandler(trap_xerror);
466
rc = XQueryTree_wr(dpy, win1, &r, &parent, &list1, &nc1);
467
XSetErrorHandler(old_handler);
469
if (! rc || trapped_xerror) {
475
/* loop over great-grandchildren of rootwin: */
476
for (i2=0; i2< (int) nc1; i2++) {
477
Window win2 = list1[i2];
479
if (check_depth(win2, win, doall)) {
482
/* more? Which wm does this? */
497
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));
499
if (screen_fixup_8 > 0.0 && now > last_fixup + screen_fixup_8) {
501
mark_8bpp(MARK_8BPP_ALL);
504
} else if (poll_8to24_delay > 0.0) {
508
if (diff && multivis_count) {
511
if (now > last_poll + poll_8to24_delay) {
515
mod = sraRgnCreate();
516
area = poll_8bpp(mod, validate);
518
poll_8bpp_complement(mod);
523
if (0 && area < dpy_x * dpy_y / 2 && diff && multivis_count) {
524
mark_8bpp(MARK_8BPP_POINTER);
528
} else if (diff && multivis_count) {
529
mark_8bpp(MARK_8BPP_ALL);
532
} else if (depth == 8 && multivis_24count) {
533
static double last_check = 0.0;
534
if (now > last_check + 0.4) {
536
if (check_pointer_in_depth24()) {
541
if (0) fprintf(stderr, "done: %.4f\n", dnow() - last_query);
545
#define VW_CACHE_MAX 1024
546
static XWindowAttributes vw_cache_attr[VW_CACHE_MAX];
547
static Window vw_cache_win[VW_CACHE_MAX];
549
static void set_attr(XWindowAttributes *attr, int j) {
550
memcpy((void *) (vw_cache_attr+j), (void *) attr,
551
sizeof(XWindowAttributes));
554
static int get_attr(XWindowAttributes *attr, int j) {
555
memcpy((void *) attr, (void *) (vw_cache_attr+j),
556
sizeof(XWindowAttributes));
561
static XWindowAttributes wattr;
563
static XWindowAttributes *vw_lookup(Window win) {
564
static double last_purge = 0.0;
573
if (now > last_purge + cache_win) {
575
for (i=0; i<VW_CACHE_MAX; i++) {
576
vw_cache_win[i] = None;
582
for (i=0; i<VW_CACHE_MAX; i++) {
583
if (vw_cache_win[i] == win) {
586
} else if (vw_cache_win[i] == None) {
594
return vw_cache_attr+j;
597
XWindowAttributes attr2;
598
int rc = valid_window(win, &attr2, 1);
600
vw_cache_win[k] = win;
602
return vw_cache_attr+k;
608
int rc = valid_window(win, &wattr, 1);
617
static int check_depth(Window win, Window top, int doall) {
618
XWindowAttributes attr, *pattr;
620
/* first see if it is (still) a valid window: */
623
if (cache_win > 0.0) {
624
pattr = vw_lookup(win);
626
return 1; /* indicate done */
629
if (! valid_window(win, &attr, 1)) {
630
return 1; /* indicate done */
635
if (! doall && pattr->map_state != IsViewable) {
637
* store results anyway... this may lead to table
638
* filling up, but currently this allows us to update
639
* state of onetime mapped windows.
641
check_depth_win(win, top, pattr);
642
return 1; /* indicate done */
643
} else if (check_depth_win(win, top, pattr)) {
644
return 1; /* indicate done */
646
return 0; /* indicate not done */
650
static int check_depth_win(Window win, Window top, XWindowAttributes *attr) {
653
* only store windows with depth not equal to the default visual's
654
* depth note some windows can have depth == 0 ... (skip them).
656
if (attr->depth > 0) {
657
if (depth == 24 && attr->depth != 24) {
659
} else if (depth == 8 && root_cmap && attr->colormap !=
666
int i, j = -1, none = -1, nomap = -1;
668
if (attr->map_state == IsViewable) {
669
/* count the visible ones: */
671
if (attr->depth == 24) {
674
if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr->depth);
677
/* try to find a table slot for this window: */
678
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
679
if (none < 0 && windows_8bpp[i].win == None) {
680
/* found first None */
683
if (windows_8bpp[i].win == win) {
688
if (nomap < 0 && windows_8bpp[i].win != None &&
689
windows_8bpp[i].map_state != IsViewable) {
690
/* found first unmapped */
695
if (attr->map_state != IsViewable) {
696
/* no slot and not visible: not worth keeping */
698
} else if (none >= 0) {
699
/* put it in the first None slot */
702
} else if (nomap >=0) {
703
/* put it in the first unmapped slot */
706
/* otherwise we cannot store it... */
709
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);
711
/* store if if we found a slot j: */
717
if (attr->map_state == IsViewable &&
718
windows_8bpp[j].map_state != IsViewable) {
721
if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d dep=%d\n", win, j, attr->map_state, attr->depth);
722
windows_8bpp[j].win = win;
723
windows_8bpp[j].top = top;
724
windows_8bpp[j].depth = attr->depth;
725
windows_8bpp[j].map_state = attr->map_state;
726
windows_8bpp[j].cmap = attr->colormap;
727
windows_8bpp[j].map_installed = attr->map_installed;
728
windows_8bpp[j].w = attr->width;
729
windows_8bpp[j].h = attr->height;
730
windows_8bpp[j].fetched = 1;
731
windows_8bpp[j].last_fetched = dnow();
733
/* translate x y to be WRT the root window (not parent) */
734
xtranslate(win, window, 0, 0, &x, &y, &w, 1);
735
windows_8bpp[j].x = x;
736
windows_8bpp[j].y = y;
738
if (new || now_vis) {
739
if (db24) fprintf(stderr, "new/now_vis: 0x%lx %d/%d\n", win, new, now_vis);
740
/* mark it immediately if a new one: */
741
X_UNLOCK; /* dont forget the giant lock */
742
mark_rect_as_modified(x, y, x + attr->width,
743
y + attr->height, 0);
748
* Error: could not find a slot.
749
* perhaps keep age and expire old ones??
751
if (db24) fprintf(stderr, "multivis: CANNOT STORE 0x%lx j=%d\n", win, j);
752
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
753
if (db24 > 1) fprintf(stderr, " ------------ 0x%lx i=%d\n", windows_8bpp[i].win, i);
762
static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w) {
766
if (!xi || !visual || !win_depth || !w) {}
769
if (xi == NULL || *w < dpy_x) {
774
if (win_depth == 8) {
775
d = (char *) malloc(dpy_x * 1);
777
d = (char *) malloc(dpy_x * 4);
780
xi = XCreateImage(dpy, visual, win_depth, ZPixmap, 0, d,
787
static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) {
790
if (!x1 || !x2 || !y1 || !n || !mod) {}
793
int fac, n_off, w, xo, yo;
794
char *poll_fb, *dst, *src;
795
int w2, xl, xh, stride = 32;
796
int inrun = 0, rx1 = -1, rx2 = -1;
798
static XImage *xi8 = NULL, *xi24 = NULL, *xi_r;
799
static int xi8_w = 0, xi24_w = 0;
801
XErrorHandler old_handler = NULL;
803
Window c, win = windows_8bpp[n].win;
805
static XWindowAttributes attr;
806
static Window last_win = None;
807
static double last_time = 0.0;
811
int mx1, mx2, my1, my2;
819
if (windows_8bpp[n].map_state != IsViewable) {
822
if (! xgetimage_8to24) {
828
if (last_win != None && win == last_win && now < last_time + 0.5) {
829
; /* use previous attr */
831
if (! valid_window(win, &attr, 1)) {
840
if (attr.depth != 8 && attr.depth != 24) {
843
} else if (attr.depth == 8) {
844
xi = xi8 = p_xi(xi8, attr.visual, 8, &xi8_w);
848
n_off = poll8_fb_w * y1 + x1;
850
xi = xi24 = p_xi(xi24, attr.visual, 24, &xi24_w);
854
n_off = poll24_fb_w * y1 + x1;
857
old_handler = XSetErrorHandler(trap_xerror);
860
/* xtranslate() not used to save two XSetErrorHandler calls */
861
XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c);
867
if (trapped_xerror || xo < 0 || yo < 0 || xo + w > attr.width) {
868
if (db24 > 2) fprintf(stderr, "avoid bad match...\n");
869
XSetErrorHandler(old_handler);
876
xi_r = XGetSubImage(dpy, win, xo, yo, w, 1, AllPlanes, ZPixmap, xi,
878
XSetErrorHandler(old_handler);
881
if (! xi_r || trapped_xerror) {
888
dst = poll_fb + fac * n_off;
899
if (memcmp(dst, src, fac * w2)) {
911
my1 = nfix(y1 - ns, dpy_y);
912
my2 = nfix(y1 + ns, dpy_y+1);
914
rect = sraRgnCreateRect(mx1, my1, mx2, my2);
929
my1 = nfix(y1 - ns, dpy_y);
930
my2 = nfix(y1 + ns, dpy_y+1);
932
rect = sraRgnCreateRect(mx1, my1, mx2, my2);
940
static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod) {
941
int n_off, w, xl, xh, stride = 32;
943
int inrun = 0, rx1 = -1, rx2 = -1;
945
int mx1, mx2, my1, my2;
951
if (! cmap8to24_fb) {
954
if (! xgetimage_8to24) {
958
n_off = main_bytes_per_line * y1 + 4 * x1;
960
src = main_fb + n_off;
961
dst = cmap8to24_fb + n_off;
972
if (memcmp(dst, src, 4 * w)) {
984
my1 = nfix(y1 - ns, dpy_y);
985
my2 = nfix(y1 + ns, dpy_y+1);
987
rect = sraRgnCreateRect(mx1, my1, mx2, my2);
1003
my1 = nfix(y1 - ns, dpy_y);
1004
my2 = nfix(y1 + ns, dpy_y+1);
1006
rect = sraRgnCreateRect(mx1, my1, mx2, my2);
1007
sraRgnOr(mod, rect);
1008
sraRgnDestroy(rect);
1015
static Colormap cmaps[CMAPMAX];
1018
static int poll_8bpp(sraRegionPtr mod, int validate) {
1019
int i, y, ysh, map_count;
1020
static int ycnt = 0;
1023
sraRectangleIterator *iter;
1024
int br = 0, area = 0;
1025
static double last_call = 0.0;
1027
map_count = get_8bpp_regions(validate);
1029
if (db24 > 1) fprintf(stderr, "poll_8bpp mc: %d\n", map_count);
1037
ysh = scanlines[(ycnt++) % NSCAN];
1038
if (db24 > 2) fprintf(stderr, "poll_8bpp: ysh: %2d %.4f\n", ysh, dnow() - last_call);
1041
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
1042
sraRegionPtr reg = windows_8bpp[i].clip_region;
1044
if (! reg || sraRgnEmpty(reg)) {
1049
line = sraRgnCreateRect(0, y, dpy_x, y+1);
1051
if (sraRgnAnd(line, reg)) {
1052
iter = sraRgnGetIterator(line);
1053
while (sraRgnIteratorNext(iter, &rect)) {
1054
if (! poll_line(rect.x1, rect.x2,
1057
break; /* exception */
1060
sraRgnReleaseIterator(iter);
1063
sraRgnDestroy(line);
1070
iter = sraRgnGetIterator(mod);
1071
while (sraRgnIteratorNext(iter, &rect)) {
1072
area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1));
1074
sraRgnReleaseIterator(iter);
1079
static void poll_8bpp_complement(sraRegionPtr mod) {
1081
static int ycnt = 0;
1082
sraRegionPtr disp, line;
1084
sraRectangleIterator *iter;
1086
disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
1088
ysh = scanlines[(ycnt++) % NSCAN];
1090
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
1091
sraRegionPtr reg = windows_8bpp[i].clip_region;
1096
if (windows_8bpp[i].map_state != IsViewable) {
1099
sraRgnSubtract(disp, reg);
1104
line = sraRgnCreateRect(0, y, dpy_x, y+1);
1106
if (sraRgnAnd(line, disp)) {
1107
iter = sraRgnGetIterator(line);
1108
while (sraRgnIteratorNext(iter, &rect)) {
1109
poll_line_complement(rect.x1, rect.x2,
1112
sraRgnReleaseIterator(iter);
1115
sraRgnDestroy(line);
1120
sraRgnDestroy(disp);
1123
static void mark_rgn_rects(sraRegionPtr mod) {
1125
sraRectangleIterator *iter;
1128
if (sraRgnEmpty(mod)) {
1132
iter = sraRgnGetIterator(mod);
1133
while (sraRgnIteratorNext(iter, &rect)) {
1134
mark_rect_as_modified(rect.x1, rect.y1, rect.x2, rect.y2, 0);
1135
area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1));
1137
sraRgnReleaseIterator(iter);
1139
if (db24 > 1) fprintf(stderr, " mark_rgn_rects area: %d\n", area);
1142
static int get_8bpp_regions(int validate) {
1144
XWindowAttributes attr;
1145
int i, k, mapcount = 0;
1147
/* initialize color map list */
1149
for (i=0; i < CMAPMAX; i++) {
1150
cmaps[i] = (Colormap) 0;
1153
/* loop over the table of 8bpp windows: */
1154
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
1155
sraRegionPtr tmp_reg, tmp_reg2;
1156
Window c, w = windows_8bpp[i].win;
1159
if (windows_8bpp[i].clip_region) {
1160
sraRgnDestroy(windows_8bpp[i].clip_region);
1162
windows_8bpp[i].clip_region = NULL;
1168
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);
1171
* this could be slow: validating 8bpp windows each
1176
if (! valid_window(w, &attr, 1)) {
1178
windows_8bpp[i].win = None;
1179
windows_8bpp[i].top = None;
1180
windows_8bpp[i].map_state = IsUnmapped;
1181
windows_8bpp[i].cmap = (Colormap) 0;
1182
windows_8bpp[i].fetched = 0;
1183
windows_8bpp[i].last_fetched = -1.0;
1188
windows_8bpp[i].depth = attr.depth;
1189
windows_8bpp[i].map_state = attr.map_state;
1190
windows_8bpp[i].cmap = attr.colormap;
1191
windows_8bpp[i].map_installed = attr.map_installed;
1192
windows_8bpp[i].w = attr.width;
1193
windows_8bpp[i].h = attr.height;
1194
windows_8bpp[i].fetched = 1;
1195
windows_8bpp[i].last_fetched = dnow();
1197
if (attr.map_state != IsViewable) {
1202
xtranslate(w, window, 0, 0, &x, &y, &c, 1);
1204
windows_8bpp[i].x = x;
1205
windows_8bpp[i].y = y;
1208
/* this will be faster: no call to X server: */
1209
if (windows_8bpp[i].map_state != IsViewable) {
1212
attr.depth = windows_8bpp[i].depth;
1213
attr.map_state = windows_8bpp[i].map_state;
1214
attr.colormap = windows_8bpp[i].cmap;
1215
attr.map_installed = windows_8bpp[i].map_installed;
1216
attr.width = windows_8bpp[i].w;
1217
attr.height = windows_8bpp[i].h;
1219
x = windows_8bpp[i].x;
1220
y = windows_8bpp[i].y;
1225
/* tmp region for this 8bpp rectangle: */
1226
tmp_reg = sraRgnCreateRect(nfix(x, dpy_x), nfix(y, dpy_y),
1227
nfix(x + attr.width, dpy_x+1), nfix(y + attr.height, dpy_y+1));
1229
/* loop over all toplevels, top to bottom clipping: */
1230
for (k = stack_list_num - 1; k >= 0; k--) {
1231
Window swin = stack_list[k].win;
1234
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);
1236
if (swin == windows_8bpp[i].top) {
1237
/* found our top level: we skip the rest. */
1238
if (db24 > 1) fprintf(stderr, "found top: 0x%lx %d iv=%d\n", swin, k, stack_list[k].map_state);
1241
if (stack_list[k].map_state != IsViewable) {
1242
/* skip unmapped ones: */
1246
/* make a temp rect for this toplevel: */
1247
sx = stack_list[k].x;
1248
sy = stack_list[k].y;
1249
sw = stack_list[k].width;
1250
sh = stack_list[k].height;
1252
if (db24 > 1) fprintf(stderr, "subtract: 0x%lx %d -- %d %d %d %d\n", swin, k, sx, sy, sw, sh);
1254
tmp_reg2 = sraRgnCreateRect(nfix(sx, dpy_x),
1255
nfix(sy, dpy_y), nfix(sx + sw, dpy_x+1),
1256
nfix(sy + sh, dpy_y+1));
1258
/* subtract it from the 8bpp window region */
1259
sraRgnSubtract(tmp_reg, tmp_reg2);
1261
sraRgnDestroy(tmp_reg2);
1263
if (sraRgnEmpty(tmp_reg)) {
1268
if (sraRgnEmpty(tmp_reg)) {
1269
/* skip this 8bpp if completely clipped away: */
1270
sraRgnDestroy(tmp_reg);
1274
/* otherwise, store any new colormaps: */
1275
if (ncmaps < CMAPMAX && attr.colormap != (Colormap) 0) {
1277
for (m=0; m < ncmaps; m++) {
1278
if (cmaps[m] == attr.colormap) {
1283
if (! seen && attr.depth == 8) {
1284
/* store only new ones: */
1285
cmaps[ncmaps++] = attr.colormap;
1289
windows_8bpp[i].clip_region = tmp_reg;
1295
static XColor color[CMAPMAX][NCOLOR];
1296
static unsigned int rgb[CMAPMAX][NCOLOR];
1297
static int cmap_failed[CMAPMAX];
1300
static int get_cmap(int j, Colormap cmap) {
1307
XErrorHandler old_handler = NULL;
1312
/* not working properly for depth 24... */
1314
ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr));
1319
if (db24 > 1) fprintf(stderr, "get_cmap: %d 0x%x\n", j, (unsigned int) cmap);
1321
/* ncells should "always" be 256. */
1322
if (ncells > NCOLOR) {
1324
} else if (ncells == 8) {
1325
/* hmmm. see set_colormap() */
1329
/* initialize XColor array: */
1330
for (i=0; i < ncells; i++) {
1331
color[j][i].pixel = i;
1332
color[j][i].pad = 0;
1335
/* try to query the colormap, trap errors */
1338
old_handler = XSetErrorHandler(trap_xerror);
1339
XQueryColors(dpy, cmap, color[j], ncells);
1340
XSetErrorHandler(old_handler);
1343
if (trapped_xerror) {
1349
/* now map each index to depth 24 RGB */
1350
for (i=0; i < ncells; i++) {
1351
unsigned int red, green, blue;
1352
/* strip out highest 8 bits of values: */
1353
red = (color[j][i].red & 0xff00) >> 8;
1354
green = (color[j][i].green & 0xff00) >> 8;
1355
blue = (color[j][i].blue & 0xff00) >> 8;
1358
* the maxes should be at 255 already,
1359
* but just in case...
1361
red = (main_red_max * red )/255;
1362
green = (main_green_max * green)/255;
1363
blue = (main_blue_max * blue )/255;
1365
if (db24 > 2) fprintf(stderr, " cmap[%02d][%03d]: %03d %03d %03d 0x%08x \n", j, i, red, green, blue, ( red << main_red_shift | green << main_green_shift | blue << main_blue_shift));
1367
/* shift them over and or together for value */
1368
red = red << main_red_shift;
1369
green = green << main_green_shift;
1370
blue = blue << main_blue_shift;
1372
/* store it in the array to be used later */
1373
rgb[j][i] = red | green | blue;
1379
static void do_8bpp_region(int n, sraRegionPtr mark) {
1380
int k, cm = -1, failed = 0;
1381
sraRectangleIterator *iter;
1385
if (! windows_8bpp[n].clip_region) {
1388
if (windows_8bpp[n].win == None) {
1391
if (windows_8bpp[n].map_state != IsViewable) {
1394
if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps);
1396
/* see if XQueryColors failed: */
1397
for (k=0; k<ncmaps; k++) {
1398
if (windows_8bpp[n].cmap == cmaps[k]) {
1400
if (cmap_failed[k]) {
1407
if (windows_8bpp[n].depth == 8) { /* 24 won't have a cmap */
1408
if (failed || cm == -1) {
1413
clip = sraRgnCreateRgn(mark);
1414
sraRgnAnd(clip, windows_8bpp[n].clip_region);
1416
/* loop over the rectangles making up region */
1417
iter = sraRgnGetIterator(clip);
1418
while (sraRgnIteratorNext(iter, &rect)) {
1419
if (rect.x1 > rect.x2) {
1424
if (rect.y1 > rect.y2) {
1430
transform_rect(rect, windows_8bpp[n].win,
1431
windows_8bpp[n].depth, cm);
1433
sraRgnReleaseIterator(iter);
1434
sraRgnDestroy(clip);
1437
static XImage *cmap_xi(XImage *xi, Window win, int win_depth) {
1439
if (!xi || !win || !win_depth) {}
1442
XWindowAttributes attr;
1448
if (! dpy || ! valid_window(win, &attr, 1)) {
1449
return (XImage *) NULL;
1451
if (attr.depth != win_depth) {
1452
return (XImage *) NULL;
1453
} else if (win_depth == 8) {
1454
d = (char *) malloc(dpy_x * dpy_y * 1);
1455
} else if (win_depth == 24) {
1456
d = (char *) malloc(dpy_x * dpy_y * 4);
1458
return (XImage *) NULL;
1460
return XCreateImage(dpy, attr.visual, win_depth, ZPixmap, 0, d, dpy_x,
1466
static void transform_rect(sraRect rect, Window win, int win_depth, int cm) {
1469
if (!rect.x1 || !win || !win_depth || !cm) {}
1473
char *src, *dst, *poll;
1476
int ps, pixelsize = bpp/8;
1479
int do_getimage = xgetimage_8to24;
1480
int line, n_off, j, h, w;
1481
unsigned int hi, idx;
1482
XWindowAttributes attr;
1483
XErrorHandler old_handler = NULL;
1485
if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rect.y1, rect.x2, rect.y2, cm);
1492
/* now transform the pixels in this rectangle: */
1493
n_off = main_bytes_per_line * rect.y1 + pixelsize * rect.x1;
1495
h = rect.y2 - rect.y1;
1496
w = rect.x2 - rect.x1;
1499
/* need to fetch depth 24 data. */
1506
vw = valid_window(win, &attr, 1);
1510
if (do_getimage && vw) {
1514
static XImage *xi_8 = NULL;
1515
static XImage *xi_24 = NULL;
1516
XImage *xi = NULL, *xi_r;
1518
unsigned int wu, hu;
1521
wu = (unsigned int) w;
1522
hu = (unsigned int) h;
1527
if (win_depth == 8) {
1528
if (xi_8 == NULL || xi_8->width != dpy_x ||
1529
xi_8->height != dpy_y) {
1530
xi_8 = cmap_xi(xi_8, win, 8);
1533
} else if (win_depth == 24) {
1534
if (xi_24 == NULL || xi_24->width != dpy_x ||
1535
xi_24->height != dpy_y) {
1536
xi_24 = cmap_xi(xi_24, win, 24);
1542
old_handler = XSetErrorHandler(trap_xerror);
1545
XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c);
1550
if (db24 > 1) fprintf(stderr, "xywh: %d %d %d %d vs. %d %d\n", xo, yo, w, h, attr.width, attr.height);
1552
if (trapped_xerror || xo < 0 || yo < 0) {
1553
/* w > attr.width || h > attr.height */
1554
XSetErrorHandler(old_handler);
1557
if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n");
1563
xi = XGetImage(dpy, win, xo, yo, wu, hu, AllPlanes, ZPixmap);
1566
xi_r = XGetSubImage(dpy, win, xo, yo, wu, hu, AllPlanes,
1569
XSetErrorHandler(old_handler);
1572
if (! xi_r || trapped_xerror) {
1574
if (db24 > 1) fprintf(stderr, "xi-fail: 0x%p trap=%d %d %d %d %d\n", (void *)xi, trapped_xerror, xo, yo, w, h);
1577
if (db24 > 1) fprintf(stderr, "xi: 0x%p %d %d %d %d -- %d %d\n", (void *)xi, xo, yo, w, h, xi->width, xi->height);
1581
if (xi->depth != 8 && xi->depth != 24) {
1587
if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth);
1593
if (xi->depth == 8) {
1607
dst = cmap8to24_fb + fac * n_off;
1609
poll = poll8_fb + poll8_fb_w * rect.y1 + rect.x1;
1610
poll_Bpl = poll8_fb_w * 1;
1612
/* line by line ... */
1613
for (line = 0; line < h; line++) {
1614
/* pixel by pixel... */
1615
for (j = 0; j < w; j++) {
1617
uc = (unsigned char *) (src + ps1 * j);
1618
ui = (unsigned int *) (dst + ps2 * j);
1624
*(poll + ps1 * j) = *uc;
1626
src += xi->bytes_per_line;
1627
dst += main_bytes_per_line * fac;
1630
} else if (xi->depth == 24) {
1631
/* line by line ... */
1636
fac = 1; /* will not happen */
1640
dst = cmap8to24_fb + fac * n_off;
1642
poll = poll24_fb + (poll24_fb_w * rect.y1 + rect.x1)*4;
1643
poll_Bpl = poll24_fb_w * 4;
1645
for (line = 0; line < h; line++) {
1646
memcpy(dst, src, w * ps1);
1647
memcpy(poll, src, w * ps1);
1649
src += xi->bytes_per_line;
1650
dst += main_bytes_per_line * fac;
1661
} else if (! do_getimage) {
1665
/* cooked up depth 24 TrueColor */
1666
/* but currently disabled (high bits no useful?) */
1669
src = cmap8to24_fb + 4 * n_off;
1673
src = cmap8to24_fb + n_off;
1676
/* line by line ... */
1677
for (line = 0; line < h; line++) {
1678
/* pixel by pixel... */
1679
for (j = 0; j < w; j++) {
1681
/* grab 32 bit value */
1682
ui = (unsigned int *) (src + ps * j);
1684
/* extract top 8 bits (FIXME: masks?) */
1685
hi = (*ui) & 0xff000000;
1687
/* map to lookup index; rewrite pixel */
1689
*ui = hi | rgb[cm][idx];
1691
src += main_bytes_per_line * fac;
1697
void bpp8to24(int x1, int y1, int x2, int y2) {
1701
int idx, pixelsize = bpp/8;
1702
int line, k, i, j, h, w;
1706
static int last_map_count = 0, call_count = 0;
1707
static double last_get_8bpp_validate = 0.0;
1708
static double last_snapshot = 0.0;
1710
double dt, d0 = 0.0, t2;
1714
if (! cmap8to24 || ! cmap8to24_fb) {
1715
/* hmmm, why were we called? */
1719
if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, dnow() - last_get_8bpp_validate);
1723
/* clip to display just in case: */
1725
x1 = nfix(x1, dpy_x);
1726
y1 = nfix(y1, dpy_y);
1727
x2 = nfix(x2, dpy_x+1);
1728
y2 = nfix(y2, dpy_y+1);
1731
if (wireframe_in_progress) {
1733
* draw_box() manages cmap8to24_fb for us so we get out as
1734
* soon as we can. No need to cp main_fb -> cmap8to24_fb.
1739
/* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */
1745
/* need to cook up to depth 24 TrueColor */
1748
n_off = main_bytes_per_line * y1 + pixelsize * x1;
1750
src = main_fb + n_off;
1751
dst = cmap8to24_fb + 4 * n_off;
1755
int ps1 = 1, ps2 = 4;
1760
/* line by line ... */
1761
for (line = 0; line < h; line++) {
1762
/* pixel by pixel... */
1763
for (j = 0; j < w; j++) {
1765
uc = (unsigned char *) (src + ps1 * j);
1766
ui = (unsigned int *) (dst + ps2 * j);
1770
if (0 && line % 100 == 0 && j % 32 == 0) fprintf(stderr, "%d %d %u x1=%d y1=%d\n", line, j, root_rgb[idx], x1, y1);
1774
*ui = hi | rgb[0][idx];
1778
*ui = root_rgb[idx];
1779
if (db24 > 2) histo[idx]++;
1781
src += main_bytes_per_line;
1782
dst += main_bytes_per_line * 4;
1786
} else if (depth == 24) {
1788
n_off = main_bytes_per_line * y1 + pixelsize * x1;
1790
src = main_fb + n_off;
1791
dst = cmap8to24_fb + n_off;
1793
/* otherwise, the pixel data as is */
1794
for (line = 0; line < h; line++) {
1795
memcpy(dst, src, w * pixelsize);
1796
src += main_bytes_per_line;
1797
dst += main_bytes_per_line;
1801
if (last_map_count > MAX_8BPP_WINDOWS/4) {
1802
/* table is filling up... skip validating sometimes: */
1804
if (last_map_count > MAX_8BPP_WINDOWS/2) {
1806
} else if (last_map_count > 3*MAX_8BPP_WINDOWS/4) {
1809
if (call_count % skip != 0) {
1814
if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}}
1817
dt = now - last_get_8bpp_validate;
1820
; /* XXX does this still give painting errors? */
1823
double delay1, delay2, delay3;
1824
if (poll_8to24_delay >= POLL_8TO24_DELAY) {
1825
delay1 = 1.0 * poll_8to24_delay;
1826
delay2 = 2.0 * poll_8to24_delay;
1827
delay3 = 10. * poll_8to24_delay;
1829
delay1 = 1.0 * POLL_8TO24_DELAY; /* 0.05 */
1830
delay2 = 2.0 * POLL_8TO24_DELAY; /* 0.1 */
1831
delay3 = 10. * POLL_8TO24_DELAY; /* 0.5 */
1833
if (cache_win > 1.0) {
1840
if (last_map_count) {
1841
if (now > last_snapshot + delay2) {
1845
if (now > last_snapshot + delay3) {
1851
/* less problems if we update the stack frequently */
1852
snapshot_stack_list(0, 0.0);
1853
if (0) fprintf(stderr, "SNAP time: %.4f\n", dnow() - now);
1854
update_stack_list();
1855
last_snapshot = dnow();
1856
if (0) fprintf(stderr, "UPDA time: %.4f\n", last_snapshot - now);
1860
last_map_count = get_8bpp_regions(validate);
1862
last_get_8bpp_validate = dnow();
1864
if (0) fprintf(stderr, "get8bpp-%d: %.4f\n", validate, dnow() - t2);
1866
if (db24) d0 = dnow();
1868
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);
1871
* now go back and transform and 8bpp regions to TrueColor in
1874
if (last_map_count && (ncmaps || depth == 8)) {
1876
int win[MAX_8BPP_WINDOWS];
1877
int did[MAX_8BPP_WINDOWS];
1881
* first, grab all of the associated colormaps from the
1882
* X server. Hopefully just 1 or 2...
1884
for (j=0; j<ncmaps; j++) {
1885
if (! get_cmap(j, cmaps[j])) {
1890
if (db24 > 2) fprintf(stderr, "cmap %d %.4f\n", (int) cmaps[j], dnow() - d0);
1892
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
1893
sraRegionPtr reg = windows_8bpp[i].clip_region;
1895
rect = sraRgnCreateRect(x1, y1, x2, y2);
1896
if (sraRgnAnd(rect, reg)) {
1900
sraRgnDestroy(rect);
1906
rect = sraRgnCreateRect(x1, y1, x2, y2);
1907
/* try to apply lower windows first */
1908
for (k=0; k < stack_list_num; k++) {
1909
Window swin = stack_list[k].win;
1910
for (j=0; j<count; j++) {
1915
if (windows_8bpp[i].top == swin) {
1916
do_8bpp_region(i, rect);
1922
for (j=0; j<count; j++) {
1925
do_8bpp_region(i, rect);
1929
sraRgnDestroy(rect);
1932
if (0) fprintf(stderr, "done time: %.4f\n", dnow() - d0);
1934
if (db24 > 2) {for(i=0; i<256;i++) {fprintf(stderr, " cmap histo[%03d] %d\n", i, histo[i]);}}
1937
void mark_8bpp(int mode) {
1943
if (! cmap8to24 || !cmap8to24_fb) {
1947
if (mode == MARK_8BPP_TOP) {
1949
for (k = stack_list_num - 1; k >= 0; k--) {
1950
Window swin = stack_list[k].win;
1951
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
1952
if (windows_8bpp[i].win == None) {
1955
if (windows_8bpp[i].map_state != IsViewable) {
1958
if (swin == windows_8bpp[i].top) {
1969
/* for each mapped 8bpp window, mark it changed: */
1971
for (i=0; i < MAX_8BPP_WINDOWS; i++) {
1972
int x1, y1, x2, y2, w, h, f = 32;
1974
f = 0; /* skip fuzz, may bring in other windows... */
1976
if (windows_8bpp[i].win == None) {
1979
if (mode == MARK_8BPP_TOP) {
1980
if (windows_8bpp[i].top != top) {
1984
if (windows_8bpp[i].map_state != IsViewable) {
1985
XWindowAttributes attr;
1989
vw = valid_window(windows_8bpp[i].win, &attr, 1);
1992
if (attr.map_state != IsViewable) {
2000
x1 = windows_8bpp[i].x;
2001
y1 = windows_8bpp[i].y;
2002
w = windows_8bpp[i].w;
2003
h = windows_8bpp[i].h;
2008
if (mode == MARK_8BPP_POINTER) {
2009
int b = 32; /* apply some fuzz for wm border */
2010
if (cursor_x < x1 - b || cursor_y < y1 - b) {
2013
if (cursor_x > x2 + b || cursor_y > y2 + b) {
2018
/* apply fuzz f around each one; constrain to screen */
2019
x1 = nfix(x1 - f, dpy_x);
2020
y1 = nfix(y1 - f, dpy_y);
2021
x2 = nfix(x2 + f, dpy_x+1);
2022
y2 = nfix(y2 + f, dpy_y+1);
2024
if (db24 > 1) fprintf(stderr, "mark_8bpp: 0x%lx %d %d %d %d\n", windows_8bpp[i].win, x1, y1, x2, y2);
2026
mark_rect_as_modified(x1, y1, x2, y2, 0);
2030
/* push it to viewers if possible. */
2035
#endif /* SKIP_8TO24 */