~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/x11vnc/8to24.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -- 8to24.c -- */
 
2
#include "x11vnc.h"
 
3
#include "cleanup.h"
 
4
#include "scan.h"
 
5
#include "util.h"
 
6
#include "win_utils.h"
 
7
#include "xwrappers.h"
 
8
 
 
9
int multivis_count = 0;
 
10
int multivis_24count = 0;
 
11
 
 
12
void check_for_multivis(void);
 
13
void bpp8to24(int, int, int, int);
 
14
void mark_8bpp(int);
 
15
 
 
16
#if SKIP_8TO24
 
17
void check_for_multivis(void) {}
 
18
void bpp8to24(int x, int y, int z, int t) {}
 
19
void mark_8bpp(int x) {}
 
20
#else
 
21
/* lots... */
 
22
 
 
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);
 
40
 
 
41
/* struct for keeping info about the 8bpp windows: */
 
42
typedef struct window8 {
 
43
        Window win;
 
44
        Window top;
 
45
        int depth;
 
46
        int x, y;
 
47
        int w, h;
 
48
        int map_state;
 
49
        Colormap cmap;
 
50
        Bool map_installed;
 
51
        int fetched;
 
52
        double last_fetched;
 
53
        sraRegionPtr clip_region;
 
54
} window8bpp_t;
 
55
 
 
56
enum mark_8bpp_modes {
 
57
        MARK_8BPP_ALL = 0,
 
58
        MARK_8BPP_POINTER,
 
59
        MARK_8BPP_TOP
 
60
};
 
61
 
 
62
#define NCOLOR 256
 
63
 
 
64
static Colormap root_cmap = 0;
 
65
static unsigned int root_rgb[NCOLOR];
 
66
 
 
67
static void set_root_cmap(void) {
 
68
#if NO_X11
 
69
        RAWFB_RET_VOID
 
70
        return;
 
71
#else
 
72
        static time_t last_set = 0;
 
73
        time_t now = time(NULL);
 
74
        XWindowAttributes attr;
 
75
        static XColor color[NCOLOR];
 
76
        int redo = 0;
 
77
 
 
78
        RAWFB_RET_VOID
 
79
 
 
80
        if (now > last_set + 10) {
 
81
                redo = 1;
 
82
        }
 
83
        if (! root_cmap || redo) {
 
84
                X_LOCK;
 
85
                if (! valid_window(window, &attr, 1)) {
 
86
                        X_UNLOCK;
 
87
                        return;
 
88
                }
 
89
                if (attr.colormap) {
 
90
                        int i, ncells = NCOLOR;
 
91
                        for (i=0; i < ncells; i++) {
 
92
                                color[i].pixel = i;
 
93
                                color[i].pad = 0;
 
94
                        }
 
95
                        last_set = now;
 
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;
 
104
 
 
105
                                /*
 
106
                                 * the maxes should be at 255 already,
 
107
                                 * but just in case...
 
108
                                 */
 
109
                                red   = (main_red_max   * red  )/255;
 
110
                                green = (main_green_max * green)/255;
 
111
                                blue  = (main_blue_max  * blue )/255;
 
112
 
 
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;
 
117
 
 
118
                                /* store it in the array to be used later */
 
119
                                root_rgb[i] = red | green | blue;
 
120
                        }
 
121
                }
 
122
                X_UNLOCK;
 
123
        }
 
124
#endif  /* NO_X11 */
 
125
}
 
126
 
 
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];
 
130
 
 
131
static int db24 = 0;
 
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;
 
136
 
 
137
static int check_pointer_in_depth24(void) {
 
138
        int tries = 0, in_24 = 0;
 
139
        XWindowAttributes attr;
 
140
        Window c, w;
 
141
        double now = dnow();
 
142
 
 
143
        c = window;
 
144
 
 
145
        RAWFB_RET(0)
 
146
 
 
147
        if (now > last_keyboard_time + 1.0 && now > last_pointer_time + 1.0) {
 
148
                return 0;
 
149
        }
 
150
 
 
151
        X_LOCK;
 
152
        while (c && tries++ < 3) {
 
153
                c = query_pointer(c);
 
154
                if (valid_window(c, &attr, 1))  {
 
155
                        if (attr.depth == 24) {
 
156
                                in_24 = 1;
 
157
                                break;
 
158
                        }
 
159
                }
 
160
        }
 
161
        X_UNLOCK;
 
162
        if (in_24) {
 
163
                int x1, y1, x2, y2;
 
164
                X_LOCK;
 
165
                xtranslate(c, window, 0, 0, &x1, &y1, &w, 1);
 
166
                X_UNLOCK;
 
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);
 
174
 
 
175
if (db24 > 1) fprintf(stderr, "check_pointer_in_depth24 %d %d %d %d\n", x1, y1, x2, y2);
 
176
 
 
177
                return 1;
 
178
        }
 
179
        return 0;
 
180
}
 
181
 
 
182
static void parse_cmap8to24(void) {
 
183
        if (cmap8to24_str) {
 
184
                char *p, *str = strdup(cmap8to24_str);
 
185
                p = strtok(str, ",");
 
186
                /* defaults: */
 
187
                db24 = 0;
 
188
                xgetimage_8to24 = 1;
 
189
                poll_8to24_delay = POLL_8TO24_DELAY;
 
190
                level2_8to24 = 0;
 
191
                cache_win = 0.0;
 
192
                while (p) {
 
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")) {
 
200
                                xgetimage_8to24 = 0;
 
201
                        } else if (!strcmp(p, "level2")) {
 
202
                                level2_8to24 = 1;
 
203
                        }
 
204
                        p = strtok(NULL, ",");
 
205
                }
 
206
                free(str);
 
207
        } else {
 
208
                if (getenv("DEBUG_8TO24") != NULL) {
 
209
                        db24 = atoi(getenv("DEBUG_8TO24"));
 
210
                }
 
211
                if (getenv("NOXGETIMAGE_8TO24") != NULL) {
 
212
                        xgetimage_8to24 = 0;
 
213
                }
 
214
        }
 
215
}
 
216
 
 
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;
 
220
 
 
221
static void pfb(int fac, char **fb, int *w, int *h)  {
 
222
        if (! *fb || *w != dpy_x || *h != dpy_y) {
 
223
                if (*fb) {
 
224
                        free(*fb);
 
225
                }
 
226
                *fb = (char *) calloc(fac * dpy_x * dpy_y, 1);
 
227
                *w = dpy_x;
 
228
                *h = dpy_y;
 
229
        }
 
230
}
 
231
 
 
232
static void set_poll_fb(void) {
 
233
        /* create polling framebuffers or recreate if too small. */
 
234
 
 
235
        if (! xgetimage_8to24) {
 
236
                return;         /* this saves a bit of RAM */
 
237
        }
 
238
        pfb(4, &poll24_fb, &poll24_fb_w, &poll24_fb_h);
 
239
        pfb(1, &poll8_fb,  &poll8_fb_w,  &poll8_fb_h);
 
240
}
 
241
 
 
242
int MV_glob = 0;
 
243
int MV_count;
 
244
int MV_hit;
 
245
double MV_start;
 
246
 
 
247
void check_for_multivis(void) {
 
248
#if NO_X11
 
249
        RAWFB_RET_VOID
 
250
        return;
 
251
#else
 
252
        XWindowAttributes attr;
 
253
        int doall = 0;
 
254
        int k, i, cnt, diff;
 
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;
 
265
        double now = dnow();
 
266
        double delay;
 
267
 
 
268
        RAWFB_RET_VOID
 
269
 
 
270
        if (now > last_parse + 1.0) {
 
271
                last_parse = now;
 
272
                parse_cmap8to24();
 
273
        }
 
274
if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call);
 
275
        last_call = now;
 
276
 
 
277
        if (first) {
 
278
                int i;
 
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;
 
288
                }
 
289
                set_poll_fb();
 
290
 
 
291
                first = 0;
 
292
                doall = 1;      /* fetch everything first time */
 
293
        }
 
294
 
 
295
        if (wireframe_in_progress) {
 
296
                return;
 
297
        }
 
298
 
 
299
        set_root_cmap();
 
300
 
 
301
        /*
 
302
         * allocate an "old stack" list of all toplevels.  we compare
 
303
         * this to the current stack to guess stacking order changes.
 
304
         */
 
