15 #include <GL/glxtokens.h>
17 #include <GL/glxext.h>
28 typedef void (*BindEXTFunc)(Display *, GLXDrawable, int, const int *);
29 typedef void (*ReleaseEXTFunc)(Display *, GLXDrawable, int);
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);
43 GLXFBConfig fbconfig[MAX_DEPTH + 1];
47 GLXPixmap root_glpixmap;
49 BindEXTFunc bind_func;
50 ReleaseEXTFunc release_func;
62 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
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,
71 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
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,
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);
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);
85 glxrender_init(d_screen_t *sc, int id)
87 static int context_visual_config[] = {
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);
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;
114 d->shadowalpha = 0.2f; /* 20% */
118 vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config);
120 printf("unable to find a valid double buffered GL context to use\n");
124 d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
125 glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
128 if (!(glxrender_find_fb_config(sc, d))) {
129 printf("unable to find FB configs\n");
133 glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
134 glMatrixMode(GL_PROJECTION);
136 glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0,
138 glMatrixMode(GL_MODELVIEW);
140 glEnable(GL_TEXTURE_2D);
141 glEnable(GL_DEPTH_TEST);
143 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
144 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
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);
151 d->bind_func = (BindEXTFunc)
152 glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
153 d->release_func = (ReleaseEXTFunc)
154 glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
156 glGenTextures(1, &d->root_texname);
157 d->root_glpixmap = XCB_NONE;
161 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
163 static const int drawable_tfp_attrs[] = {
164 GLX_CONFIG_CAVEAT, GLX_NONE,
165 GLX_DOUBLEBUFFER, FALSE,
171 GLX_RENDER_TYPE, GLX_RGBA_BIT,
172 GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
175 int db, stencil, depth, numfb, i;
177 XVisualInfo tvis, *visinfo;
179 fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num,
180 drawable_tfp_attrs, &numfb);
181 if (!fbcons) return FALSE;
183 for (i = 0; i <= MAX_DEPTH; i++) {
193 printf("looking for depth %d\n", i);
196 visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
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);
204 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER,
210 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE,
216 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE,
222 /* use this visual */
223 vid = visinfo[j].visualid;
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];
235 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
236 (uint32_t)vid, (uint32_t)fbcons[j], i);
247 glxrender_free(d_screen_t *sc)
249 data_t *d = screen_find_plugin_data(sc, plugin_id);
251 glxrender_free_root_pixmap(sc, d);
254 screen_remove_plugin_data(sc, plugin_id);
258 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
266 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
272 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
274 glxrender_free_window_pixmap(w, d, wd);
275 glDeleteTextures(1, &wd->texname);
280 glxrender_window_show(d_window_t *w)
285 d = screen_find_plugin_data(w->sc, plugin_id);
290 wd = window_find_plugin_data(w, plugin_id);
292 glxrender_window_free_data(w, d, wd);
294 wd = malloc(sizeof(window_data_t));
295 glGenTextures(1, &wd->texname);
296 wd->glpixmap = XCB_NONE;
299 window_add_plugin_data(w, plugin_id, wd);
301 glxrender_update_window_pixmap(w, d, wd);
305 glxrender_window_zombie_dead(d_window_t *w)
310 d = screen_find_plugin_data(w->sc, plugin_id);
311 wd = window_find_plugin_data(w, plugin_id);
313 glxrender_window_free_data(w, d, wd);
314 window_remove_plugin_data(w, plugin_id);
318 d->window_zombie_dead(w);
322 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
324 /* this might cause an error, oh well */
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);
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;
344 glxrender_free_root_pixmap(d_screen_t *sc, data_t *d)
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);
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;
360 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
365 static int attrs[] = {
366 GLX_TEXTURE_FORMAT_EXT,
371 px = window_get_pixmap(w);
372 depth = window_get_depth(w);
376 if (!d->fbconfig[depth]) {
377 printf("no GL visual for depth %d\n", depth);
381 if (window_is_argb(w))
382 attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
384 attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
386 wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
391 glBindTexture(GL_TEXTURE_2D, wd->texname);
392 d->bind_func(w->sc->dpy->xlib_dpy,
393 wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
395 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
396 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
401 glBindTexture(GL_TEXTURE_2D, 0);
403 glxrender_update_window_region(w, wd);
407 glxrender_update_window_region(d_window_t *w, window_data_t *wd)
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;
415 reg = window_get_region(w);
416 ck = xcb_xfixes_fetch_region_unchecked(w->sc->dpy->conn, reg);
418 window_get_area(w, &x, &y, &wid, &hei, &bwid);
421 area.width = wid + bwid * 2;
422 area.height = hei + bwid * 2;
424 rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, ck, NULL);
430 rects = xcb_xfixes_fetch_region_rectangles(rep);
431 nrects = xcb_xfixes_fetch_region_rectangles_length(rep);
434 wd->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * (nrects * 4));
435 wd->vertices = (GLint*)malloc(sizeof(GLint) * (nrects * 4));
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) /
446 wd->texcoords[i+BOTTOM] =
447 (GLfloat)(rects[i].y - area.y + rects[i].height) /
448 (GLfloat)area.height;
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;
461 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
464 static int attrs[] = {
465 GLX_TEXTURE_FORMAT_EXT,
466 GLX_TEXTURE_FORMAT_RGB_EXT,
470 px = screen_get_root_pixmap(sc);
473 if (!d->fbconfig[sc->super->root_depth]) {
474 printf("no GL visual for depth %d\n", sc->super->root_depth);
478 d->root_glpixmap = glXCreatePixmap(sc->dpy->xlib_dpy,
479 d->fbconfig[sc->super->root_depth],
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);
487 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
488 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
493 glBindTexture(GL_TEXTURE_2D, 0);
497 glxrender_window_resize(d_window_t *w)
502 d = screen_find_plugin_data(w->sc, plugin_id);
503 wd = window_find_plugin_data(w, plugin_id);
509 glxrender_free_window_pixmap(w, d, wd);
510 glxrender_update_window_pixmap(w, d, wd);
514 glxrender_window_reshape(d_window_t *w)
519 d = screen_find_plugin_data(w->sc, plugin_id);
520 wd = window_find_plugin_data(w, plugin_id);
523 d->window_reshape(w);
526 glxrender_free_window_pixmap(w, d, wd);
527 glxrender_update_window_pixmap(w, d, wd);
531 glxrender_root_pixmap_change(d_screen_t *sc)
535 d = screen_find_plugin_data(sc, plugin_id);
536 glxrender_free_root_pixmap(sc, d);
539 d->screen_root_pixmap_change(sc);
543 glxrender_paint(d_screen_t *sc)
545 data_t *d = screen_find_plugin_data(sc, plugin_id);
549 //printf("painting\n");
551 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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;
558 if (!window_is_input_only(w) &&
559 (window_is_mapped(w) || window_is_zombie(w)))
561 int x, y, width, height, bwidth;
565 window_get_area(w, &x, &y, &width, &height, &bwidth);
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)))
575 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
578 wd = window_find_plugin_data(w, plugin_id);
582 paint_window(w, d, wd, x, y, z - 0.05f);
594 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
596 for (it = list_bottom(sc->stacking); it; it = it->prev) {
597 d_window_t *w = it->data;
599 if (!window_is_input_only(w) &&
600 (window_is_mapped(w) || window_is_zombie(w)))
602 int x, y, width, height, bwidth;
608 window_get_area(w, &x, &y, &width, &height, &bwidth);
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)))
618 opac = window_get_opacity(w);
619 opaque = !window_is_argb(w) && opac == 0xffff;
621 wd = window_find_plugin_data(w, plugin_id);
626 alpha = d->shadowalpha;
630 glColor4f(0.0f, 0.0f, 0.0f, alpha);
631 paint_shadow(d, wd, x, y, z);
635 glColor4us(opac, opac, opac, opac);
636 paint_window(w, d, wd, x, y, z + 0.05f);
645 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
646 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
649 //xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
650 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
652 /* call the function we replaced in the chain */
657 paint_root(d_screen_t *sc, data_t *d)
659 if (!d->root_glpixmap)
660 glxrender_update_root_pixmap(sc, d);
662 glBindTexture(GL_TEXTURE_2D, d->root_texname);
667 glVertex3i(sc->super->width_in_pixels, 0, 0);
669 glVertex3i(sc->super->width_in_pixels, sc->super->height_in_pixels, 0);
671 glVertex3i(0, sc->super->height_in_pixels, 0);
674 glBindTexture(GL_TEXTURE_2D, 0);
678 paint_window(d_window_t *w, data_t *d, window_data_t *wd, int x, int y,
684 glxrender_update_window_pixmap(w, d, wd);
686 if (wd->nrects < 1) return;
688 glBindTexture(GL_TEXTURE_2D, wd->texname);
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);
703 glBindTexture(GL_TEXTURE_2D, 0);
707 paint_shadow(data_t *d, window_data_t *wd, int x, int y, GLfloat z)
711 if (wd->nrects < 1) return;
713 /* shape the shadow to the window */
714 glBindTexture(GL_TEXTURE_2D, wd->texname);
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);
732 glBindTexture(GL_TEXTURE_2D, 0);