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);
33 typedef int (*SwapIntervalSGIFunc)(int);
36 void (*screen_paint)(d_screen_t *sc);
37 void (*screen_root_pixmap_change)(d_screen_t *sc);
38 void (*window_show)(d_window_t *w);
39 void (*window_zombie_dead)(d_window_t *w);
40 void (*window_resize)(d_window_t *w);
41 void (*window_reshape)(d_window_t *w);
47 GLXFBConfig fbconfig[MAX_DEPTH + 1];
51 GLXPixmap root_glpixmap;
53 BindEXTFunc bind_func;
54 ReleaseEXTFunc release_func;
65 xcb_xfixes_fetch_region_cookie_t ck_region;
74 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
76 static void glxrender_paint(d_screen_t *sc);
77 static void glxrender_root_pixmap_change(d_screen_t *sc);
78 static void paint_root(d_screen_t *sc, data_t *d);
79 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
80 int x, int y, GLfloat z);
81 static void paint_shadow(data_t *d, window_data_t *wd, int x, int y,
83 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
85 static void glxrender_fetch_window_region(d_window_t *w, window_data_t *wd);
86 static void glxrender_update_window_region(d_window_t *w, window_data_t *wd);
87 static void glxrender_free_window_pixmap(d_window_t *w, data_t *d,
89 static void glxrender_free_window_region(window_data_t *wd);
90 static void glxrender_free_root_pixmap(d_screen_t *sc, data_t *d);
91 static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
93 static void glxrender_window_show(d_window_t *window);
94 static void glxrender_window_zombie_dead(d_window_t *window);
95 static void glxrender_window_resize(d_window_t *window);
96 static void glxrender_window_reshape(d_window_t *window);
99 glxrender_init(d_screen_t *sc, int id)
101 static int context_visual_config[] = {
112 d = malloc(sizeof(data_t));
113 d->screen_paint = sc->screen_paint;
114 d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
115 d->window_show = sc->window_show;
116 d->window_zombie_dead = sc->window_zombie_dead;
117 d->window_resize = sc->window_resize;
118 d->window_reshape = sc->window_reshape;
119 screen_add_plugin_data(sc, plugin_id, d);
121 sc->screen_paint = glxrender_paint;
122 sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
123 sc->window_show = glxrender_window_show;
124 sc->window_zombie_dead = glxrender_window_zombie_dead;
125 sc->window_resize = glxrender_window_resize;
126 sc->window_reshape = glxrender_window_reshape;
128 d->shadowalpha = 0.2f; /* 20% */
132 vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config);
134 printf("unable to find a valid double buffered GL context to use\n");
138 if (!(glxrender_find_fb_config(sc, d))) {
139 printf("unable to find FB configs\n");
143 d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
144 glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
146 glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
147 glMatrixMode(GL_PROJECTION);
149 glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0,
151 glMatrixMode(GL_MODELVIEW);
153 glEnable(GL_TEXTURE_2D);
154 glEnable(GL_DEPTH_TEST);
155 //glEnable(GL_SCISSOR_TEST); ?? what is this, glxcompmgr enables it
156 //glEnable(GL_STENCIL_TEST); ?? what is this, glxcompmgr enables it
158 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
159 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
162 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
163 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
165 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
167 d->bind_func = (BindEXTFunc)
168 glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
169 d->release_func = (ReleaseEXTFunc)
170 glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
172 SwapIntervalSGIFunc swap_interval_func = (SwapIntervalSGIFunc)
173 glXGetProcAddress((const guchar*)"glXSwapIntervalSGI");
174 if(swap_interval_func)
175 swap_interval_func(1);
177 glGenTextures(1, &d->root_texname);
178 d->root_glpixmap = XCB_NONE;
182 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
184 static const int drawable_tfp_attrs[] = {
185 GLX_CONFIG_CAVEAT, GLX_NONE,
186 GLX_DOUBLEBUFFER, FALSE,
192 GLX_RENDER_TYPE, GLX_RGBA_BIT,
193 GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
196 int db, stencil, depth, numfb, i;
198 XVisualInfo tvis, *visinfo;
200 fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num,
201 drawable_tfp_attrs, &numfb);
202 if (!fbcons) return FALSE;
204 for (i = 0; i <= MAX_DEPTH; i++) {
214 //printf("looking for depth %d\n", i);
217 visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
219 /* pick the nicest visual for the depth */
220 for (j = 0; j < count; j++) {
221 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_USE_GL, &value);
225 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER,
231 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE,
237 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE,
243 /* use this visual */
244 vid = visinfo[j].visualid;
249 /* look for an fbconfig for this visual */
250 for (j = 0; j < numfb; ++j) {
251 glXGetFBConfigAttrib(sc->dpy->xlib_dpy, fbcons[j],
252 GLX_VISUAL_ID, &value);
253 if ((unsigned)value == vid) {
254 d->fbconfig[i] = fbcons[j];
256 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
257 (uint32_t)vid, (uint32_t)fbcons[j], i);
268 glxrender_free(d_screen_t *sc)
270 data_t *d = screen_find_plugin_data(sc, plugin_id);
272 glxrender_free_root_pixmap(sc, d);
273 glXDestroyContext(sc->dpy->xlib_dpy, d->context);
276 screen_remove_plugin_data(sc, plugin_id);
280 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
288 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
294 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
296 glxrender_free_window_pixmap(w, d, wd);
297 glxrender_free_window_region(wd);
298 glDeleteTextures(1, &wd->texname);
303 glxrender_window_show(d_window_t *w)
308 d = screen_find_plugin_data(w->sc, plugin_id);
313 wd = window_find_plugin_data(w, plugin_id);
315 glxrender_window_free_data(w, d, wd);
316 window_remove_plugin_data(w, plugin_id);
319 wd = malloc(sizeof(window_data_t));
320 glGenTextures(1, &wd->texname);
321 wd->glpixmap = XCB_NONE;
322 wd->texcoords = NULL;
325 wd->waiting_region = FALSE;
327 window_add_plugin_data(w, plugin_id, wd);
329 glxrender_fetch_window_region(w, wd);
333 glxrender_window_zombie_dead(d_window_t *w)
338 d = screen_find_plugin_data(w->sc, plugin_id);
339 wd = window_find_plugin_data(w, plugin_id);
341 glxrender_window_free_data(w, d, wd);
342 window_remove_plugin_data(w, plugin_id);
346 d->window_zombie_dead(w);
350 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
352 /* this might cause an error, oh well */
354 glBindTexture(GL_TEXTURE_2D, wd->texname);
355 d->release_func(w->sc->dpy->xlib_dpy,
356 wd->glpixmap, GLX_FRONT_LEFT_EXT);
357 glBindTexture(GL_TEXTURE_2D, 0);
359 glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
360 wd->glpixmap = XCB_NONE;
366 glxrender_free_window_region(window_data_t *wd)
371 wd->texcoords = NULL;
378 glxrender_free_root_pixmap(d_screen_t *sc, data_t *d)
380 /* this might cause an error, oh well */
381 if (d->root_glpixmap) {
382 glBindTexture(GL_TEXTURE_2D, d->root_texname);
383 d->release_func(sc->dpy->xlib_dpy,
384 d->root_glpixmap, GLX_FRONT_LEFT_EXT);
385 glBindTexture(GL_TEXTURE_2D, 0);
387 glXDestroyPixmap(sc->dpy->xlib_dpy, d->root_glpixmap);
388 d->root_glpixmap = XCB_NONE;
393 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
398 static int attrs[] = {
399 GLX_TEXTURE_FORMAT_EXT,
404 px = window_get_pixmap(w);
405 depth = window_get_depth(w);
409 if (!d->fbconfig[depth]) {
410 printf("no GL visual for depth %d\n", depth);
414 if (window_is_argb(w))
415 attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
417 attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
419 wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
423 wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
425 glXGetFBConfigAttrib(w->sc->dpy->xlib_dpy, d->fbconfig[depth],
426 GLX_FBCONFIG_ID, &v);
427 xcb_void_cookie_t ck =
428 xcb_glx_create_pixmap_checked(w->sc->dpy->conn, w->sc->num,
433 xcb_generic_error_t *err = xcb_request_check(w->sc->dpy->conn, ck);
435 display_error(w->sc->dpy, err);
437 wd->glpixmap = XCB_NONE;
442 glBindTexture(GL_TEXTURE_2D, wd->texname);
443 d->bind_func(w->sc->dpy->xlib_dpy,
444 wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
449 1 CARD8 opcode (X assigned)
450 1 16 GLX opcode (glXVendorPrivate)
452 4 1330 vendor specific opcode
454 4 GLX_DRAWABLE drawable
456 4 CARD32 num_attributes
457 4*n LISTofATTRIBUTE_PAIR attribute, value pairs.
459 unsigned int len = 12;
465 xcb_glx_vendor_private(w->sc->dpy->conn,
466 X_GLXvop_BindTexImageEXT,
468 len, (uint8_t*)data);
472 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
475 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
476 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
478 glBindTexture(GL_TEXTURE_2D, 0);
482 glxrender_fetch_window_region(d_window_t *w, window_data_t *wd)
484 window_get_area(w, &wd->x_region, &wd->y_region,
485 &wd->w_region, &wd->h_region, &wd->bw_region);
488 xcb_xfixes_fetch_region_unchecked(w->sc->dpy->conn,
489 window_get_region(w));
490 wd->waiting_region = TRUE;
491 xcb_flush(w->sc->dpy->conn);
495 glxrender_update_window_region(d_window_t *w, window_data_t *wd)
497 xcb_xfixes_fetch_region_reply_t *rep;
498 xcb_rectangle_t area, *rects;
501 if (!wd->waiting_region) return;
503 area.x = wd->x_region;
504 area.y = wd->y_region;
505 area.width = wd->w_region + wd->bw_region * 2;
506 area.height = wd->h_region + wd->bw_region * 2;
508 rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, wd->ck_region, NULL);
514 rects = xcb_xfixes_fetch_region_rectangles(rep);
515 nrects = xcb_xfixes_fetch_region_rectangles_length(rep);
518 wd->texcoords = (GLfloat*)realloc(wd->texcoords,
519 sizeof(GLfloat) * (nrects * 4));
520 wd->vertices = (GLint*)realloc(wd->vertices, sizeof(GLint) * (nrects * 4));
523 for (i = j = 0; i < nrects * 4; ++j, i += 4) {
524 wd->texcoords[i+LEFT] =
525 (GLfloat)(rects[j].x - area.x) / (GLfloat)area.width;
526 wd->texcoords[i+TOP] =
527 (GLfloat)(rects[j].y - area.y) / (GLfloat)area.height;
528 wd->texcoords[i+RIGHT] =
529 (GLfloat)(rects[j].x - area.x + rects[j].width) /
531 wd->texcoords[i+BOTTOM] =
532 (GLfloat)(rects[j].y - area.y + rects[j].height) /
533 (GLfloat)area.height;
535 wd->vertices[i+LEFT] = rects[j].x - area.x;
536 wd->vertices[i+TOP] = rects[j].y - area.y;
537 wd->vertices[i+RIGHT] = rects[j].x - area.x + rects[j].width;
538 wd->vertices[i+BOTTOM] = rects[j].y - area.y + rects[j].height;
544 wd->waiting_region = FALSE;
548 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
551 static int attrs[] = {
552 GLX_TEXTURE_FORMAT_EXT,
553 GLX_TEXTURE_FORMAT_RGB_EXT,
557 px = screen_get_root_pixmap(sc);
560 if (!d->fbconfig[sc->super->root_depth]) {
561 printf("no GL visual for depth %d\n", sc->super->root_depth);
565 d->root_glpixmap = glXCreatePixmap(sc->dpy->xlib_dpy,
566 d->fbconfig[sc->super->root_depth],
570 glBindTexture(GL_TEXTURE_2D, d->root_texname);
571 d->bind_func(sc->dpy->xlib_dpy,
572 d->root_glpixmap, GLX_FRONT_LEFT_EXT, NULL);
574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
577 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
578 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
580 glBindTexture(GL_TEXTURE_2D, 0);
584 glxrender_window_resize(d_window_t *w)
589 d = screen_find_plugin_data(w->sc, plugin_id);
590 wd = window_find_plugin_data(w, plugin_id);
596 glxrender_free_window_pixmap(w, d, wd);
597 glxrender_fetch_window_region(w, wd);
601 glxrender_window_reshape(d_window_t *w)
606 d = screen_find_plugin_data(w->sc, plugin_id);
607 wd = window_find_plugin_data(w, plugin_id);
610 d->window_reshape(w);
613 //glxrender_free_window_pixmap(w, d, wd);
614 glxrender_fetch_window_region(w, wd);
618 glxrender_root_pixmap_change(d_screen_t *sc)
622 d = screen_find_plugin_data(sc, plugin_id);
623 glxrender_free_root_pixmap(sc, d);
626 d->screen_root_pixmap_change(sc);
630 glxrender_paint(d_screen_t *sc)
632 data_t *d = screen_find_plugin_data(sc, plugin_id);
636 //printf("painting\n");
638 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
640 /* add 0.1f to keep everything above the root */
641 z = list_length(sc->stacking) * 0.1f + 0.1f;
642 for (it = list_top(sc->stacking); it; it = it->next) {
643 d_window_t *w = it->data;
645 if (!window_is_input_only(w) &&
646 (window_is_mapped(w) || window_is_zombie(w)))
648 int x, y, width, height, bwidth;
652 window_get_area(w, &x, &y, &width, &height, &bwidth);
654 if (!(x < sc->super->width_in_pixels &&
655 y < sc->super->height_in_pixels &&
656 (x + width > 0 || x + width + d->xshadowoff > 0) &&
657 (y + height > 0 || y + height + d->yshadowoff > 0)))
662 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
665 wd = window_find_plugin_data(w, plugin_id);
669 paint_window(w, d, wd, x, y, z - 0.05f);
681 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
683 for (it = list_bottom(sc->stacking); it; it = it->prev) {
684 d_window_t *w = it->data;
686 if (!window_is_input_only(w) &&
687 (window_is_mapped(w) || window_is_zombie(w)))
689 int x, y, width, height, bwidth;
695 window_get_area(w, &x, &y, &width, &height, &bwidth);
697 if (!(x < sc->super->width_in_pixels &&
698 y < sc->super->height_in_pixels &&
699 (x + width > 0 || x + width + d->xshadowoff > 0) &&
700 (y + height > 0 || y + height + d->yshadowoff > 0)))
705 opac = window_get_opacity(w);
706 opaque = !window_is_argb(w) && opac == 0xffff;
708 wd = window_find_plugin_data(w, plugin_id);
711 alpha = d->shadowalpha;
715 glColor4f(0.0f, 0.0f, 0.0f, alpha);
716 paint_shadow(d, wd, x, y, z);
720 glColor4us(opac, opac, opac, opac);
721 paint_window(w, d, wd, x, y, z + 0.05f);
728 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
729 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
732 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
736 /* call the function we replaced in the chain */
741 paint_root(d_screen_t *sc, data_t *d)
743 if (!d->root_glpixmap)
744 glxrender_update_root_pixmap(sc, d);
746 glBindTexture(GL_TEXTURE_2D, d->root_texname);
751 glVertex3i(sc->super->width_in_pixels, 0, 0);
753 glVertex3i(sc->super->width_in_pixels, sc->super->height_in_pixels, 0);
755 glVertex3i(0, sc->super->height_in_pixels, 0);
758 glBindTexture(GL_TEXTURE_2D, 0);
762 paint_window(d_window_t *w, data_t *d, window_data_t *wd, int x, int y,
768 glxrender_update_window_pixmap(w, d, wd);
769 if (wd->waiting_region)
770 glxrender_update_window_region(w, wd);
772 if (wd->nrects < 1) return;
774 glBindTexture(GL_TEXTURE_2D, wd->texname);
777 for (i = 0; i < wd->nrects * 4; i += 4) {
778 glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
779 glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
780 glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
781 glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
782 glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
783 glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
784 glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
785 glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
789 glBindTexture(GL_TEXTURE_2D, 0);
793 paint_shadow(data_t *d, window_data_t *wd, int x, int y, GLfloat z)
797 if (wd->nrects < 1) return;
799 /* shape the shadow to the window */
800 glBindTexture(GL_TEXTURE_2D, wd->texname);
806 for (i = 0; i < wd->nrects * 4; i += 4) {
807 glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
808 glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+TOP], z);
809 glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
810 glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+TOP], z);
811 glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
812 glVertex3f(x+wd->vertices[i+RIGHT], y+wd->vertices[i+BOTTOM], z);
813 glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
814 glVertex3f(x+wd->vertices[i+LEFT], y+wd->vertices[i+BOTTOM], z);
818 glBindTexture(GL_TEXTURE_2D, 0);