305
        if (!stack_old || stack_old_len < stack_list_len) {
 
306
                int n = stack_list_len;
 
307
                if (n < 256) {
 
308
                        n = 256;
 
309
                }
 
310
                if (stack_old) {
 
311
                        free(stack_old);
 
312
                }
 
313
                stack_old = (Window *) malloc(n*sizeof(Window));
 
314
                stack_old_len = n;
 
315
        }
 
316
 
 
317
        /* fill the old stack with visible windows: */
 
318
        cnt = 0;
 
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;
 
323
                }
 
324
        }
 
325
 
 
326
        /* snapshot + update the current stacking order: */
 
327
        /* TUNABLE */
 
328
        if (poll_8to24_delay >= POLL_8TO24_DELAY) {
 
329
                delay = 3.0 * poll_8to24_delay;
 
330
        } else {
 
331
                delay = 3.0 * POLL_8TO24_DELAY; /* 0.15 */
 
332
        }
 
333
        if (doall || now > last_update + delay) {
 
334
                snapshot_stack_list(0, 0.0);
 
335
                update_stack_list();
 
336
                last_update = now;
 
337
        }
 
338
 
 
339
        /* look for differences in the visible toplevels: */
 
340
        diff = 0;
 
341
        cnt = 0;
 
342
        for (k=0; k < stack_list_num; k++) {
 
343
                if (stack_list[k].valid && stack_list[k].map_state ==
 
344
                    IsViewable) {
 
345
                        if (stack_old[cnt] != stack_list[k].win) {
 
346
                                diff = 1;
 
347
                                break;
 
348
                        }
 
349
                        cnt++;
 
350
                }
 
351
        }
 
352
 
 
353
        multivis_count = 0;
 
354
        multivis_24count = 0;
 
355
 
 
356
        /*
 
357
         * every 10 seconds we try to clean out and also refresh the window
 
358
         * info in the the 8bpp window table:
 
359
         */
 
360
        if (now > last_clear + 10) {
 
361
                last_clear = now;
 
362
                X_LOCK;
 
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;
 
373
                        }
 
374
                }
 
375
                X_UNLOCK;
 
376
        }
 
377
 
 
378
        MV_count = 0;
 
379
        MV_hit = 0;
 
380
        MV_start = dnow();
 
381
 
 
382
        set_root_cmap();
 
383
 
 
384
        /* loop over all toplevels, both 8 and 24 depths: */
 
385
 
 
386
        X_LOCK; /* a giant lock around the whole activity */
 
387
 
 
388
        for (k=0; k < stack_list_num; k++) {
 
389
                Window r, parent;
 
390
                Window *list0;
 
391
                Status rc;
 
392
                unsigned int nc0;
 
393
                int i1;
 
394
                XErrorHandler old_handler;
 
395
                double delay;
 
396
 
 
397
                Window win = stack_list[k].win;
 
398
 
 
399
                /* TUNABLE */
 
400
                if (poll_8to24_delay >= POLL_8TO24_DELAY) {
 
401
                        delay = 1.5 * poll_8to24_delay;
 
402
                } else {
 
403
                        delay = 1.5 * POLL_8TO24_DELAY; /* 0.075 */
 
404
                }
 
405
 
 
406
                if (now < last_query + delay) {
 
407
                        break;
 
408
                }
 
409
 
 
410
                if (win == None) {
 
411
                        continue;
 
412
                }
 
413
 
 
414
                if (stack_list[k].map_state != IsViewable) {
 
415
                        int i;
 
416
                        /*
 
417
                         * if the toplevel became unmapped, mark it
 
418
                         * for the children as well...
 
419
                         */
 
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;
 
424
                                }
 
425
                        }
 
426
                }
 
427
 
 
428
                if (check_depth(win, win, doall)) {
 
429
                        /*
 
430
                         * returns 1 if no need to recurse down e.g. It
 
431
                         * is 8bpp and we assume all lower one are too.
 
432
                         */
 
433
                        continue;
 
434
                }
 
435
 
 
436
                /* we recurse up to two levels down from stack_list windows */
 
437
 
 
438
                old_handler = XSetErrorHandler(trap_xerror);
 
439
                trapped_xerror = 0;
 
440
                rc = XQueryTree_wr(dpy, win, &r, &parent, &list0, &nc0);
 
441
                XSetErrorHandler(old_handler);
 
442
 
 
443
                if (! rc || trapped_xerror) {
 
444
                        trapped_xerror = 0;
 
445
                        continue;
 
446
                }
 
447
                trapped_xerror = 0;
 
448
 
 
449
                /* loop over grandchildren of rootwin: */
 
450
                for (i1=0; i1 < (int) nc0; i1++) {
 
451
                        Window win1 = list0[i1];
 
452
                        Window *list1;
 
453
                        unsigned int nc1;
 
454
                        int i2;
 
455
 
 
456
                        if (check_depth(win1, win, doall)) {
 
457
                                continue;
 
458
                        }
 
459
 
 
460
                        if (level2_8to24) {
 
461
                                continue;
 
462
                        }
 
463
 
 
464
                        old_handler = XSetErrorHandler(trap_xerror);
 
465
                        trapped_xerror = 0;
 
466
                        rc = XQueryTree_wr(dpy, win1, &r, &parent, &list1, &nc1);
 
467
                        XSetErrorHandler(old_handler);
 
468
 
 
469
                        if (! rc || trapped_xerror) {
 
470
                                trapped_xerror = 0;
 
471
                                continue;
 
472
                        }
 
473
                        trapped_xerror = 0;
 
474
 
 
475
                        /* loop over great-grandchildren of rootwin: */
 
476
                        for (i2=0; i2< (int) nc1; i2++) {
 
477
                                Window win2 = list1[i2];
 
478
 
 
479
                                if (check_depth(win2, win, doall)) {
 
480
                                        continue;
 
481
                                }
 
482
                                /* more? Which wm does this? */
 
483
                        }
 
484
                        if (nc1) {
 
485
                                XFree_wr(list1);
 
486
                        }
 
487
                }
 
488
                if (nc0) {
 
489
                        XFree_wr(list0);
 
490
                }
 
491
        }
 
492
        X_UNLOCK;
 
493
 
 
494
        last_query = dnow();
 
495
 
 
496
MV_glob += MV_count;
 
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));
 
498
 
 
499
        if (screen_fixup_8 > 0.0 && now > last_fixup + screen_fixup_8) {
 
500
                last_fixup = now;
 
501
                mark_8bpp(MARK_8BPP_ALL);
 
502
                last_poll = now;
 
503
 
 
504
        } else if (poll_8to24_delay > 0.0) {
 
505
                int area = -1;
 
506
                int validate = 0;
 
507
 
 
508
                if (diff && multivis_count) {
 
509
                        validate = 1;
 
510
                }
 
511
                if (now > last_poll + poll_8to24_delay) {
 
512
                        sraRegionPtr mod;
 
513
 
 
514
                        last_poll = now;
 
515
                        mod = sraRgnCreate();
 
516
                        area = poll_8bpp(mod, validate);
 
517
                        if (depth == 24) {
 
518
                                poll_8bpp_complement(mod);
 
519
                        }
 
520
                        mark_rgn_rects(mod);
 
521
                        sraRgnDestroy(mod);
 
522
                }
 
523
                if (0 && area < dpy_x * dpy_y / 2 && diff && multivis_count) {
 
524
                        mark_8bpp(MARK_8BPP_POINTER);
 
525
                        last_poll = now;
 
526
                }
 
527
 
 
528
        } else if (diff && multivis_count) {
 
529
                mark_8bpp(MARK_8BPP_ALL);
 
530
                last_poll = now;
 
531
 
 
532
        } else if (depth == 8 && multivis_24count) {
 
533
                static double last_check = 0.0;
 
534
                if (now > last_check + 0.4) {
 
535
                        last_check = now;
 
536
                        if (check_pointer_in_depth24()) {
 
537
                                last_poll = now;
 
538
                        }
 
539
                }
 
540
        }
 
541
if (0) fprintf(stderr, "done: %.4f\n", dnow() - last_query);
 
542
#endif  /* NO_X11 */
 
543
}
 
544
 
 
545
#define VW_CACHE_MAX 1024
 
546
static XWindowAttributes vw_cache_attr[VW_CACHE_MAX];
 
547
static Window vw_cache_win[VW_CACHE_MAX];
 
548
 
 
549
static void set_attr(XWindowAttributes *attr, int j) {
 
550
        memcpy((void *) (vw_cache_attr+j), (void *) attr,
 
551
            sizeof(XWindowAttributes));
 
552
}
 
553
#if 0
 
