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