make sure the window's region is correct, and if we fail to update the region cuz...
[dana/dcompmgr.git] / glxrender.c
1 #include "efence.h"
2
3 #include "render.h"
4 #include "screen.h"
5 #include "window.h"
6 #include "display.h"
7 #include "list.h"
8 #include <stdio.h>
9 #include <string.h>
10 #include <assert.h>
11 #include <stdlib.h>
12
13 #include <X11/Xmd.h>
14 #include <GL/glxproto.h>
15
16 #include <GL/gl.h>
17 #include <GL/glx.h>
18 #include <GL/glxtokens.h>
19 #include <GL/glext.h>
20 #include <GL/glxext.h>
21
22 #define MAX_DEPTH 32
23
24 static int plugin_id;
25
26 #define LEFT   0
27 #define TOP    1
28 #define RIGHT  2
29 #define BOTTOM 3
30
31 typedef void (*BindEXTFunc)(Display *, GLXDrawable, int, const int *);
32 typedef void (*ReleaseEXTFunc)(Display *, GLXDrawable, int);
33
34 typedef struct {
35     void (*screen_paint)(d_screen_t *sc);
36     void (*screen_root_pixmap_change)(d_screen_t *sc);
37     void (*window_show)(d_window_t *w);
38     void (*window_zombie_dead)(d_window_t *w);
39     void (*window_resize)(d_window_t *w);
40     void (*window_reshape)(d_window_t *w);
41
42     float shadowalpha;
43     int xshadowoff;
44     int yshadowoff;
45
46     GLXFBConfig fbconfig[MAX_DEPTH + 1];
47
48     GLXContext context;
49     GLuint root_texname;
50     GLXPixmap root_glpixmap;
51
52     BindEXTFunc bind_func;
53     ReleaseEXTFunc release_func;
54 } data_t;
55
56 typedef struct {
57     GLuint texname;
58     GLXPixmap glpixmap;
59
60     GLfloat *texcoords;
61     GLint *vertices;
62     int nrects;
63
64     xcb_xfixes_fetch_region_cookie_t ck_region;
65     int waiting_region;
66     int x_region;
67     int y_region;
68     int w_region;
69     int h_region;
70     int bw_region;
71 } window_data_t;
72
73 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
74
75 static void glxrender_paint(d_screen_t *sc);
76 static void glxrender_root_pixmap_change(d_screen_t *sc);
77 static void paint_root(d_screen_t *sc, data_t *d);
78 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
79                          int x, int y, GLfloat z);
80 static void paint_shadow(data_t *d, window_data_t *wd, int x, int y,
81                          GLfloat z);
82 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
83                                            window_data_t *wd);
84 static void glxrender_fetch_window_region(d_window_t *w, window_data_t *wd);
85 static void glxrender_update_window_region(d_window_t *w, window_data_t *wd);
86 static void glxrender_free_window_pixmap(d_window_t *w, data_t *d,
87                                          window_data_t *wd);
88 static void glxrender_free_window_region(window_data_t *wd);
89 static void glxrender_free_root_pixmap(d_screen_t *sc, data_t *d);
90 static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
91
92 static void glxrender_window_show(d_window_t *window);
93 static void glxrender_window_zombie_dead(d_window_t *window);
94 static void glxrender_window_resize(d_window_t *window);
95 static void glxrender_window_reshape(d_window_t *window);
96
97 void
98 glxrender_init(d_screen_t *sc, int id)
99 {
100     static int context_visual_config[] = {
101         GLX_DEPTH_SIZE, 1,
102         GLX_DOUBLEBUFFER,
103         GLX_RGBA,
104         XCB_NONE
105     };
106     XVisualInfo *vi;
107     data_t *d;
108
109     plugin_id = id;
110
111     d = malloc(sizeof(data_t));
112     d->screen_paint = sc->screen_paint;
113     d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
114     d->window_show = sc->window_show;
115     d->window_zombie_dead = sc->window_zombie_dead;
116     d->window_resize = sc->window_resize;
117     d->window_reshape = sc->window_reshape;
118     screen_add_plugin_data(sc, plugin_id, d);
119
120     sc->screen_paint = glxrender_paint;
121     sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
122     sc->window_show = glxrender_window_show;
123     sc->window_zombie_dead = glxrender_window_zombie_dead;
124     sc->window_resize = glxrender_window_resize;
125     sc->window_reshape = glxrender_window_reshape;
126
127     d->shadowalpha = 0.2f; /* 20% */
128     d->xshadowoff = 2;
129     d->yshadowoff = 2;
130
131     vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config);
132     if (!vi) {
133         printf("unable to find a valid double buffered GL context to use\n");
134         exit(1);
135     }
136
137     if (!(glxrender_find_fb_config(sc, d))) {
138         printf("unable to find FB configs\n");
139         exit(1);
140     }
141
142     d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
143     glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
144
145     glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
146     glMatrixMode(GL_PROJECTION);
147     glLoadIdentity();
148     glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0,
149             -100.0, 100.0);
150     glMatrixMode(GL_MODELVIEW);
151     glLoadIdentity();
152     glEnable(GL_TEXTURE_2D);
153     glEnable(GL_DEPTH_TEST);
154     //glEnable(GL_SCISSOR_TEST); ?? what is this, glxcompmgr enables it
155     //glEnable(GL_STENCIL_TEST); ?? what is this, glxcompmgr enables it
156
157     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
158     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
159     glDisable(GL_BLEND);
160
161     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
162     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
163
164     glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
165
166     d->bind_func = (BindEXTFunc)
167         glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
168     d->release_func = (ReleaseEXTFunc)
169         glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
170
171     glGenTextures(1, &d->root_texname);
172     d->root_glpixmap = XCB_NONE;
173 }
174
175 static gboolean
176 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
177 {
178     static const int drawable_tfp_attrs[] = {
179         GLX_CONFIG_CAVEAT, GLX_NONE,
180         GLX_DOUBLEBUFFER, FALSE,
181         GLX_DEPTH_SIZE, 0,
182         GLX_RED_SIZE, 1,
183         GLX_GREEN_SIZE, 1,
184         GLX_BLUE_SIZE, 1,
185         GLX_ALPHA_SIZE, 1,
186         GLX_RENDER_TYPE, GLX_RGBA_BIT,
187         GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
188         XCB_NONE
189     };
190     int db, stencil, depth, numfb, i;
191     GLXFBConfig *fbcons;
192     XVisualInfo tvis, *visinfo;
193
194     fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num,
195                                drawable_tfp_attrs, &numfb);
196     if (!fbcons) return FALSE;
197
198     for (i = 0; i <= MAX_DEPTH; i++) {
199         int j, count, value;
200         VisualID vid;
201
202         vid = 0;
203         d->fbconfig[i] = 0;
204         db = 32767;
205         stencil = 32767;
206         depth = 32767;
207
208         //printf("looking for depth %d\n", i);
209
210         tvis.depth = i;
211         visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
212                                  &tvis, &count);
213         /* pick the nicest visual for the depth */
214         for (j = 0; j < count; j++) {
215             glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_USE_GL, &value);
216             if (!value)
217                 continue;
218
219             glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER,
220                          &value);
221             if (value > db)
222                 continue;
223             db = value;
224
225             glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE,
226                          &value);
227             if (value > stencil)
228                 continue;
229             stencil = value;
230
231             glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE,
232                          &value);
233             if (value > depth)
234                 continue;
235             depth = value;
236
237             /* use this visual */
238             vid = visinfo[j].visualid;
239         }
240
241         if (!vid) continue;
242
243         /* look for an fbconfig for this visual */
244         for (j = 0; j < numfb; ++j) {
245             glXGetFBConfigAttrib(sc->dpy->xlib_dpy, fbcons[j],
246                                  GLX_VISUAL_ID, &value);
247             if ((unsigned)value == vid) {
248                 d->fbconfig[i] = fbcons[j];
249
250                 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
251                        (uint32_t)vid, (uint32_t)fbcons[j], i);
252                 break;
253             }
254         }
255     }
256
257     XFree(fbcons);
258     return TRUE;
259 }
260
261 void
262 glxrender_free(d_screen_t *sc)
263 {
264     data_t *d = screen_find_plugin_data(sc, plugin_id);
265     if (d) {
266         glxrender_free_root_pixmap(sc, d);
267         glXDestroyContext(sc->dpy->xlib_dpy, d->context);
268         free(d);
269     }
270     screen_remove_plugin_data(sc, plugin_id);
271 }
272
273 int
274 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
275 {
276     (void)sc;
277     (void)tv;
278     return FALSE;
279 }
280
281 void
282 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
283 {
284     (void)sc; (void)now;
285 }
286
287 void
288 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
289 {
290     glxrender_free_window_pixmap(w, d, wd);
291     glxrender_free_window_region(wd);
292     glDeleteTextures(1, &wd->texname);
293     free(wd);
294 }
295
296 static void
297 glxrender_window_show(d_window_t *w)
298 {
299     data_t *d;
300     window_data_t *wd;
301
302     d = screen_find_plugin_data(w->sc, plugin_id);
303
304     /* pass it on */
305     d->window_show(w);
306
307     wd = window_find_plugin_data(w, plugin_id);
308     if (wd) {
309         glxrender_window_free_data(w, d, wd);
310         window_remove_plugin_data(w, plugin_id);
311     }
312
313     wd = malloc(sizeof(window_data_t));
314     glGenTextures(1, &wd->texname);
315     wd->glpixmap = XCB_NONE;
316     wd->texcoords = NULL;
317     wd->vertices = NULL;
318     wd->nrects = 0;
319     wd->waiting_region = FALSE;
320
321     window_add_plugin_data(w, plugin_id, wd);
322
323     glxrender_fetch_window_region(w, wd);
324 }
325
326 static void
327 glxrender_window_zombie_dead(d_window_t *w)
328 {
329     data_t *d;
330     window_data_t *wd;
331
332     d = screen_find_plugin_data(w->sc, plugin_id);
333     wd = window_find_plugin_data(w, plugin_id);
334     if (wd) {
335         glxrender_window_free_data(w, d, wd);
336         window_remove_plugin_data(w, plugin_id);
337     }
338
339     /* pass it on */
340     d->window_zombie_dead(w);
341 }
342
343 static void
344 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
345 {
346     /* this might cause an error, oh well */
347     if (wd->glpixmap) {
348         glBindTexture(GL_TEXTURE_2D, wd->texname);
349         d->release_func(w->sc->dpy->xlib_dpy,
350                         wd->glpixmap, GLX_FRONT_LEFT_EXT);
351         glBindTexture(GL_TEXTURE_2D, 0);
352
353         glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
354         wd->glpixmap = XCB_NONE;
355
356     }
357 }
358
359 static void
360 glxrender_free_window_region(window_data_t *wd)
361 {
362     if (wd->nrects) {
363         free(wd->texcoords);
364         free(wd->vertices);
365         wd->texcoords = NULL;
366         wd->vertices = NULL;
367         wd->nrects = 0;
368     }
369 }
370
371 static void
372 glxrender_free_root_pixmap(d_screen_t *sc, data_t *d)
373 {
374     /* this might cause an error, oh well */
375     if (d->root_glpixmap) {
376         glBindTexture(GL_TEXTURE_2D, d->root_texname);
377         d->release_func(sc->dpy->xlib_dpy,
378                         d->root_glpixmap, GLX_FRONT_LEFT_EXT);
379         glBindTexture(GL_TEXTURE_2D, 0);
380
381         glXDestroyPixmap(sc->dpy->xlib_dpy, d->root_glpixmap);
382         d->root_glpixmap = XCB_NONE;
383     }
384 }
385
386 static void
387 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
388 {
389     xcb_pixmap_t px;
390     uint8_t depth;
391
392     static int attrs[] = {
393         GLX_TEXTURE_FORMAT_EXT,
394         XCB_NONE,
395         XCB_NONE
396     };
397
398     px = window_get_pixmap(w);
399     depth = window_get_depth(w);
400
401     if (!px) return;
402
403     if (!d->fbconfig[depth]) {
404         printf("no GL visual for depth %d\n", depth);
405         return;
406     }
407
408     if (window_is_argb(w))
409         attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
410     else
411         attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
412
413     wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
414                                    d->fbconfig[depth],
415                                    px, attrs);
416 #if 0
417     wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
418     int v;
419     glXGetFBConfigAttrib(w->sc->dpy->xlib_dpy, d->fbconfig[depth],
420                          GLX_FBCONFIG_ID, &v);
421     xcb_void_cookie_t ck =
422         xcb_glx_create_pixmap_checked(w->sc->dpy->conn, w->sc->num,
423                                       v,
424                                       px, wd->glpixmap,
425                                       2,
426                                       attrs);
427     xcb_generic_error_t *err = xcb_request_check(w->sc->dpy->conn, ck);
428     if (err) {
429         display_error(w->sc->dpy, err);
430         free(err);
431         wd->glpixmap = XCB_NONE;
432         return;
433     }
434 #endif
435
436     glBindTexture(GL_TEXTURE_2D, wd->texname);
437     d->bind_func(w->sc->dpy->xlib_dpy,
438                  wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
439 #if 0
440     {
441         /*
442           BindTexImageEXT
443           1           CARD8                   opcode (X assigned)
444           1           16                      GLX opcode (glXVendorPrivate)
445           2           6+n                     request length
446           4           1330                    vendor specific opcode
447           4           CARD32                  context tag
448           4           GLX_DRAWABLE            drawable
449           4           INT32                   buffer
450           4           CARD32                  num_attributes
451           4*n         LISTofATTRIBUTE_PAIR    attribute, value pairs.
452         */
453         unsigned int len = 12;
454         uint32_t data[] = {
455             wd->glpixmap,
456             GLX_FRONT_LEFT_EXT,
457             0,
458         };
459         xcb_glx_vendor_private(w->sc->dpy->conn,
460                                X_GLXvop_BindTexImageEXT,
461                                1,
462                                len, (uint8_t*)data);
463     }
464 #endif
465
466     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
467     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
468
469     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
470     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
471
472     glBindTexture(GL_TEXTURE_2D, 0);
473 }
474
475 static void
476 glxrender_fetch_window_region(d_window_t *w, window_data_t *wd)
477 {
478     window_get_area(w, &wd->x_region, &wd->y_region,
479                     &wd->w_region, &wd->h_region, &wd->bw_region);
480
481     wd->ck_region =
482         xcb_xfixes_fetch_region_unchecked(w->sc->dpy->conn,
483                                           window_get_region(w));
484     wd->waiting_region = TRUE;
485     xcb_flush(w->sc->dpy->conn);
486 }
487
488 static void
489 glxrender_update_window_region(d_window_t *w, window_data_t *wd)
490 {
491     xcb_xfixes_fetch_region_reply_t *rep;
492     xcb_rectangle_t area, *rects;
493     int nrects, i, j;
494
495     if (!wd->waiting_region) return;
496
497     area.x = wd->x_region;
498     area.y = wd->y_region;
499     area.width = wd->w_region + wd->bw_region * 2;
500     area.height = wd->h_region + wd->bw_region * 2;
501
502     rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, wd->ck_region, NULL);
503     if (!rep) {
504         rects = &area;
505         nrects = 1;
506     }
507     else {
508         rects = xcb_xfixes_fetch_region_rectangles(rep);
509         nrects = xcb_xfixes_fetch_region_rectangles_length(rep);
510     }
511
512     wd->texcoords = (GLfloat*)realloc(wd->texcoords,
513                                       sizeof(GLfloat) * (nrects * 4));
514     wd->vertices = (GLint*)realloc(wd->vertices, sizeof(GLint) * (nrects * 4));
515     wd->nrects = nrects;
516
517     for (i = j = 0; i < nrects * 4; ++j, i += 4) {
518         wd->texcoords[i+LEFT] =
519             (GLfloat)(rects[j].x - area.x) / (GLfloat)area.width;
520         wd->texcoords[i+TOP] =
521             (GLfloat)(rects[j].y - area.y) / (GLfloat)area.height;
522         wd->texcoords[i+RIGHT] =
523             (GLfloat)(rects[j].x - area.x + rects[j].width) /
524             (GLfloat)area.width;
525         wd->texcoords[i+BOTTOM] =
526             (GLfloat)(rects[j].y - area.y + rects[j].height) /
527             (GLfloat)area.height;
528
529         wd->vertices[i+LEFT] = rects[j].x - area.x;
530         wd->vertices[i+TOP] = rects[j].y - area.y;
531         wd->vertices[i+RIGHT] = rects[j].x - area.x + rects[j].width;
532         wd->vertices[i+BOTTOM] = rects[j].y - area.y + rects[j].height;
533     }
534
535     if (rep)
536         free(rep);
537
538     wd->waiting_region = FALSE;
539 }
540
541 static void
542 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
543 {
544     xcb_pixmap_t px;
545     static int attrs[] = {
546         GLX_TEXTURE_FORMAT_EXT,
547         GLX_TEXTURE_FORMAT_RGB_EXT,
548         XCB_NONE
549     };
550
551     px = screen_get_root_pixmap(sc);
552     if (!px) return;
553
554     if (!d->fbconfig[sc->super->root_depth]) {
555         printf("no GL visual for depth %d\n", sc->super->root_depth);
556         return;
557     }
558
559     d->root_glpixmap = glXCreatePixmap(sc->dpy->xlib_dpy,
560                                        d->fbconfig[sc->super->root_depth],
561                                        px, attrs);
562
563
564     glBindTexture(GL_TEXTURE_2D, d->root_texname);
565     d->bind_func(sc->dpy->xlib_dpy,
566                  d->root_glpixmap, GLX_FRONT_LEFT_EXT, NULL);
567
568     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
569     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
570
571     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
572     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
573
574     glBindTexture(GL_TEXTURE_2D, 0);
575 }
576
577 static void
578 glxrender_window_resize(d_window_t *w)
579 {
580     data_t *d;
581     window_data_t *wd;
582
583     d = screen_find_plugin_data(w->sc, plugin_id);
584     wd = window_find_plugin_data(w, plugin_id);
585
586     /* pass it on */
587     d->window_resize(w);
588
589     assert(wd != NULL);
590     glxrender_free_window_pixmap(w, d, wd);
591     glxrender_fetch_window_region(w, wd);
592 }
593
594 static void
595 glxrender_window_reshape(d_window_t *w)
596 {
597     data_t *d;
598     window_data_t *wd;
599
600     d = screen_find_plugin_data(w->sc, plugin_id);
601     wd = window_find_plugin_data(w, plugin_id);
602
603     /* pass it on */
604     d->window_reshape(w);
605
606     assert(wd != NULL);
607     //glxrender_free_window_pixmap(w, d, wd);
608     glxrender_fetch_window_region(w, wd);
609 }
610
611 static void
612 glxrender_root_pixmap_change(d_screen_t *sc)
613 {
614     data_t *d;
615
616     d = screen_find_plugin_data(sc, plugin_id);
617     glxrender_free_root_pixmap(sc, d);
618
619     /* pass it on */
620     d->screen_root_pixmap_change(sc);
621 }
622
623 static void
624 glxrender_paint(d_screen_t *sc)
625 {
626     data_t *d = screen_find_plugin_data(sc, plugin_id);
627     d_list_it_t *it;
628     GLfloat z;
629
630     //printf("painting\n");
631
632     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
633
634     /* add 0.1f to keep everything above the root */
635     z = list_length(sc->stacking) * 0.1f + 0.1f;
636     for (it = list_top(sc->stacking); it; it = it->next) {
637         d_window_t *w = it->data;
638
639         if (!window_is_input_only(w) &&
640             (window_is_mapped(w) || window_is_zombie(w)))
641         {
642             int x, y, width, height, bwidth;
643             gboolean opaque;
644             window_data_t *wd;
645
646             window_get_area(w, &x, &y, &width, &height, &bwidth);
647
648             if (!(x < sc->super->width_in_pixels &&
649                   y < sc->super->height_in_pixels &&
650                   (x + width > 0 || x + width + d->xshadowoff > 0) &&
651                   (y + height > 0 || y + height + d->yshadowoff > 0)))
652             {
653                 continue;
654             }
655
656             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
657
658             if (opaque) {
659                 wd = window_find_plugin_data(w, plugin_id);
660
661                 //glPushMatrix();
662
663                 paint_window(w, d, wd, x, y, z - 0.05f);
664
665                 //glPopMatrix();
666             }
667
668             z -= 0.1f;
669         }
670     }
671
672     paint_root(sc, d);
673
674     glEnable(GL_BLEND);
675     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
676
677     for (it = list_bottom(sc->stacking); it; it = it->prev) {
678         d_window_t *w = it->data;
679
680         if (!window_is_input_only(w) &&
681             (window_is_mapped(w) || window_is_zombie(w)))
682         {
683             int x, y, width, height, bwidth;
684             gboolean opaque;
685             window_data_t *wd;
686             uint16_t opac;
687             GLfloat alpha;
688
689             window_get_area(w, &x, &y, &width, &height, &bwidth);
690
691             if (!(x < sc->super->width_in_pixels &&
692                   y < sc->super->height_in_pixels &&
693                   (x + width > 0 || x + width + d->xshadowoff > 0) &&
694                   (y + height > 0 || y + height + d->yshadowoff > 0)))
695             {
696                 continue;
697             }
698
699             opac = window_get_opacity(w);
700             opaque = !window_is_argb(w) && opac == 0xffff;
701
702             wd = window_find_plugin_data(w, plugin_id);
703
704             //glPushMatrix();
705
706             /* black shadow */
707             alpha = d->shadowalpha;
708             alpha *= opac;
709             alpha /= 0xffff;
710             if (alpha >= 0.01) {
711                 glColor4f(0.0f, 0.0f, 0.0f, alpha);
712                 paint_shadow(d, wd, x, y, z);
713             }
714
715             if (!opaque) {
716                 glColor4us(opac, opac, opac, opac);
717                 paint_window(w, d, wd, x, y, z + 0.05f);
718             }
719
720             //glPopMatrix();
721
722             z += 0.1f;
723         }
724     }
725
726     glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
727     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
728     glDisable(GL_BLEND);
729
730     glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
731
732     /* call the function we replaced in the chain */
733     d->screen_paint(sc);
734 }
735
736 static void
737 paint_root(d_screen_t *sc, data_t *d)
738 {
739     if (!d->root_glpixmap)
740         glxrender_update_root_pixmap(sc, d);
741
742     glBindTexture(GL_TEXTURE_2D, d->root_texname);
743     glBegin(GL_QUADS);
744     glTexCoord2f(0, 0);
745     glVertex3i(0, 0, 0);
746     glTexCoord2f(1, 0);
747     glVertex3i(sc->super->width_in_pixels, 0, 0);
748     glTexCoord2f(1, 1);
749     glVertex3i(sc->super->width_in_pixels, sc->super->height_in_pixels, 0);
750     glTexCoord2f(0, 1);
751     glVertex3i(0, sc->super->height_in_pixels, 0);
752     glEnd();
753
754     glBindTexture(GL_TEXTURE_2D, 0);
755 }
756
757 static void
758 paint_window(d_window_t *w, data_t *d, window_data_t *wd, int x, int y,
759              GLfloat z)
760 {
761     int i;
762
763     if (!wd->glpixmap)
764         glxrender_update_window_pixmap(w, d, wd);
765     if (wd->waiting_region)
766         glxrender_update_window_region(w, wd);
767
768     if (wd->nrects < 1) return;
769
770     glBindTexture(GL_TEXTURE_2D, wd->texname);
771
772     glBegin(GL_QUADS);
773     for (i = 0; i < wd->nrects * 4; i += 4) {
774         glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
775         glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
776         glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
777         glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
778         glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
779         glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
780         glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
781         glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
782     }
783     glEnd();
784
785     glBindTexture(GL_TEXTURE_2D, 0);
786 }
787
788 static void
789 paint_shadow(data_t *d, window_data_t *wd, int x, int y, GLfloat z)
790 {
791     int i;
792
793     if (wd->nrects < 1) return;
794
795     /* shape the shadow to the window */
796     glBindTexture(GL_TEXTURE_2D, wd->texname);
797
798     x += d->xshadowoff;
799     y += d->yshadowoff;
800
801     glBegin(GL_QUADS);
802     for (i = 0; i < wd->nrects * 4; i += 4) {
803         glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
804         glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
805         glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
806         glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
807         glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
808         glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
809         glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
810         glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
811     }
812     glEnd();
813
814     glBindTexture(GL_TEXTURE_2D, 0);
815 }