554
static int get_attr(XWindowAttributes *attr, int j) {
 
555
        memcpy((void *) attr, (void *) (vw_cache_attr+j),
 
556
            sizeof(XWindowAttributes));
 
557
        return 1;
 
558
}
 
559
#endif
 
560
 
 
561
static XWindowAttributes wattr;
 
562
 
 
563
static XWindowAttributes *vw_lookup(Window win) {
 
564
        static double last_purge = 0.0;
 
565
        double now;
 
566
        int i, j, k;
 
567
 
 
568
        if (win == None) {
 
569
                return NULL;
 
570
        }
 
571
 
 
572
        now = dnow();
 
573
        if (now > last_purge + cache_win) {
 
574
                last_purge = now;
 
575
                for (i=0; i<VW_CACHE_MAX; i++) {
 
576
                        vw_cache_win[i] = None;
 
577
                }
 
578
        }
 
579
 
 
580
        j = -1;
 
581
        k = -1;
 
582
        for (i=0; i<VW_CACHE_MAX; i++) {
 
583
                if (vw_cache_win[i] == win) {
 
584
                        j = i;
 
585
                        break;
 
586
                } else if (vw_cache_win[i] == None) {
 
587
                        k = i;
 
588
                        break;
 
589
                }
 
590
        }
 
591
 
 
592
        if (j >= 0) {
 
593
MV_hit++;
 
594
                return vw_cache_attr+j;
 
595
                
 
596
        } else if (k >= 0) {
 
597
                XWindowAttributes attr2;
 
598
                int rc = valid_window(win, &attr2, 1);
 
599
                if (rc) {
 
600
                        vw_cache_win[k] = win;
 
601
                        set_attr(&attr2, k);
 
602
                        return vw_cache_attr+k;
 
603
                } else {
 
604
                        return NULL;
 
605
                }
 
606
        } else {
 
607
                /* Full */
 
608
                int rc = valid_window(win, &wattr, 1);
 
609
                if (rc) {
 
610
                        return &wattr;
 
611
                } else {
 
612
                        return NULL;
 
613
                }
 
614
        }
 
615
}
 
616
 
 
617
static int check_depth(Window win, Window top, int doall) {
 
618
        XWindowAttributes attr, *pattr;
 
619
 
 
620
        /* first see if it is (still) a valid window: */
 
621
MV_count++;
 
622
 
 
623
        if (cache_win > 0.0) {
 
624
                pattr = vw_lookup(win);
 
625
                if (pattr == NULL) {
 
626
                        return 1;       /* indicate done */
 
627
                }
 
628
        } else {
 
629
                if (! valid_window(win, &attr, 1)) {
 
630
                        return 1;       /* indicate done */
 
631
                }
 
632
                pattr = &attr;
 
633
        }
 
634
 
 
635
        if (! doall && pattr->map_state != IsViewable) {
 
636
                /*
 
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.
 
640
                 */
 
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 */
 
645
        } else {
 
646
                return 0;       /* indicate not done */
 
647
        }
 
648
}
 
649
 
 
650
static int check_depth_win(Window win, Window top, XWindowAttributes *attr) {
 
651
        int store_it = 0;
 
652
        /*
 
653
         * only store windows with depth not equal to the default visual's
 
654
         * depth note some windows can have depth == 0 ... (skip them).
 
655
         */
 
656
        if (attr->depth > 0) {
 
657
                if (depth == 24 && attr->depth != 24) {
 
658
                        store_it = 1;
 
659
                } else if (depth == 8 && root_cmap && attr->colormap !=
 
660
                    root_cmap) {
 
661
                        store_it = 1;
 
662
                }
 
663
        }
 
664
 
 
665
        if (store_it) {
 
666
                int i, j = -1, none = -1, nomap = -1;
 
667
                int new = 0;
 
668
                if (attr->map_state == IsViewable) {
 
669
                        /* count the visible ones: */
 
670
                        multivis_count++;
 
671
                        if (attr->depth == 24) {
 
672
                                multivis_24count++;
 
673
                        }
 
674
if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr->depth);
 
675
                }
 
676
 
 
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 */
 
681
                                none = i;
 
682
                        }
 
683
                        if (windows_8bpp[i].win == win) {
 
684
                                /* found myself */
 
685
                                j = i;
 
686
                                break;
 
687
                        }
 
688
                        if (nomap < 0 && windows_8bpp[i].win != None &&
 
689
                            windows_8bpp[i].map_state != IsViewable) {
 
690
                                /* found first unmapped */
 
691
                                nomap = i;
 
692
                        }
 
693
                }
 
694
                if (j < 0) {
 
695
                        if (attr->map_state != IsViewable) {
 
696
                                /* no slot and not visible: not worth keeping */
 
697
                                return 1;
 
698
                        } else if (none >= 0) {
 
699
                                /* put it in the first None slot */
 
700
                                j = none;
 
701
                                new = 1;
 
702
                        } else if (nomap >=0) {
 
703
                                /* put it in the first unmapped slot */
 
704
                                j = nomap;
 
705
                        }
 
706
                        /* otherwise we cannot store it... */
 
707
                }
 
708
 
 
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);
 
710
 
 
711
                /* store if if we found a slot j: */
 
712
                if (j >= 0) {
 
713
                        Window w;
 
714
                        int x, y;
 
715
                        int now_vis = 0;
 
716
 
 
717
                        if (attr->map_state == IsViewable &&
 
718
                            windows_8bpp[j].map_state != IsViewable) {
 
719
                                now_vis = 1;
 
720
                        } 
 
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();
 
732
 
 
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;
 
737
 
 
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);
 
744
                                X_LOCK;
 
745
                        }
 
746
                } else {
 
747
                        /*
 
748
                         * Error: could not find a slot.
 
749
                         * perhaps keep age and expire old ones??
 
750
                         */
 
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);
 
754
                        }
 
755
                        
 
756
                }
 
757
                return 1;
 
758
        }
 
759
        return 0;
 
760
}
 
761
 
 
762
static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w) {
 
763
        RAWFB_RET(NULL)
 
764
 
 
765
#if NO_X11
 
766
        if (!xi || !visual || !win_depth || !w) {}
 
767
        return NULL;
 
768
#else
 
769
        if (xi == NULL || *w < dpy_x) {
 
770
                char *d;
 
771
                if (xi) {
 
772
                        XDestroyImage(xi);
 
773
                }
 
774
                if (win_depth == 8) {
 
775
                        d = (char *) malloc(dpy_x * 1);
 
776
                } else {
 
777
                        d = (char *) malloc(dpy_x * 4);
 
778
                }
 
779
                *w = dpy_x;
 
780
                xi = XCreateImage(dpy, visual, win_depth, ZPixmap, 0, d,
 
781
                    dpy_x, 1, 8, 0);
 
782
        }
 
783
        return xi;
 
784
#endif  /* NO_X11 */
 
785
}
 
786
 
 
787
static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) {
 
788
#if NO_X11
 
789
        RAWFB_RET(1)
 
790
        if (!x1 || !x2 || !y1 || !n || !mod) {}
 
791
        return 1;
 
792
#else
 
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;
 
797
 
 
798
        static XImage *xi8 = NULL, *xi24 = NULL, *xi_r;
 
799
        static int xi8_w = 0, xi24_w = 0;
 
800
 
 
801
        XErrorHandler old_handler = NULL;
 
802
        XImage *xi;
 
803
        Window c, win = windows_8bpp[n].win;
 
804
 
 
805
        static XWindowAttributes attr;
 
806
        static Window last_win = None; 
 
807
        static double last_time = 0.0;
 
808
        double now;
 
809
 
 
810
        sraRegionPtr rect;
 
811
        int mx1, mx2, my1, my2;
 
812
        int ns = NSCAN/2;
 
813
 
 
814
        RAWFB_RET(1)
 
815
 
 
816
        if (win == None) {
 
817
                return 1;
 
818
        }
 
819
        if (windows_8bpp[n].map_state != IsViewable) {
 
820
                return 1;
 
821
        }
 
822
        if (! xgetimage_8to24) {
 
823
                return 1;
 
824
        }
 
825
 
 
826
        X_LOCK;
 
827
        now = dnow();
 
828
        if (last_win != None && win == last_win && now < last_time + 0.5) {
 
829
                ;       /* use previous attr */
 
830
        } else {
 
831
                if (! valid_window(win, &attr, 1)) {
 
832
                        X_UNLOCK;
 
833
                        last_win = None;
 
834
                        return 0;
 
835
                }
 
836
                last_time = now;
 
837
                last_win = win;
 
838
        }
 
839
 
 
840
        if (attr.depth != 8 && attr.depth != 24) {
 
841
                X_UNLOCK;
 
842
                return 1;
 
843
        } else if (attr.depth == 8) {
 
844
                xi = xi8 = p_xi(xi8, attr.visual, 8, &xi8_w);
 
845
 
 
846
                poll_fb = poll8_fb;
 
847
                fac = 1;
 
848
                n_off = poll8_fb_w * y1 + x1;
 
849
        } else {
 
850
                xi = xi24 = p_xi(xi24, attr.visual, 24, &xi24_w);
 
851
 
 
852
                poll_fb = poll24_fb;
 
853
                fac = 4;
 
854
                n_off = poll24_fb_w * y1 + x1;
 
855
        }
 
856
 
 
857
        old_handler = XSetErrorHandler(trap_xerror);
 
858
        trapped_xerror = 0;
 
859
 
 
860
        /* xtranslate() not used to save two XSetErrorHandler calls */
 
861
        XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c);
 
