14 #include <GL/glxproto.h>
18 #include <GL/glxtokens.h>
20 #include <GL/glxext.h>
31 typedef void (*BindEXTFunc)(Display *, GLXDrawable, int, const int *);
32 typedef void (*ReleaseEXTFunc)(Display *, GLXDrawable, int);
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);
46 GLXFBConfig fbconfig[MAX_DEPTH + 1];
50 GLXPixmap root_glpixmap;
52 BindEXTFunc bind_func;
53 ReleaseEXTFunc release_func;
64 xcb_xfixes_fetch_region_cookie_t ck_region;
73 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
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,
82 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
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,
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);
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);
98 glxrender_init(d_screen_t *sc, int id)
100 static int context_visual_config[] = {
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);
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;
127 d->shadowalpha = 0.2f; /* 20% */
131 vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config);
133 printf("unable to find a valid double buffered GL context to use\n");
137 if (!(glxrender_find_fb_config(sc, d))) {
138 printf("unable to find FB configs\n");
142 d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
143 glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
145 glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
146 glMatrixMode(GL_PROJECTION);
148 glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0,
150 glMatrixMode(GL_MODELVIEW);
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
157 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
158 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
161 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
162 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
164 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
166 d->bind_func = (BindEXTFunc)
167 glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
168 d->release_func = (ReleaseEXTFunc)
169 glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
171 glGenTextures(1, &d->root_texname);
172 d->root_glpixmap = XCB_NONE;
176 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
178 static const int drawable_tfp_attrs[] = {
179 GLX_CONFIG_CAVEAT, GLX_NONE,
180 GLX_DOUBLEBUFFER, FALSE,
186 GLX_RENDER_TYPE, GLX_RGBA_BIT,
187 GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
190 int db, stencil, depth, numfb, i;
192 XVisualInfo tvis, *visinfo;
194 fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num,
195 drawable_tfp_attrs, &numfb);
196 if (!fbcons) return FALSE;
198 for (i = 0; i <= MAX_DEPTH; i++) {
208 //printf("looking for depth %d\n", i);
211 visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
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);
219 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER,
225 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE,
231 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE,
237 /* use this visual */
238 vid = visinfo[j].visualid;
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];
250 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
251 (uint32_t)vid, (uint32_t)fbcons[j], i);
262 glxrender_free(d_screen_t *sc)
264 data_t *d = screen_find_plugin_data(sc, plugin_id);
266 glxrender_free_root_pixmap(sc, d);
267 glXDestroyContext(sc->dpy->xlib_dpy, d->context);
270 screen_remove_plugin_data(sc, plugin_id);
274 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
282 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
288 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
290 glxrender_free_window_pixmap(w, d, wd);
291 glxrender_free_window_region(wd);
292 glDeleteTextures(1, &wd->texname);
297 glxrender_window_show(d_window_t *w)
302 d = screen_find_plugin_data(w->sc, plugin_id);
307 wd = window_find_plugin_data(w, plugin_id);
309 glxrender_window_free_data(w, d, wd);
310 window_remove_plugin_data(w, plugin_id);
313 wd = malloc(sizeof(window_data_t));
314 glGenTextures(1, &wd->texname);
315 wd->glpixmap = XCB_NONE;
316 wd->texcoords = NULL;
319 wd->waiting_region = FALSE;
321 window_add_plugin_data(w, plugin_id, wd);
323 glxrender_fetch_window_region(w, wd);
327 glxrender_window_zombie_dead(d_window_t *w)
332 d = screen_find_plugin_data(w->sc, plugin_id);
333 wd = window_find_plugin_data(w, plugin_id);
335 glxrender_window_free_data(w, d, wd);
336 window_remove_plugin_data(w, plugin_id);
340 d->window_zombie_dead(w);
344 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
346 /* this might cause an error, oh well */
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);
353 glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
354 wd->glpixmap = XCB_NONE;
360 glxrender_free_window_region(window_data_t *wd)
365 wd->texcoords = NULL;
372 glxrender_free_root_pixmap(d_screen_t *sc, data_t *d)
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);
381 glXDestroyPixmap(sc->dpy->xlib_dpy, d->root_glpixmap);
382 d->root_glpixmap = XCB_NONE;
387 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
392 static int attrs[] = {
393 GLX_TEXTURE_FORMAT_EXT,
398 px = window_get_pixmap(w);
399 depth = window_get_depth(w);
403 if (!d->fbconfig[depth]) {
404 printf("no GL visual for depth %d\n", depth);
408 if (window_is_argb(w))
409 attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
411 attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
413 wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
417 wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
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,
427 xcb_generic_error_t *err = xcb_request_check(w->sc->dpy->conn, ck);
429 display_error(w->sc->dpy, err);
431 wd->glpixmap = XCB_NONE;
436 glBindTexture(GL_TEXTURE_2D, wd->texname);
437 d->bind_func(w->sc->dpy->xlib_dpy,
438 wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
443 1 CARD8 opcode (X assigned)
444 1 16 GLX opcode (glXVendorPrivate)
446 4 1330 vendor specific opcode
448 4 GLX_DRAWABLE drawable
450 4 CARD32 num_attributes
451 4*n LISTofATTRIBUTE_PAIR attribute, value pairs.
453 unsigned int len = 12;
459 xcb_glx_vendor_private(w->sc->dpy->conn,
460 X_GLXvop_BindTexImageEXT,
462 len, (uint8_t*)data);
466 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
472 glBindTexture(GL_TEXTURE_2D, 0);
476 glxrender_fetch_window_region(d_window_t *w, window_data_t *wd)
478 window_get_area(w, &wd->x_region, &wd->y_region,
479 &wd->w_region, &wd->h_region, &wd->bw_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);
489 glxrender_update_window_region(d_window_t *w, window_data_t *wd)
491 xcb_xfixes_fetch_region_reply_t *rep;
492 xcb_rectangle_t area, *rects;
495 if (!wd->waiting_region) return;
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;
502 rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, wd->ck_region, NULL);
508 rects = xcb_xfixes_fetch_region_rectangles(rep);
509 nrects = xcb_xfixes_fetch_region_rectangles_length(rep);
512 wd->texcoords = (GLfloat*)realloc(wd->texcoords,
513 sizeof(GLfloat) * (nrects * 4));
514 wd->vertices = (GLint*)realloc(wd->vertices, sizeof(GLint) * (nrects * 4));
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) /
525 wd->texcoords[i+BOTTOM] =
526 (GLfloat)(rects[j].y - area.y + rects[j].height) /
527 (GLfloat)area.height;
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;
538 wd->waiting_region = FALSE;
542 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
545 static int attrs[] = {
546 GLX_TEXTURE_FORMAT_EXT,
547 GLX_TEXTURE_FORMAT_RGB_EXT,
551 px = screen_get_root_pixmap(sc);
554 if (!d->fbconfig[sc->super->root_depth]) {
555 printf("no GL visual for depth %d\n", sc->super->root_depth);
559 d->root_glpixmap = glXCreatePixmap(sc->dpy->xlib_dpy,
560 d->fbconfig[sc->super->root_depth],
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);
568 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
569 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
574 glBindTexture(GL_TEXTURE_2D, 0);
578 glxrender_window_resize(d_window_t *w)
583 d = screen_find_plugin_data(w->sc, plugin_id);
584 wd = window_find_plugin_data(w, plugin_id);
590 glxrender_free_window_pixmap(w, d, wd);
591 glxrender_fetch_window_region(w, wd);
595 glxrender_window_reshape(d_window_t *w)
600 d = screen_find_plugin_data(w->sc, plugin_id);
601 wd = window_find_plugin_data(w, plugin_id);
604 d->window_reshape(w);
607 //glxrender_free_window_pixmap(w, d, wd);
608 glxrender_fetch_window_region(w, wd);
612 glxrender_root_pixmap_change(d_screen_t *sc)
616 d = screen_find_plugin_data(sc, plugin_id);
617 glxrender_free_root_pixmap(sc, d);
620 d->screen_root_pixmap_change(sc);
624 glxrender_paint(d_screen_t *sc)
626 data_t *d = screen_find_plugin_data(sc, plugin_id);
630 //printf("painting\n");
632 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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;
639 if (!window_is_input_only(w) &&
640 (window_is_mapped(w) || window_is_zombie(w)))
642 int x, y, width, height, bwidth;
646 window_get_area(w, &x, &y, &width, &height, &bwidth);
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)))
656 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
659 wd = window_find_plugin_data(w, plugin_id);
663 paint_window(w, d, wd, x, y, z - 0.05f);
675 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
677 for (it = list_bottom(sc->stacking); it; it = it->prev) {
678 d_window_t *w = it->data;
680 if (!window_is_input_only(w) &&
681 (window_is_mapped(w) || window_is_zombie(w)))
683 int x, y, width, height, bwidth;
689 window_get_area(w, &x, &y, &width, &height, &bwidth);
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)))
699 opac = window_get_opacity(w);
700 opaque = !window_is_argb(w) && opac == 0xffff;
702 wd = window_find_plugin_data(w, plugin_id);
707 alpha = d->shadowalpha;
711 glColor4f(0.0f, 0.0f, 0.0f, alpha);
712 paint_shadow(d, wd, x, y, z);
716 glColor4us(opac, opac, opac, opac);
717 paint_window(w, d, wd, x, y, z + 0.05f);
726 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
727 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
730 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
732 /* call the function we replaced in the chain */
737 paint_root(d_screen_t *sc, data_t *d)
739 if (!d->root_glpixmap)
740 glxrender_update_root_pixmap(sc, d);
742 glBindTexture(GL_TEXTURE_2D, d->root_texname);
747 glVertex3i(sc->super->width_in_pixels, 0, 0);
749 glVertex3i(sc->super->width_in_pixels, sc->super->height_in_pixels, 0);
751 glVertex3i(0, sc->super->height_in_pixels, 0);
754 glBindTexture(GL_TEXTURE_2D, 0);
758 paint_window(d_window_t *w, data_t *d, window_data_t *wd, int x, int y,
764 glxrender_update_window_pixmap(w, d, wd);
765 if (wd->waiting_region)
766 glxrender_update_window_region(w, wd);
768 if (wd->nrects < 1) return;
770 glBindTexture(GL_TEXTURE_2D, wd->texname);
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);
785 glBindTexture(GL_TEXTURE_2D, 0);
789 paint_shadow(data_t *d, window_data_t *wd, int x, int y, GLfloat z)
793 if (wd->nrects < 1) return;
795 /* shape the shadow to the window */
796 glBindTexture(GL_TEXTURE_2D, wd->texname);
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);
814 glBindTexture(GL_TEXTURE_2D, 0);