4647d62be8b44bb7b72d69658eda457093f653e2
[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    
311     wd = malloc(sizeof(window_data_t));
312     glGenTextures(1, &wd->texname);
313     wd->glpixmap = XCB_NONE;
314     wd->texcoords = NULL;
315     wd->vertices = NULL;
316     wd->nrects = 0;
317     wd->waiting_region = FALSE;
318
319     window_add_plugin_data(w, plugin_id, wd);
320
321     glxrender_fetch_window_region(w, wd);
322 }
323
324 static void
325 glxrender_window_zombie_dead(d_window_t *w)
326 {
327     data_t *d;
328     window_data_t *wd;
329
330     d = screen_find_plugin_data(w->sc, plugin_id);
331     wd = window_find_plugin_data(w, plugin_id);
332     if (wd) {
333         glxrender_window_free_data(w, d, wd);
334         window_remove_plugin_data(w, plugin_id);
335     }
336
337     /* pass it on */
338     d->window_zombie_dead(w);
339 }
340
341 static void
342 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
343 {
344     /* this might cause an error, oh well */
345     if (wd->glpixmap) {
346         glBindTexture(GL_TEXTURE_2D, wd->texname);
347         d->release_func(w->sc->dpy->xlib_dpy,
348                         wd->glpixmap, GLX_FRONT_LEFT_EXT);
349         glBindTexture(GL_TEXTURE_2D, 0);
350
351         glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
352         wd->glpixmap = XCB_NONE;
353
354     }
355 }
356
357 static void
358 glxrender_free_window_region(window_data_t *wd)
359 {
360     if (wd->nrects) {
361         free(wd->texcoords);
362         free(wd->vertices);
363         wd->texcoords = NULL;
364         wd->vertices = NULL;
365         wd->nrects = 0;
366     }
367 }
368
369 static void
370 glxrender_free_root_pixmap(d_screen_t *sc, data_t *d)
371 {
372     /* this might cause an error, oh well */
373     if (d->root_glpixmap) {
374         glBindTexture(GL_TEXTURE_2D, d->root_texname);
375         d->release_func(sc->dpy->xlib_dpy,
376                         d->root_glpixmap, GLX_FRONT_LEFT_EXT);
377         glBindTexture(GL_TEXTURE_2D, 0);
378
379         glXDestroyPixmap(sc->dpy->xlib_dpy, d->root_glpixmap);
380         d->root_glpixmap = XCB_NONE;
381     }
382 }
383
384 static void
385 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
386 {
387     xcb_pixmap_t px;
388     uint8_t depth;
389
390     static int attrs[] = {
391         GLX_TEXTURE_FORMAT_EXT,
392         XCB_NONE,
393         XCB_NONE
394     };
395
396     px = window_get_pixmap(w);
397     depth = window_get_depth(w);
398
399     if (!px) return;
400
401     if (!d->fbconfig[depth]) {
402         printf("no GL visual for depth %d\n", depth);
403         return;
404     }
405
406     if (window_is_argb(w))
407         attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
408     else
409         attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
410
411     wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
412                                    d->fbconfig[depth],
413                                    px, attrs);
414 #if 0
415     wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
416     int v;
417     glXGetFBConfigAttrib(w->sc->dpy->xlib_dpy, d->fbconfig[depth],
418                          GLX_FBCONFIG_ID, &v);
419     xcb_void_cookie_t ck =
420         xcb_glx_create_pixmap_checked(w->sc->dpy->conn, w->sc->num,
421                                       v,
422                                       px, wd->glpixmap,
423                                       2,
424                                       attrs);
425     xcb_generic_error_t *err = xcb_request_check(w->sc->dpy->conn, ck);
426     if (err) {
427         display_error(w->sc->dpy, err);
428         free(err);
429         wd->glpixmap = XCB_NONE;
430         return;
431     }
432 #endif
433
434     glBindTexture(GL_TEXTURE_2D, wd->texname);
435     d->bind_func(w->sc->dpy->xlib_dpy,
436                  wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
437 #if 0
438     {
439         /*
440           BindTexImageEXT
441           1           CARD8                   opcode (X assigned)
442           1           16                      GLX opcode (glXVendorPrivate)
443           2           6+n                     request length
444           4           1330                    vendor specific opcode
445           4           CARD32                  context tag
446           4           GLX_DRAWABLE            drawable
447           4           INT32                   buffer
448           4           CARD32                  num_attributes
449           4*n         LISTofATTRIBUTE_PAIR    attribute, value pairs.
450         */
451         unsigned int len = 12;
452         uint32_t data[] = {
453             wd->glpixmap,
454             GLX_FRONT_LEFT_EXT,
455             0,
456         };
457         xcb_glx_vendor_private(w->sc->dpy->conn,
458                                X_GLXvop_BindTexImageEXT,
459                                1,
460                                len, (uint8_t*)data);
461     }
462 #endif
463
464     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
465     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
466
467     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
468     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
469
470     glBindTexture(GL_TEXTURE_2D, 0);
471 }
472
473 static void
474 glxrender_fetch_window_region(d_window_t *w, window_data_t *wd)
475 {
476     window_get_area(w, &wd->x_region, &wd->y_region,
477                     &wd->w_region, &wd->h_region, &wd->bw_region);
478
479     wd->ck_region =
480         xcb_xfixes_fetch_region_unchecked(w->sc->dpy->conn,
481                                           window_get_region(w));
482     wd->waiting_region = TRUE;
483     xcb_flush(w->sc->dpy->conn);
484 }
485
486 static void
487 glxrender_update_window_region(d_window_t *w, window_data_t *wd)
488 {
489     xcb_xfixes_fetch_region_reply_t *rep;
490     xcb_rectangle_t area, *rects;
491     int nrects, i, j;
492
493     if (!wd->waiting_region) return;
494
495     area.x = wd->x_region;
496     area.y = wd->y_region;
497     area.width = wd->w_region + wd->bw_region * 2;
498     area.height = wd->h_region + wd->bw_region * 2;
499
500     rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, wd->ck_region, NULL);
501     if (!rep) {
502         rects = &area;
503         nrects = 1;
504     }
505     else {
506         rects = xcb_xfixes_fetch_region_rectangles(rep);
507         nrects = xcb_xfixes_fetch_region_rectangles_length(rep);
508     }
509
510     wd->texcoords = (GLfloat*)realloc(wd->texcoords,
511                                       sizeof(GLfloat) * (nrects * 4));
512     wd->vertices = (GLint*)realloc(wd->vertices, sizeof(GLint) * (nrects * 4));
513     wd->nrects = nrects;
514
515     for (i = j = 0; i < nrects * 4; ++j, i += 4) {
516         wd->texcoords[i+LEFT] =
517             (GLfloat)(rects[j].x - area.x) / (GLfloat)area.width;
518         wd->texcoords[i+TOP] =
519             (GLfloat)(rects[j].y - area.y) / (GLfloat)area.height;
520         wd->texcoords[i+RIGHT] =
521             (GLfloat)(rects[j].x - area.x + rects[j].width) /
522             (GLfloat)area.width;
523         wd->texcoords[i+BOTTOM] =
524             (GLfloat)(rects[j].y - area.y + rects[j].height) /
525             (GLfloat)area.height;
526
527         wd->vertices[i+LEFT] = rects[j].x - area.x;
528         wd->vertices[i+TOP] = rects[j].y - area.y;
529         wd->vertices[i+RIGHT] = rects[j].x - area.x + rects[j].width;
530         wd->vertices[i+BOTTOM] = rects[j].y - area.y + rects[j].height;
531     }
532
533     if (rep)
534         free(rep);
535
536     wd->waiting_region = FALSE;
537 }
538
539 static void
540 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
541 {
542     xcb_pixmap_t px;
543     static int attrs[] = {
544         GLX_TEXTURE_FORMAT_EXT,
545         GLX_TEXTURE_FORMAT_RGB_EXT,
546         XCB_NONE
547     };
548
549     px = screen_get_root_pixmap(sc);
550     if (!px) return;
551
552     if (!d->fbconfig[sc->super->root_depth]) {
553         printf("no GL visual for depth %d\n", sc->super->root_depth);
554         return;
555     }
556
557     d->root_glpixmap = glXCreatePixmap(sc->dpy->xlib_dpy,
558                                        d->fbconfig[sc->super->root_depth],
559                                        px, attrs);
560
561
562     glBindTexture(GL_TEXTURE_2D, d->root_texname);
563     d->bind_func(sc->dpy->xlib_dpy,
564                  d->root_glpixmap, GLX_FRONT_LEFT_EXT, NULL);
565
566     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
567     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
568
569     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
570     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
571
572     glBindTexture(GL_TEXTURE_2D, 0);
573 }
574
575 static void
576 glxrender_window_resize(d_window_t *w)
577 {
578     data_t *d;
579     window_data_t *wd;
580
581     d = screen_find_plugin_data(w->sc, plugin_id);
582     wd = window_find_plugin_data(w, plugin_id);
583
584     /* pass it on */
585     d->window_resize(w);
586
587     assert(wd != NULL);
588     glxrender_free_window_pixmap(w, d, wd);
589     glxrender_fetch_window_region(w, wd);
590 }
591
592 static void
593 glxrender_window_reshape(d_window_t *w)
594 {
595     data_t *d;
596     window_data_t *wd;
597
598     d = screen_find_plugin_data(w->sc, plugin_id);
599     wd = window_find_plugin_data(w, plugin_id);
600
601     /* pass it on */
602     d->window_reshape(w);
603
604     assert(wd != NULL);
605     glxrender_free_window_pixmap(w, d, wd);
606     glxrender_fetch_window_region(w, wd);
607 }
608
609 static void
610 glxrender_root_pixmap_change(d_screen_t *sc)
611 {
612     data_t *d;
613
614     d = screen_find_plugin_data(sc, plugin_id);
615     glxrender_free_root_pixmap(sc, d);
616
617     /* pass it on */
618     d->screen_root_pixmap_change(sc);
619 }
620
621 static void
622 glxrender_paint(d_screen_t *sc)
623 {
624     data_t *d = screen_find_plugin_data(sc, plugin_id);
625     d_list_it_t *it;
626     GLfloat z;
627
628     //printf("painting\n");
629
630     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
631
632     /* add 0.1f to keep everything above the root */
633     z = list_length(sc->stacking) * 0.1f + 0.1f;
634     for (it = list_top(sc->stacking); it; it = it->next) {
635         d_window_t *w = it->data;
636
637         if (!window_is_input_only(w) &&
638             (window_is_mapped(w) || window_is_zombie(w)))
639         {
640             int x, y, width, height, bwidth;
641             gboolean opaque;
642             window_data_t *wd;
643
644             window_get_area(w, &x, &y, &width, &height, &bwidth);
645
646             if (!(x < sc->super->width_in_pixels &&
647                   y < sc->super->height_in_pixels &&
648                   (x + width > 0 || x + width + d->xshadowoff > 0) &&
649                   (y + height > 0 || y + height + d->yshadowoff > 0)))
650             {
651                 continue;
652             }
653
654             opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
655
656             if (opaque) {
657                 wd = window_find_plugin_data(w, plugin_id);
658
659                 //glPushMatrix();
660
661                 paint_window(w, d, wd, x, y, z - 0.05f);
662
663                 //glPopMatrix();
664             }
665
666             z -= 0.1f;
667         }
668     }
669
670     paint_root(sc, d);
671
672     glEnable(GL_BLEND);
673     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
674
675     for (it = list_bottom(sc->stacking); it; it = it->prev) {
676         d_window_t *w = it->data;
677
678         if (!window_is_input_only(w) &&
679             (window_is_mapped(w) || window_is_zombie(w)))
680         {
681             int x, y, width, height, bwidth;
682             gboolean opaque;
683             window_data_t *wd;
684             uint16_t opac;
685             GLfloat alpha;
686
687             window_get_area(w, &x, &y, &width, &height, &bwidth);
688
689             if (!(x < sc->super->width_in_pixels &&
690                   y < sc->super->height_in_pixels &&
691                   (x + width > 0 || x + width + d->xshadowoff > 0) &&
692                   (y + height > 0 || y + height + d->yshadowoff > 0)))
693             {
694                 continue;
695             }
696
697             opac = window_get_opacity(w);
698             opaque = !window_is_argb(w) && opac == 0xffff;
699
700             wd = window_find_plugin_data(w, plugin_id);
701
702             //glPushMatrix();
703
704             /* black shadow */
705             alpha = d->shadowalpha;
706             alpha *= opac;
707             alpha /= 0xffff;
708             if (alpha >= 0.01) {
709                 glColor4f(0.0f, 0.0f, 0.0f, alpha);
710                 paint_shadow(d, wd, x, y, z);
711             }
712
713             if (!opaque) {
714                 glColor4us(opac, opac, opac, opac);
715                 paint_window(w, d, wd, x, y, z + 0.05f);
716             }
717
718             //glPopMatrix();
719
720             z += 0.1f;
721         }
722     }
723
724     glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
725     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
726     glDisable(GL_BLEND);
727
728     glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
729
730     /* call the function we replaced in the chain */
731     d->screen_paint(sc);
732 }
733
734 static void
735 paint_root(d_screen_t *sc, data_t *d)
736 {
737     if (!d->root_glpixmap)
738         glxrender_update_root_pixmap(sc, d);
739
740     glBindTexture(GL_TEXTURE_2D, d->root_texname);
741     glBegin(GL_QUADS);
742     glTexCoord2f(0, 0);
743     glVertex3i(0, 0, 0);
744     glTexCoord2f(1, 0);
745     glVertex3i(sc->super->width_in_pixels, 0, 0);
746     glTexCoord2f(1, 1);
747     glVertex3i(sc->super->width_in_pixels, sc->super->height_in_pixels, 0);
748     glTexCoord2f(0, 1);
749     glVertex3i(0, sc->super->height_in_pixels, 0);
750     glEnd();
751
752     glBindTexture(GL_TEXTURE_2D, 0);
753 }
754
755 static void
756 paint_window(d_window_t *w, data_t *d, window_data_t *wd, int x, int y,
757              GLfloat z)
758 {
759     int i;
760
761     if (!wd->glpixmap)
762         glxrender_update_window_pixmap(w, d, wd);
763     if (wd->waiting_region)
764         glxrender_update_window_region(w, wd);
765
766     if (wd->nrects < 1) return;
767
768     glBindTexture(GL_TEXTURE_2D, wd->texname);
769
770     glBegin(GL_QUADS);
771     for (i = 0; i < wd->nrects * 4; i += 4) {
772         glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
773         glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
774         glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
775         glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
776         glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
777         glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
778         glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
779         glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
780     }
781     glEnd();
782
783     glBindTexture(GL_TEXTURE_2D, 0);
784 }
785
786 static void
787 paint_shadow(data_t *d, window_data_t *wd, int x, int y, GLfloat z)
788 {
789     int i;
790
791     if (wd->nrects < 1) return;
792
793     /* shape the shadow to the window */
794     glBindTexture(GL_TEXTURE_2D, wd->texname);
795
796     x += d->xshadowoff;
797     y += d->yshadowoff;
798
799     glBegin(GL_QUADS);
800     for (i = 0; i < wd->nrects * 4; i += 4) {
801         glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
802         glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
803         glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
804         glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
805         glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
806         glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
807         glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
808         glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
809     }
810     glEnd();
811
812     glBindTexture(GL_TEXTURE_2D, 0);
813 }