862
 
 
863
        xo = x1 - xo;
 
864
        yo = y1 - yo;
 
865
        w = x2 - x1;
 
866
 
 
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);
 
870
                trapped_xerror = 0;
 
871
                X_UNLOCK;
 
872
                return 0;
 
873
        }
 
874
 
 
875
        trapped_xerror = 0;
 
876
        xi_r = XGetSubImage(dpy, win, xo, yo, w, 1, AllPlanes, ZPixmap, xi,
 
877
            0, 0);
 
878
        XSetErrorHandler(old_handler);
 
879
        X_UNLOCK;
 
880
 
 
881
        if (! xi_r || trapped_xerror) {
 
882
                trapped_xerror = 0;
 
883
                return 0;
 
884
        }
 
885
        trapped_xerror = 0;
 
886
 
 
887
        src = xi->data;
 
888
        dst = poll_fb + fac * n_off;
 
889
 
 
890
        inrun = 0;
 
891
 
 
892
        xl = x1;
 
893
        while (xl < x2) {
 
894
                xh = xl + stride;
 
895
                if (xh > x2) {
 
896
                        xh = x2;
 
897
                }
 
898
                w2 = xh - xl;
 
899
                if (memcmp(dst, src, fac * w2)) {
 
900
                        if (inrun) {
 
901
                                rx2 = xh;
 
902
                        } else {
 
903
                                rx1 = xl;
 
904
                                rx2 = xh;
 
905
                                inrun = 1;
 
906
                        }
 
907
                } else {
 
908
                        if (inrun) {
 
909
                                mx1 = rx1;
 
910
                                mx2 = rx2;
 
911
                                my1 = nfix(y1 - ns, dpy_y);
 
912
                                my2 = nfix(y1 + ns, dpy_y+1);
 
913
 
 
914
                                rect = sraRgnCreateRect(mx1, my1, mx2, my2);
 
915
                                sraRgnOr(mod, rect);
 
916
                                sraRgnDestroy(rect);    
 
917
                                inrun = 0;
 
918
                        }
 
919
                }
 
920
 
 
921
                xl += stride;
 
922
                dst += fac * stride;
 
923
                src += fac * stride;
 
924
        }
 
925
 
 
926
        if (inrun) {
 
927
                mx1 = rx1;
 
928
                mx2 = rx2;
 
929
                my1 = nfix(y1 - ns, dpy_y);
 
930
                my2 = nfix(y1 + ns, dpy_y+1);
 
931
 
 
932
                rect = sraRgnCreateRect(mx1, my1, mx2, my2);
 
933
                sraRgnOr(mod, rect);
 
934
                sraRgnDestroy(rect);    
 
935
        }
 
936
        return 1;
 
937
#endif  /* NO_X11 */
 
938
}
 
939
 
 
940
static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod) {
 
941
        int n_off, w, xl, xh, stride = 32;
 
942
        char *dst, *src;
 
943
        int inrun = 0, rx1 = -1, rx2 = -1;
 
944
        sraRegionPtr rect;
 
945
        int mx1, mx2, my1, my2;
 
946
        int ns = NSCAN/2;
 
947
 
 
948
        if (depth != 24) {
 
949
                return;
 
950
        }
 
951
        if (! cmap8to24_fb) {
 
952
                return;
 
953
        }
 
954
        if (! xgetimage_8to24) {
 
955
                return;
 
956
        }
 
957
 
 
958
        n_off = main_bytes_per_line * y1 + 4 * x1;
 
959
 
 
960
        src = main_fb + n_off;
 
961
        dst = cmap8to24_fb + n_off;
 
962
 
 
963
        inrun = 0;
 
964
 
 
965
        xl = x1;
 
966
        while (xl < x2) {
 
967
                xh = xl + stride;
 
968
                if (xh > x2) {
 
969
                        xh = x2;
 
970
                }
 
971
                w = xh - xl;
 
972
                if (memcmp(dst, src, 4 * w)) {
 
973
                        if (inrun) {
 
974
                                rx2 = xh;
 
975
                        } else {
 
976
                                rx1 = xl;
 
977
                                rx2 = xh;
 
978
                                inrun = 1;
 
979
                        }
 
980
                } else {
 
981
                        if (inrun) {
 
982
                                mx1 = rx1;
 
983
                                mx2 = rx2;
 
984
                                my1 = nfix(y1 - ns, dpy_y);
 
985
                                my2 = nfix(y1 + ns, dpy_y+1);
 
986
 
 
987
                                rect = sraRgnCreateRect(mx1, my1, mx2, my2);
 
988
                                sraRgnOr(mod, rect);
 
989
                                sraRgnDestroy(rect);    
 
990
 
 
991
                                inrun = 0;
 
992
                        }
 
993
                }
 
994
 
 
995
                xl += stride;
 
996
                dst += 4 * stride;
 
997
                src += 4 * stride;
 
998
        }
 
999
 
 
1000
        if (inrun) {
 
1001
                mx1 = rx1;
 
1002
                mx2 = rx2;
 
1003
                my1 = nfix(y1 - ns, dpy_y);
 
1004
                my2 = nfix(y1 + ns, dpy_y+1);
 
1005
 
 
1006
                rect = sraRgnCreateRect(mx1, my1, mx2, my2);
 
1007
                sraRgnOr(mod, rect);
 
1008
                sraRgnDestroy(rect);    
 
1009
 
 
1010
                inrun = 0;
 
1011
        }
 
1012
}
 
1013
 
 
1014
#define CMAPMAX 64
 
1015
static Colormap cmaps[CMAPMAX];
 
1016
static int ncmaps;
 
1017
 
 
1018
static int poll_8bpp(sraRegionPtr mod, int validate) {
 
1019
        int i, y, ysh, map_count;
 
1020
        static int ycnt = 0;
 
1021
        sraRegionPtr line;
 
1022
        sraRect rect;
 
1023
        sraRectangleIterator *iter;
 
1024
        int br = 0, area = 0;
 
1025
        static double last_call = 0.0;
 
1026
        
 
1027
        map_count = get_8bpp_regions(validate);
 
1028
 
 
1029
if (db24 > 1) fprintf(stderr, "poll_8bpp mc: %d\n", map_count);
 
1030
 
 
1031
        if (! map_count) {
 
1032
                return 0;
 
1033
        }
 
1034
 
 
1035
        set_poll_fb();
 
1036
 
 
1037
        ysh = scanlines[(ycnt++) % NSCAN];
 
1038
if (db24 > 2) fprintf(stderr, "poll_8bpp: ysh: %2d  %.4f\n", ysh, dnow() - last_call);
 
1039
        last_call = dnow();
 
1040
 
 
1041
        for (i=0; i < MAX_8BPP_WINDOWS; i++) {
 
1042
                sraRegionPtr reg = windows_8bpp[i].clip_region;
 
1043
 
 
1044
                if (! reg || sraRgnEmpty(reg)) {
 
1045
                        continue;
 
1046
                }
 
1047
                y = ysh;
 
1048
                while (y < dpy_y) {
 
1049
                        line = sraRgnCreateRect(0, y, dpy_x, y+1);
 
1050
 
 
1051
                        if (sraRgnAnd(line, reg)) {
 
1052
                                iter = sraRgnGetIterator(line);
 
1053
                                while (sraRgnIteratorNext(iter, &rect)) {
 
1054
                                        if (! poll_line(rect.x1, rect.x2,
 
1055
                                            rect.y1, i, mod)) {
 
1056
                                                br = 1;
 
1057
                                                break;  /* exception */
 
1058
                                        }
 
1059
                                }
 
1060
                                sraRgnReleaseIterator(iter);
 
1061
                        }
 
1062
 
 
1063
                        sraRgnDestroy(line);
 
1064
                        y += NSCAN;
 
1065
                        if (br) break;
 
1066
                }
 
1067
                if (br) break;
 
1068
        }
 
1069
 
 
1070
        iter = sraRgnGetIterator(mod);
 
1071
        while (sraRgnIteratorNext(iter, &rect)) {
 
1072
                area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1));
 
