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 gboolean opaque, int x, int y);
69 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
71 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
73 static void glxrender_free_window_pixmap(d_window_t *w, data_t *d,
75 static void glxrender_free_root_pixmap(d_screen_t *sc, data_t *d);
76 static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
78 static void glxrender_window_show(d_window_t *window);
79 static void glxrender_window_zombie_dead(d_window_t *window);
80 static void glxrender_window_resize(d_window_t *window);
81 static void glxrender_window_reshape(d_window_t *window);
84 glxrender_init(d_screen_t *sc, int id)
86 static int context_visual_config[] = {
97 d = malloc(sizeof(data_t));
98 d->screen_paint = sc->screen_paint;
99 d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
100 d->window_show = sc->window_show;
101 d->window_zombie_dead = sc->window_zombie_dead;
102 d->window_resize = sc->window_resize;
103 d->window_reshape = sc->window_reshape;
104 screen_add_plugin_data(sc, plugin_id, d);
106 sc->screen_paint = glxrender_paint;
107 sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
108 sc->window_show = glxrender_window_show;
109 sc->window_zombie_dead = glxrender_window_zombie_dead;
110 sc->window_resize = glxrender_window_resize;
111 sc->window_reshape = glxrender_window_reshape;
113 d->shadowalpha = 0.2f; /* 20% */
117 vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config);
119 printf("unable to find a valid double buffered GL context to use\n");
123 d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
124 glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
127 if (!(glxrender_find_fb_config(sc, d))) {
128 printf("unable to find FB configs\n");
132 glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
133 glMatrixMode(GL_PROJECTION);
135 glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0,
137 glMatrixMode(GL_MODELVIEW);
139 glEnable(GL_TEXTURE_2D);
141 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
142 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
145 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
146 glClear(GL_COLOR_BUFFER_BIT);
147 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
149 d->bind_func = (BindEXTFunc)
150 glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
151 d->release_func = (ReleaseEXTFunc)
152 glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
154 glGenTextures(1, &d->root_texname);
155 d->root_glpixmap = XCB_NONE;
159 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
161 static const int drawable_tfp_attrs[] = {
162 GLX_CONFIG_CAVEAT, GLX_NONE,
163 GLX_DOUBLEBUFFER, FALSE,
169 GLX_RENDER_TYPE, GLX_RGBA_BIT,
170 GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
173 int db, stencil, depth, numfb, i;
175 XVisualInfo tvis, *visinfo;
177 fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num,
178 drawable_tfp_attrs, &numfb);
179 if (!fbcons) return FALSE;
181 for (i = 0; i <= MAX_DEPTH; i++) {
191 printf("looking for depth %d\n", i);
194 visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
196 /* pick the nicest visual for the depth */
197 for (j = 0; j < count; j++) {
198 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_USE_GL, &value);
202 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER,
208 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE,
214 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE,
220 /* use this visual */
221 vid = visinfo[j].visualid;
226 /* look for an fbconfig for this visual */
227 for (j = 0; j < numfb; ++j) {
228 glXGetFBConfigAttrib(sc->dpy->xlib_dpy, fbcons[j],
229 GLX_VISUAL_ID, &value);
230 if ((unsigned)value == vid) {
231 d->fbconfig[i] = fbcons[j];
233 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
234 (uint32_t)vid, (uint32_t)fbcons[j], i);
245 glxrender_free(d_screen_t *sc)
247 data_t *d = screen_find_plugin_data(sc, plugin_id);
248 glxrender_free_root_pixmap(sc, d);
250 screen_remove_plugin_data(sc, plugin_id);
254 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
262 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
268 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
270 glxrender_free_window_pixmap(w, d, wd);
271 glDeleteTextures(1, &wd->texname);
276 glxrender_window_show(d_window_t *w)
281 d = screen_find_plugin_data(w->sc, plugin_id);
286 wd = window_find_plugin_data(w, plugin_id);
288 glxrender_window_free_data(w, d, wd);
290 wd = malloc(sizeof(window_data_t));
291 glGenTextures(1, &wd->texname);
292 wd->glpixmap = XCB_NONE;
295 window_add_plugin_data(w, plugin_id, wd);
297 glxrender_update_window_pixmap(w, d, wd);
301 glxrender_window_zombie_dead(d_window_t *w)
306 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);
314 d->window_zombie_dead(w);
318 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
320 /* this might cause an error, oh well */
322 glBindTexture(GL_TEXTURE_2D, wd->texname);
323 d->release_func(w->sc->dpy->xlib_dpy,
324 wd->glpixmap, GLX_FRONT_LEFT_EXT);
325 glBindTexture(GL_TEXTURE_2D, 0);
327 //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap);
328 glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
329 wd->glpixmap = XCB_NONE;
338 glxrender_free_root_pixmap(d_screen_t *sc, data_t *d)
340 /* this might cause an error, oh well */
341 if (d->root_glpixmap) {
342 glBindTexture(GL_TEXTURE_2D, d->root_texname);
343 d->release_func(sc->dpy->xlib_dpy,
344 d->root_glpixmap, GLX_FRONT_LEFT_EXT);
345 glBindTexture(GL_TEXTURE_2D, 0);
347 //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap);
348 glXDestroyPixmap(sc->dpy->xlib_dpy, d->root_glpixmap);
349 d->root_glpixmap = XCB_NONE;
354 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
359 static int attrs[] = {
360 GLX_TEXTURE_FORMAT_EXT,
365 px = window_get_pixmap(w);
366 depth = window_get_depth(w);
370 if (!d->fbconfig[depth]) {
371 printf("no GL visual for depth %d\n", depth);
375 if (window_is_argb(w))
376 attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
378 attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
380 wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
385 glBindTexture(GL_TEXTURE_2D, wd->texname);
386 d->bind_func(w->sc->dpy->xlib_dpy,
387 wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
390 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
393 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
395 glBindTexture(GL_TEXTURE_2D, 0);
398 int x, y, width, height, bwidth;
400 window_get_area(w, &x, &y, &width, &height, &bwidth);
402 wd->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * 4);
403 wd->texcoords[LEFT] = 0.0f;
404 wd->texcoords[TOP] = 0.0f;
405 wd->texcoords[RIGHT] = 1.0f;
406 wd->texcoords[BOTTOM] = 1.0f;
408 wd->vertices = (GLint*)malloc(sizeof(GLint) * 4);
409 wd->vertices[LEFT] = 0;
410 wd->vertices[TOP] = 0;
411 wd->vertices[RIGHT] = width + bwidth;
412 wd->vertices[BOTTOM] = height + bwidth;
419 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
422 static int attrs[] = {
423 GLX_TEXTURE_FORMAT_EXT,
424 GLX_TEXTURE_FORMAT_RGB_EXT,
428 px = screen_get_root_pixmap(sc);
431 if (!d->fbconfig[sc->super->root_depth]) {
432 printf("no GL visual for depth %d\n", sc->super->root_depth);
436 d->root_glpixmap = glXCreatePixmap(sc->dpy->xlib_dpy,
437 d->fbconfig[sc->super->root_depth],
441 glBindTexture(GL_TEXTURE_2D, d->root_texname);
442 d->bind_func(sc->dpy->xlib_dpy,
443 d->root_glpixmap, GLX_FRONT_LEFT_EXT, NULL);
445 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
446 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
451 glBindTexture(GL_TEXTURE_2D, 0);
455 glxrender_window_resize(d_window_t *w)
460 d = screen_find_plugin_data(w->sc, plugin_id);
461 wd = window_find_plugin_data(w, plugin_id);
467 glxrender_free_window_pixmap(w, d, wd);
468 glxrender_update_window_pixmap(w, d, wd);
472 glxrender_window_reshape(d_window_t *w)
477 d = screen_find_plugin_data(w->sc, plugin_id);
478 wd = window_find_plugin_data(w, plugin_id);
481 d->window_reshape(w);
484 glxrender_free_window_pixmap(w, d, wd);
485 glxrender_update_window_pixmap(w, d, wd);
489 glxrender_root_pixmap_change(d_screen_t *sc)
493 d = screen_find_plugin_data(sc, plugin_id);
494 glxrender_free_root_pixmap(sc, d);
497 d->screen_root_pixmap_change(sc);
501 glxrender_paint(d_screen_t *sc)
503 data_t *d = screen_find_plugin_data(sc, plugin_id);
506 //printf("painting\n");
510 for (it = list_bottom(sc->stacking); it; it = it->prev) {
511 d_window_t *w = it->data;
513 if (!window_is_input_only(w) &&
514 (window_is_mapped(w) || window_is_zombie(w)))
516 int x, y, width, height, bwidth;
520 window_get_area(w, &x, &y, &width, &height, &bwidth);
522 if (!(x < sc->super->width_in_pixels &&
523 y < sc->super->height_in_pixels &&
524 (x + width > 0 || x + width + d->xshadowoff > 0) &&
525 (y + height > 0 || y + height + d->yshadowoff > 0)))
530 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
532 wd = window_find_plugin_data(w, plugin_id);
536 glTranslatef(d->xshadowoff, d->yshadowoff, 0.0f);
537 paint_shadow(w, d, wd, x, y);
539 glTranslatef(-d->xshadowoff, -d->yshadowoff, 0.0f);
540 paint_window(w, d, wd, opaque, x, y);
546 //xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
547 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
549 /* call the function we replaced in the chain */
554 paint_root(d_screen_t *sc, data_t *d)
556 if (!d->root_glpixmap)
557 glxrender_update_root_pixmap(sc, d);
559 glClear(GL_COLOR_BUFFER_BIT);
561 glBindTexture(GL_TEXTURE_2D, d->root_texname);
566 glVertex2i(sc->super->width_in_pixels, 0);
568 glVertex2i(sc->super->width_in_pixels, sc->super->height_in_pixels);
570 glVertex2i(0, sc->super->height_in_pixels);
573 glBindTexture(GL_TEXTURE_2D, 0);
577 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
580 uint16_t o = window_get_opacity(w);
584 glxrender_update_window_pixmap(w, d, wd);
586 if (wd->nrects < 1) return;
588 glBindTexture(GL_TEXTURE_2D, wd->texname);
593 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
594 glColor4us(o, o, o, o);
598 for (i = 0; i < wd->nrects * 4; i += 4) {
599 // XXX use glVertex3i
600 glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
601 glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+TOP]);
602 glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
603 glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+TOP]);
604 glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
605 glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+BOTTOM]);
606 glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
607 glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+BOTTOM]);
611 glBindTexture(GL_TEXTURE_2D, 0);
614 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
615 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
621 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd, int x, int y)
623 float alpha = d->shadowalpha;
626 if (wd->nrects < 1) return;
628 alpha *= window_get_opacity(w);
631 if (alpha < 0.01) return;
634 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
636 glColor4f(0.0f, 0.0f, 0.0f, alpha);
638 /* shape the shadow to the window */
639 glBindTexture(GL_TEXTURE_2D, wd->texname);
642 for (i = 0; i < wd->nrects * 4; i += 4) {
643 glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]);
644 glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+TOP]);
645 glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]);
646 glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+TOP]);
647 glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]);
648 glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+BOTTOM]);
649 glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]);
650 glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+BOTTOM]);
654 glBindTexture(GL_TEXTURE_2D, 0);
656 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
657 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);