1073
        }
 
1074
        sraRgnReleaseIterator(iter);
 
1075
 
 
1076
        return area;
 
1077
}
 
1078
 
 
1079
static void poll_8bpp_complement(sraRegionPtr mod) {
 
1080
        int i, y, ysh;
 
1081
        static int ycnt = 0;
 
1082
        sraRegionPtr disp, line;
 
1083
        sraRect rect;
 
1084
        sraRectangleIterator *iter;
 
1085
 
 
1086
        disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
 
1087
 
 
1088
        ysh = scanlines[(ycnt++) % NSCAN];
 
1089
 
 
1090
        for (i=0; i < MAX_8BPP_WINDOWS; i++) {
 
1091
                sraRegionPtr reg = windows_8bpp[i].clip_region;
 
1092
 
 
1093
                if (! reg) {
 
1094
                        continue;
 
1095
                }
 
1096
                if (windows_8bpp[i].map_state != IsViewable) {
 
1097
                        continue;       
 
1098
                }
 
1099
                sraRgnSubtract(disp, reg);
 
1100
        }
 
1101
 
 
1102
        y = ysh;
 
1103
        while (y < dpy_y) {
 
1104
                line = sraRgnCreateRect(0, y, dpy_x, y+1);
 
1105
 
 
1106
                if (sraRgnAnd(line, disp)) {
 
1107
                        iter = sraRgnGetIterator(line);
 
1108
                        while (sraRgnIteratorNext(iter, &rect)) {
 
1109
                                poll_line_complement(rect.x1, rect.x2,
 
1110
                                    rect.y1, mod);
 
1111
                        }
 
1112
                        sraRgnReleaseIterator(iter);
 
1113
                }
 
1114
 
 
1115
                sraRgnDestroy(line);
 
1116
 
 
1117
                y += NSCAN;
 
1118
        }
 
1119
 
 
1120
        sraRgnDestroy(disp);
 
1121
}
 
1122
 
 
1123
static void mark_rgn_rects(sraRegionPtr mod) {
 
1124
        sraRect rect;
 
1125
        sraRectangleIterator *iter;
 
1126
        int area = 0;
 
1127
 
 
1128
        if (sraRgnEmpty(mod)) {
 
1129
                return;
 
1130
        }
 
1131
        
 
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));
 
1136
        }
 
1137
        sraRgnReleaseIterator(iter);
 
1138
 
 
1139
if (db24 > 1) fprintf(stderr, " mark_rgn_rects area: %d\n", area);
 
1140
}
 
1141
 
 
1142
static int get_8bpp_regions(int validate) {
 
1143
 
 
1144
        XWindowAttributes attr;
 
1145
        int i, k, mapcount = 0;
 
1146
 
 
1147
        /* initialize color map list */
 
1148
        ncmaps = 0;
 
1149
        for (i=0; i < CMAPMAX; i++) {
 
1150
                cmaps[i] = (Colormap) 0;
 
1151
        }
 
1152
 
 
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;
 
1157
                int x, y;
 
1158
 
 
1159
                if (windows_8bpp[i].clip_region) {
 
1160
                        sraRgnDestroy(windows_8bpp[i].clip_region);     
 
1161
                }
 
1162
                windows_8bpp[i].clip_region = NULL;
 
1163
 
 
1164
                if (w == None) {
 
1165
                        continue;
 
1166
                }
 
1167
 
 
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);
 
1169
                if (validate) {
 
1170
                        /*
 
1171
                         * this could be slow: validating 8bpp windows each
 
1172
                         * time...
 
1173
                         */
 
1174
 
 
1175
                        X_LOCK;
 
1176
                        if (! valid_window(w, &attr, 1)) {
 
1177
                                X_UNLOCK;
 
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;
 
1184
                                continue;
 
1185
                        }
 
1186
                        X_UNLOCK;
 
1187
 
 
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();
 
1196
 
 
1197
                        if (attr.map_state != IsViewable) {
 
1198
                                continue;
 
1199
                        }
 
1200
 
 
1201
                        X_LOCK;
 
1202
                        xtranslate(w, window, 0, 0, &x, &y, &c, 1);
 
1203
                        X_UNLOCK;
 
1204
                        windows_8bpp[i].x = x;
 
1205
                        windows_8bpp[i].y = y;
 
1206
 
 
1207
                } else {
 
1208
                        /* this will be faster: no call to X server: */
 
1209
                        if (windows_8bpp[i].map_state != IsViewable) {
 
1210
                                continue;
 
1211
                        }
 
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;
 
1218
 
 
1219
                        x =  windows_8bpp[i].x; 
 
1220
                        y =  windows_8bpp[i].y; 
 
1221
                }
 
1222
 
 
1223
                mapcount++;
 
1224
 
 
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));
 
1228
 
 
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;
 
1232
                        int sx, sy, sw, sh;
 
1233
 
 
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);
 
1235
 
 
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);
 
1239
                                break;
 
1240
                        }
 
1241
                        if (stack_list[k].map_state != IsViewable) {
 
1242
                                /* skip unmapped ones: */
 
1243
                                continue;
 
1244
                        }
 
1245
 
 
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;
 
1251
 
 
1252
if (db24 > 1) fprintf(stderr, "subtract:  0x%lx %d -- %d %d %d %d\n", swin, k, sx, sy, sw, sh);
 
1253
 
 
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));
 
1257
 
 
1258
                        /* subtract it from the 8bpp window region */
 
1259
                        sraRgnSubtract(tmp_reg, tmp_reg2);
 
1260
 
 
1261
                        sraRgnDestroy(tmp_reg2);
 
1262
 
 
1263
                        if (sraRgnEmpty(tmp_reg)) {
 
1264
                                break;
 
1265
                        }
 
1266
                }
 
1267
 
 
1268
                if (sraRgnEmpty(tmp_reg)) {
 
1269
                        /* skip this 8bpp if completely clipped away: */
 
1270
                        sraRgnDestroy(tmp_reg);
 
1271
                        continue;
 
1272
                }
 
1273
 
 
1274
                /* otherwise, store any new colormaps: */
 
1275
                if (ncmaps < CMAPMAX && attr.colormap != (Colormap) 0) {
 
1276
                        int m, seen = 0;
 
1277
                        for (m=0; m < ncmaps; m++) {
 
1278
                                if (cmaps[m] == attr.colormap) {
 
1279
                                        seen = 1;
 
1280
                                        break;
 
1281
                                }
 
1282
                        }
 
1283
                        if (! seen && attr.depth == 8) {
 
1284
                                /* store only new ones: */
 
1285
                                cmaps[ncmaps++] = attr.colormap;
 
1286
                        }
 
1287
                }
 
1288
 
 
1289
                windows_8bpp[i].clip_region = tmp_reg;
 
1290
        }
 
1291
 
 
1292
        return mapcount;
 
1293
}
 
1294
 
 
1295
static XColor color[CMAPMAX][NCOLOR];
 
1296
static unsigned int rgb[CMAPMAX][NCOLOR];
 
1297
static int cmap_failed[CMAPMAX];
 
1298
int histo[256];
 
1299
 
 
1300
static int get_cmap(int j, Colormap cmap) {
 
1301
#if NO_X11
 
1302
        RAWFB_RET(0)
 
1303
        if (!j || !cmap) {}
 
1304
        return 0;
 
1305
#else
 
1306
        int i, ncells;
 
1307
        XErrorHandler old_handler = NULL;
 
1308
 
 
1309
        RAWFB_RET(0)
 
1310
 
 
1311
        if (0) {
 
1312
                /* not working properly for depth 24... */
 
1313
                X_LOCK;
 
1314
                ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr));
 
1315
                X_UNLOCK;
 
1316
        } else {
 
1317
                ncells = NCOLOR;
 
1318
        }
 
1319
if (db24 > 1) fprintf(stderr, "get_cmap: %d 0x%x\n", j, (unsigned int) cmap);
 
1320
 
 
1321
        /* ncells should "always" be 256. */
 
1322
        if (ncells > NCOLOR) {
 
1323
                ncells = NCOLOR;
 
1324
        } else if (ncells == 8) {
 
1325
                /* hmmm. see set_colormap() */
 
1326
                ncells = NCOLOR;
 
1327
        }
 
1328
 
 
1329
        /* initialize XColor array: */
 
1330
        for (i=0; i < ncells; i++) {
 
1331
                color[j][i].pixel = i;
 
1332
                color[j][i].pad = 0;
 
1333
        }
 
1334
 
 
1335
        /* try to query the colormap, trap errors */
 
1336
        X_LOCK;
 
1337
        trapped_xerror = 0;
 
1338
        old_handler = XSetErrorHandler(trap_xerror);
 
1339
        XQueryColors(dpy, cmap, color[j], ncells);
 
1340
        XSetErrorHandler(old_handler);
 
1341
        X_UNLOCK;
 
1342
 
 
1343
        if (trapped_xerror) {
 
1344
                trapped_xerror = 0;
 
1345
                return 0;
 
1346
        }
 
1347
        trapped_xerror = 0;
 
1348
 
 
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;
 
1356
 
 
1357
                /*
 
1358
                 * the maxes should be at 255 already,
 
1359
                 * but just in case...
 
1360
                 */
 
1361
                red   = (main_red_max   * red  )/255;
 
1362
                green = (main_green_max * green)/255;
 
1363
                blue  = (main_blue_max  * blue )/255;
 
1364
 
 
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));
 
1366
 
 
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;
 
1371
 
 
1372
                /* store it in the array to be used later */
 
1373
                rgb[j][i] = red | green | blue;
 
1374
        }
 
1375
        return 1;
 
1376
#endif  /* NO_X11 */
 
1377
}
 
1378
 
 
1379
static void do_8bpp_region(int n, sraRegionPtr mark) {
 
1380
        int k, cm = -1, failed = 0;
 
1381
        sraRectangleIterator *iter;
 
1382
        sraRegionPtr clip;
 
1383
        sraRect rect;
 
1384
 
 
1385
        if (! windows_8bpp[n].clip_region) {
 
1386
                return;
 
1387
        }
 
1388
        if (windows_8bpp[n].win == None) {
 
1389
                return;
 
1390
        }
 
1391
        if (windows_8bpp[n].map_state != IsViewable) {
 
1392
                return;
 
1393
        }
 
1394
if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps);
 
1395
 
 
1396
        /* see if XQueryColors failed: */
 
1397
        for (k=0; k<ncmaps; k++) {
 
1398
                if (windows_8bpp[n].cmap == cmaps[k]) {
 
1399
                        cm = k;
 
1400
                        if (cmap_failed[k]) {
 
1401
                                failed = 1;
 
1402
                        }
 
1403
                        break;
 
1404
                }
 
1405
        }
 
1406
 
 
1407
        if (windows_8bpp[n].depth == 8) {       /* 24 won't have a cmap */
 
1408
                if (failed || cm == -1) {
 
1409
                        return;
 
1410
                }
 
1411
        }
 
1412
 
 
1413
        clip = sraRgnCreateRgn(mark);
 
1414
        sraRgnAnd(clip, windows_8bpp[n].clip_region);
 
1415
 
 
1416
        /* loop over the rectangles making up region */
 
1417
        iter = sraRgnGetIterator(clip);
 
1418
        while (sraRgnIteratorNext(iter, &rect)) {
 
1419
                if (rect.x1 > rect.x2) {
 
1420
                        int tmp = rect.x2;
 
1421
                        rect.x2 = rect.x1;
 
1422
                        rect.x1 = tmp;
 
1423
                }
 
1424
                if (rect.y1 > rect.y2) {
 
1425
                        int tmp = rect.y2;
 
1426
                        rect.y2 = rect.y1;
 
1427
                        rect.y1 = tmp;
 
1428
                }
 
1429
 
 
1430
                transform_rect(rect, windows_8bpp[n].win,
 
1431
                    windows_8bpp[n].depth, cm);
 
1432
        }
 
1433
        sraRgnReleaseIterator(iter);
 
1434
        sraRgnDestroy(clip);
 
1435
}
 
1436
 
 
1437
static XImage *cmap_xi(XImage *xi, Window win, int win_depth) {
 
1438
#if NO_X11
 
1439
        if (!xi || !win || !win_depth) {}
 
1440
        return NULL;
 
1441
#else
 
1442
        XWindowAttributes attr;
 
1443
        char *d;
 
1444
 
 
1445
        if (xi) {
 
1446
                XDestroyImage(xi);
 
1447
        }
 
1448
        if (! dpy || ! valid_window(win, &attr, 1)) {
 
1449
                return (XImage *) NULL;
 
1450
        }
 
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);
 
1457
        } else {
 
1458
                return (XImage *) NULL;
 
1459
        }
 
1460
        return XCreateImage(dpy, attr.visual, win_depth, ZPixmap, 0, d, dpy_x,
 
1461
            dpy_y, 8, 0);
 
1462
#endif  /* NO_X11 */
 
1463
}
 
1464
 
 
1465
 
 
1466
static void transform_rect(sraRect rect, Window win, int win_depth, int cm) {
 
1467
#if NO_X11
 
1468
        RAWFB_RET_VOID
 
1469
        if (!rect.x1 || !win || !win_depth || !cm) {}
 
1470
        return;
 
1471
#else
 
1472
 
 
1473
        char *src, *dst, *poll;
 
1474
        unsigned int *ui;
 
1475
        unsigned char *uc;
 
1476
        int ps, pixelsize = bpp/8;
 
1477
        int poll_Bpl;
 
1478
 
 
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;
 
1484
 
 
1485
if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rect.y1, rect.x2, rect.y2, cm);
 
1486
 
 
1487
        RAWFB_RET_VOID
 
1488
 
 
1489
        attr.width = 0;
 
1490
        attr.height = 0;
 
1491
 
 
1492
        /* now transform the pixels in this rectangle: */
 
1493
        n_off = main_bytes_per_line * rect.y1 + pixelsize * rect.x1;
 
1494
 
 
1495
        h = rect.y2 - rect.y1;
 
1496
        w = rect.x2 - rect.x1;
 
1497
 
 
1498
        if (depth == 8) {
 
1499
                /* need to fetch depth 24 data. */
 
1500
                do_getimage = 1;
 
1501
        }
 
1502
 
 
1503
#if 0
 
1504
        if (do_getimage) {
 
1505
                X_LOCK;
 
1506
                vw = valid_window(win, &attr, 1);
 
1507
                X_UNLOCK;
 
1508
        }
 
1509
 
 
1510
        if (do_getimage && vw) {
 
1511
#else
 
1512
        if (do_getimage) {
 
1513
#endif
 
1514
                static XImage *xi_8  = NULL;
 
1515
                static XImage *xi_24 = NULL;
 
1516
                XImage *xi = NULL, *xi_r;
 
1517
                Window c;
 
1518
                unsigned int wu, hu;
 
1519
                int xo, yo;
 
1520
 
 
1521
                wu = (unsigned int) w;
 
1522
                hu = (unsigned int) h;
 
1523
 
 
1524
                X_LOCK;
 
1525
#define GETSUBIMAGE
 
1526
#ifdef GETSUBIMAGE
 
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);
 
1531
                        }
 
1532
                        xi = xi_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);
 
1537
                        }
 
1538
                        xi = xi_24;
 
1539
                }
 
1540
#endif
 
1541
 
 
1542
                old_handler = XSetErrorHandler(trap_xerror);
 
1543
                trapped_xerror = 0;
 
1544
 
 
1545
                XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c);
 
1546
 
 
1547
                xo = rect.x1 - xo;
 
1548
                yo = rect.y1 - yo;
 
1549
 
 
1550
if (db24 > 1) fprintf(stderr, "xywh: %d %d %d %d vs. %d %d\n", xo, yo, w, h, attr.width, attr.height);
 
1551
 
 
1552
                if (trapped_xerror || xo < 0 || yo < 0) {
 
1553
                        /* w > attr.width || h > attr.height */
 
1554
                        XSetErrorHandler(old_handler);
 
1555
                        X_UNLOCK;
 
1556
                        trapped_xerror = 0;
 
1557
if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n");
 
1558
                        return;
 
1559
                }
 
1560
                trapped_xerror = 0;
 
1561
 
 
1562
#ifndef GETSUBIMAGE
 
1563
                xi = XGetImage(dpy, win, xo, yo, wu, hu, AllPlanes, ZPixmap);
 
1564
                xi_r = xi;
 
1565
#else
 
1566
                xi_r = XGetSubImage(dpy, win, xo, yo, wu, hu, AllPlanes,
 
1567
                    ZPixmap, xi, 0, 0);
 
1568
#endif
 
1569
                XSetErrorHandler(old_handler);
 
1570
                X_UNLOCK;
 
1571
 
 
1572
                if (! xi_r || trapped_xerror) {
 
1573
                        trapped_xerror = 0;
 
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);
 
1575
                        return;
 
1576
                } else {
 
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);
 
1578
                }
 
1579
                trapped_xerror = 0;
 
1580
 
 
1581
                if (xi->depth != 8 && xi->depth != 24) {
 
1582
#ifndef GETSUBIMAGE
 
1583
                        X_LOCK;
 
1584
                        XDestroyImage(xi);
 
1585
                        X_UNLOCK;
 
1586
#endif
 
1587
if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth);
 
1588
                        return;
 
1589
                }
 
1590
 
 
1591
                set_poll_fb();
 
1592
 
 
1593
                if (xi->depth == 8) {
 
1594
                        int ps1, ps2, fac;
 
1595
 
 
1596
                        if (depth == 8) {
 
1597
                                ps1 = 1;
 
1598
                                ps2 = 4;
 
1599
                                fac = 4;
 
1600
                        } else {
 
1601
                                ps1 = 1;
 
1602
                                ps2 = pixelsize;
 
1603
                                fac = 1;
 
1604
                        }
 
1605
 
 
1606
                        src = xi->data;
 
1607
                        dst = cmap8to24_fb + fac * n_off;
 
1608
 
 
1609
                        poll = poll8_fb + poll8_fb_w * rect.y1 + rect.x1;
 
1610
                        poll_Bpl = poll8_fb_w * 1;
 
1611
 
 
1612
                        /* line by line ... */
 
1613
                        for (line = 0; line < h; line++) {
 
1614
                                /* pixel by pixel... */
 
1615
                                for (j = 0; j < w; j++) {
 
1616
 
 
1617
                                        uc = (unsigned char *) (src + ps1 * j);
 
1618
                                        ui = (unsigned int *)  (dst + ps2 * j);
 
1619
 
 
1620
                                        idx = (int) (*uc);
 
1621
 
 
1622
                                        *ui = rgb[cm][idx];
 
1623
 
 
1624
                                        *(poll + ps1 * j) = *uc;
 
1625
                                }
 
1626
                                src += xi->bytes_per_line;
 
1627
                                dst += main_bytes_per_line * fac;
 
1628
                                poll += poll_Bpl;
 
1629
                        }
 
1630
                } else if (xi->depth == 24) {
 
1631
                        /* line by line ... */
 
1632
                        int ps1 = 4, fac;
 
1633
                        if (depth == 8) {
 
1634
                                fac = 4;
 
1635
                        } else {
 
1636
                                fac = 1;        /* will not happen */
 
1637
                        }
 
1638
 
 
1639
                        src = xi->data;
 
1640
                        dst = cmap8to24_fb + fac * n_off;
 
1641
 
 
1642
                        poll = poll24_fb + (poll24_fb_w * rect.y1 + rect.x1)*4;
 
1643
                        poll_Bpl = poll24_fb_w * 4;
 
1644
 
 
1645
                        for (line = 0; line < h; line++) {
 
1646
                                memcpy(dst,  src, w * ps1);
 
1647
                                memcpy(poll, src, w * ps1);
 
1648
 
 
1649
                                src += xi->bytes_per_line;
 
1650
                                dst += main_bytes_per_line * fac;
 
1651
                                poll += poll_Bpl;
 
1652
                        }
 
1653
                }
 
1654
 
 
1655
#ifndef GETSUBIMAGE
 
1656
                X_LOCK;
 
1657
                XDestroyImage(xi);
 
1658
                X_UNLOCK;
 
1659
#endif
 
1660
 
 
1661
        } else if (! do_getimage) {
 
1662
                int fac;
 
1663
 
 
1664
                if (depth == 8) {
 
1665
                        /* cooked up depth 24 TrueColor  */
 
1666
                        /* but currently disabled (high bits no useful?) */
 
1667
                        ps = 4;
 
1668
                        fac = 4;
 
1669
                        src = cmap8to24_fb + 4 * n_off;
 
1670
                } else {
 
1671
                        ps = pixelsize;
 
1672
                        fac = 1;
 
1673
                        src = cmap8to24_fb + n_off;
 
1674
                }
 
1675
                
 
1676
                /* line by line ... */
 
1677
                for (line = 0; line < h; line++) {
 
1678
                        /* pixel by pixel... */
 
1679
                        for (j = 0; j < w; j++) {
 
1680
 
 
1681
                                /* grab 32 bit value */
 
1682
                                ui = (unsigned int *) (src + ps * j);
 
1683
 
 
1684
                                /* extract top 8 bits (FIXME: masks?) */
 
1685
                                hi = (*ui) & 0xff000000; 
 
1686
 
 
1687
                                /* map to lookup index; rewrite pixel */
 
1688
                                idx = hi >> 24;
 
1689
                                *ui = hi | rgb[cm][idx];
 
1690
                        }
 
1691
                        src += main_bytes_per_line * fac;
 
1692
                }
 
1693
        }
 
1694
#endif  /* NO_X11 */
 
1695
}
 
1696
 
 
1697
void bpp8to24(int x1, int y1, int x2, int y2) {
 
1698
        char *src, *dst;
 
1699
        unsigned char *uc;
 
1700
        unsigned int *ui;
 
1701
        int idx, pixelsize = bpp/8;
 
1702
        int line, k, i, j, h, w;
 
1703
        int n_off;
 
1704
        sraRegionPtr rect;
 
1705
        int validate = 1;
 
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;
 
1709
        double now;
 
1710
        double dt, d0 = 0.0, t2;
 
1711
 
 
1712
        RAWFB_RET_VOID
 
1713
 
 
1714
        if (! cmap8to24 || ! cmap8to24_fb) {
 
1715
                /* hmmm, why were we called? */
 
1716
                return;
 
1717
        }
 
1718
 
 
1719
if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, dnow() - last_get_8bpp_validate);
 
1720
 
 
1721
        call_count++;
 
1722
 
 
1723
        /* clip to display just in case: */
 
1724
        if (!ncache) {
 
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);
 
1729
        }
 
1730
 
 
1731
        if (wireframe_in_progress) {
 
1732
                /*
 
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.
 
1735
                 */
 
1736
                return;
 
1737
        }
 
1738
 
 
1739
        /* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */
 
1740
 
 
1741
        h = y2 - y1;
 
1742
        w = x2 - x1;
 
1743
 
 
1744
        if (depth == 8) {
 
1745
                /* need to cook up to depth 24 TrueColor  */
 
1746
                /* pixelsize = 1 */
 
1747
 
 
1748
                n_off = main_bytes_per_line * y1 + pixelsize * x1;
 
1749
 
 
1750
                src = main_fb + n_off;
 
1751
                dst = cmap8to24_fb + 4 * n_off;
 
1752
 
 
1753
                set_root_cmap();
 
1754
                if (root_cmap) {
 
1755
                        int ps1 = 1, ps2 = 4;
 
1756
#if 0
 
1757
                        unsigned int hi;
 
1758
#endif
 
1759
 
 
1760
                        /* line by line ... */
 
1761
                        for (line = 0; line < h; line++) {
 
1762
                                /* pixel by pixel... */
 
1763
                                for (j = 0; j < w; j++) {
 
1764
 
 
1765
                                        uc = (unsigned char *) (src + ps1 * j);
 
1766
                                        ui = (unsigned int *)  (dst + ps2 * j);
 
1767
 
 
1768
                                        idx = (int) (*uc);
 
1769
 
 
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);
 
1771
#if 0
 
1772
                                        if (do_hibits) {
 
1773
                                                hi = idx << 24;
 
1774
                                                *ui = hi | rgb[0][idx];
 
1775
                                        } else {
 
1776
                                        }
 
1777
#endif
 
1778
                                        *ui = root_rgb[idx];
 
1779
if (db24 > 2) histo[idx]++;
 
1780
                                }
 
1781
                                src += main_bytes_per_line;
 
1782
                                dst += main_bytes_per_line * 4;
 
1783
                        }
 
1784
                }
 
1785
                
 
1786
        } else if (depth == 24) {
 
1787
                /* pixelsize = 4 */
 
1788
                n_off = main_bytes_per_line * y1 + pixelsize * x1;
 
1789
 
 
1790
                src = main_fb      + n_off;
 
1791
                dst = cmap8to24_fb + n_off;
 
1792
 
 
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;
 
1798
                }
 
1799
        }
 
1800
 
 
1801
        if (last_map_count > MAX_8BPP_WINDOWS/4) {
 
1802
                /* table is filling up... skip validating sometimes: */
 
1803
                int skip = 3;
 
1804
                if (last_map_count > MAX_8BPP_WINDOWS/2) {
 
1805
                        skip = 6;
 
1806
                } else if (last_map_count > 3*MAX_8BPP_WINDOWS/4) {
 
1807
                        skip = 12;
 
1808
                }
 
1809
                if (call_count % skip != 0) {
 
1810
                        validate = 0;
 
1811
                }
 
1812
        }
 
1813
 
 
1814
if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}}
 
1815
 
 
1816
        now = dnow();
 
1817
        dt = now - last_get_8bpp_validate;
 
1818
        /* TUNABLES  */
 
1819
        if (dt < 0.003) {
 
1820
                ;       /* XXX does this still give painting errors? */
 
1821
        } else {
 
1822
                int snapit = 0;
 
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;
 
1828
                } else {
 
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  */
 
1832
                }
 
1833
                if (cache_win > 1.0) {
 
1834
                        delay2 *= 2;
 
1835
                        delay3 *= 2;
 
1836
                }
 
1837
                if (dt < delay1) {
 
1838
                        validate = 0;
 
1839
                }
 
1840
                if (last_map_count) {
 
1841
                        if (now > last_snapshot + delay2) {
 
1842
                                snapit = 1;
 
1843
                        }
 
1844
                } else {
 
1845
                        if (now > last_snapshot + delay3) {
 
1846
                                snapit = 1;
 
1847
                        }
 
1848
                }
 
1849
 
 
1850
                if (snapit) {
 
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);
 
1857
                }
 
1858
 
 
1859
if (0) t2 = dnow();
 
1860
                last_map_count = get_8bpp_regions(validate);
 
1861
                if (validate) {
 
1862
                        last_get_8bpp_validate = dnow();
 
1863
                }
 
1864
if (0) fprintf(stderr, "get8bpp-%d: %.4f\n", validate, dnow() - t2);
 
1865
        }
 
1866
if (db24) d0 = dnow();
 
1867
 
 
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);
 
1869
 
 
1870
        /*
 
1871
         * now go back and transform and 8bpp regions to TrueColor in
 
1872
         * cmap8to24_fb.
 
1873
         */
 
1874
        if (last_map_count && (ncmaps || depth == 8)) {
 
1875
                int i, j;
 
1876
                int win[MAX_8BPP_WINDOWS];
 
1877
                int did[MAX_8BPP_WINDOWS];
 
1878
                int count = 0;
 
1879
 
 
1880
                /*
 
1881
                 * first, grab all of the associated colormaps from the
 
1882
                 * X server.  Hopefully just 1 or 2...
 
1883
                 */
 
1884
                for (j=0; j<ncmaps; j++) {
 
1885
                        if (! get_cmap(j, cmaps[j])) {
 
1886
                                cmap_failed[j] = 1;
 
1887
                        } else {
 
1888
                                cmap_failed[j] = 0;
 
1889
                        }
 
1890
if (db24 > 2) fprintf(stderr, "cmap %d  %.4f\n", (int) cmaps[j], dnow() - d0);
 
1891
                }
 
1892
                for (i=0; i < MAX_8BPP_WINDOWS; i++) {
 
1893
                        sraRegionPtr reg = windows_8bpp[i].clip_region;
 
1894
                        if (reg) {
 
1895
                                rect = sraRgnCreateRect(x1, y1, x2, y2);
 
1896
                                if (sraRgnAnd(rect, reg)) {
 
1897
                                        win[count] = i;
 
1898
                                        did[count++] = 0;
 
1899
                                }
 
1900
                                sraRgnDestroy(rect);
 
1901
                        }
 
1902
                }
 
1903
 
 
1904
                if (count) {
 
1905
 
 
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++) {
 
1911
                                        i = win[j];
 
1912
                                        if (did[j]) {
 
1913
                                                continue;
 
1914
                                        }
 
1915
                                        if (windows_8bpp[i].top == swin) {
 
1916
                                                do_8bpp_region(i, rect);
 
1917
                                                did[j] = 1;
 
1918
                                                break;
 
1919
                                        }
 
1920
                                }
 
1921
                        }
 
1922
                        for (j=0; j<count; j++) {
 
1923
                                if (! did[j]) {
 
1924
                                        i = win[j];
 
1925
                                        do_8bpp_region(i, rect);
 
1926
                                        did[j] = 1;
 
1927
                                }
 
1928
                        }
 
1929
                        sraRgnDestroy(rect);
 
1930
                }
 
1931
        }
 
1932
if (0) fprintf(stderr, "done time: %.4f\n", dnow() - d0);
 
1933
 
 
1934
if (db24 > 2) {for(i=0; i<256;i++) {fprintf(stderr, " cmap histo[%03d] %d\n", i, histo[i]);}}
 
1935
}
 
1936
 
 
1937
void mark_8bpp(int mode) {
 
1938
        int i, cnt = 0;
 
1939
        Window top = None;
 
1940
 
 
1941
        RAWFB_RET_VOID
 
1942
 
 
1943
        if (! cmap8to24 || !cmap8to24_fb) {
 
1944
                return;
 
1945
        }
 
1946
        
 
1947
        if (mode == MARK_8BPP_TOP) {
 
1948
                int k;
 
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) {
 
1953
                                        continue;
 
1954
                                }
 
1955
                                if (windows_8bpp[i].map_state != IsViewable) {
 
1956
                                        continue;
 
1957
                                }
 
1958
                                if (swin == windows_8bpp[i].top) {
 
1959
                                        top = swin;
 
1960
                                        break;
 
1961
                                }
 
1962
                        }
 
1963
                        if (top != None) {
 
1964
                                break;
 
1965
                        }
 
1966
                }
 
1967
        }
 
1968
 
 
1969
        /* for each mapped 8bpp window, mark it changed: */
 
1970
 
 
1971
        for (i=0; i < MAX_8BPP_WINDOWS; i++) {
 
1972
                int x1, y1, x2, y2, w, h, f = 32;
 
1973
 
 
1974
                f = 0;  /* skip fuzz, may bring in other windows... */
 
1975
 
 
1976
                if (windows_8bpp[i].win == None) {
 
1977
                        continue;
 
1978
                }
 
1979
                if (mode == MARK_8BPP_TOP) {
 
1980
                        if (windows_8bpp[i].top != top) {
 
1981
                                continue;
 
1982
                        }
 
1983
                }
 
1984
                if (windows_8bpp[i].map_state != IsViewable) {
 
1985
                        XWindowAttributes attr;
 
1986
                        int vw;
 
1987
 
 
1988
                        X_LOCK;
 
1989
                        vw = valid_window(windows_8bpp[i].win, &attr, 1);
 
1990
                        X_UNLOCK;
 
1991
                        if (vw) {
 
1992
                                if (attr.map_state != IsViewable) {
 
1993
                                        continue;
 
1994
                                }
 
1995
                        } else {
 
1996
                                continue;
 
1997
                        }
 
1998
                }
 
1999
 
 
2000
                x1 = windows_8bpp[i].x;
 
2001
                y1 = windows_8bpp[i].y;
 
2002
                w  = windows_8bpp[i].w;
 
2003
                h  = windows_8bpp[i].h;
 
2004
 
 
2005
                x2 = x1 + w;
 
2006
                y2 = y1 + h;
 
2007
 
 
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) {
 
2011
                                continue;
 
2012
                        }
 
2013
                        if (cursor_x > x2 + b || cursor_y > y2 + b) {
 
2014
                                continue;
 
2015
                        }
 
2016
                }
 
2017
 
 
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);
 
2023
 
 
2024
if (db24 > 1) fprintf(stderr, "mark_8bpp: 0x%lx %d %d %d %d\n", windows_8bpp[i].win, x1, y1, x2, y2);
 
2025
 
 
2026
                mark_rect_as_modified(x1, y1, x2, y2, 0);
 
2027
                cnt++;
 
2028
        }
 
2029
        if (cnt) {
 
2030
                /* push it to viewers if possible. */
 
2031
                rfbPE(-1);
 
2032
        }
 
2033
}
 
2034
 
 
2035
#endif /* SKIP_8TO24 */
 
2036