15 #include <GL/glxtokens.h>
17 #include <GL/glxext.h>
23 typedef void (*BindEXTFunc)(Display *, GLXDrawable, int, const int *);
24 typedef void (*ReleaseEXTFunc)(Display *, GLXDrawable, int);
27 void (*screen_paint)(d_screen_t *sc);
28 void (*screen_root_pixmap_change)(d_screen_t *sc);
29 void (*window_show)(d_window_t *w);
30 void (*window_zombie_dead)(d_window_t *w);
31 void (*window_resize)(d_window_t *w);
32 void (*window_reshape)(d_window_t *w);
38 GLXFBConfig fbconfig[MAX_DEPTH + 1];
42 GLXPixmap root_glpixmap;
44 BindEXTFunc bind_func;
45 ReleaseEXTFunc release_func;
53 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
55 static void glxrender_paint(d_screen_t *sc);
56 static void glxrender_root_pixmap_change(d_screen_t *sc);
57 static void paint_root(d_screen_t *sc, data_t *d);
58 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
59 gboolean opaque, int x, int y, int width,
60 int height, int bwidth);
61 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
62 int x, int y, int width, int height, int bwidth);
63 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
65 static void glxrender_free_window_pixmap(d_window_t *w, data_t *d,
67 static void glxrender_free_root_pixmap(d_screen_t *sc, data_t *d);
68 static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
70 static void glxrender_window_show(d_window_t *window);
71 static void glxrender_window_zombie_dead(d_window_t *window);
72 static void glxrender_window_resize(d_window_t *window);
73 static void glxrender_window_reshape(d_window_t *window);
76 glxrender_init(d_screen_t *sc, int id)
78 static int context_visual_config[] = {
89 d = malloc(sizeof(data_t));
90 d->screen_paint = sc->screen_paint;
91 d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
92 d->window_show = sc->window_show;
93 d->window_zombie_dead = sc->window_zombie_dead;
94 d->window_resize = sc->window_resize;
95 d->window_reshape = sc->window_reshape;
96 screen_add_plugin_data(sc, plugin_id, d);
98 sc->screen_paint = glxrender_paint;
99 sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
100 sc->window_show = glxrender_window_show;
101 sc->window_zombie_dead = glxrender_window_zombie_dead;
102 sc->window_resize = glxrender_window_resize;
103 sc->window_reshape = glxrender_window_reshape;
105 d->shadowalpha = 0.2f; /* 20% */
109 vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config);
111 printf("unable to find a valid double buffered GL context to use\n");
115 d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
116 glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
119 if (!(glxrender_find_fb_config(sc, d))) {
120 printf("unable to find FB configs\n");
124 glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
125 glMatrixMode(GL_PROJECTION);
127 glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0,
129 glMatrixMode(GL_MODELVIEW);
131 glEnable(GL_TEXTURE_2D);
133 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
134 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
137 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
138 glClear(GL_COLOR_BUFFER_BIT);
139 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
141 d->bind_func = (BindEXTFunc)
142 glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
143 d->release_func = (ReleaseEXTFunc)
144 glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
146 glGenTextures(1, &d->root_texname);
147 d->root_glpixmap = XCB_NONE;
151 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
153 static const int drawable_tfp_attrs[] = {
154 GLX_CONFIG_CAVEAT, GLX_NONE,
155 GLX_DOUBLEBUFFER, FALSE,
161 GLX_RENDER_TYPE, GLX_RGBA_BIT,
162 GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
165 int db, stencil, depth, numfb, i;
167 XVisualInfo tvis, *visinfo;
169 fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num,
170 drawable_tfp_attrs, &numfb);
171 if (!fbcons) return FALSE;
173 for (i = 0; i <= MAX_DEPTH; i++) {
183 printf("looking for depth %d\n", i);
186 visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
188 /* pick the nicest visual for the depth */
189 for (j = 0; j < count; j++) {
190 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_USE_GL, &value);
194 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER,
200 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE,
206 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE,
212 /* use this visual */
213 vid = visinfo[j].visualid;
218 /* look for an fbconfig for this visual */
219 for (j = 0; j < numfb; ++j) {
220 glXGetFBConfigAttrib(sc->dpy->xlib_dpy, fbcons[j],
221 GLX_VISUAL_ID, &value);
222 if ((unsigned)value == vid) {
223 d->fbconfig[i] = fbcons[j];
225 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
226 (uint32_t)vid, (uint32_t)fbcons[j], i);
237 glxrender_free(d_screen_t *sc)
239 data_t *d = screen_find_plugin_data(sc, plugin_id);
240 glxrender_free_root_pixmap(sc, d);
242 screen_remove_plugin_data(sc, plugin_id);
246 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
254 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
260 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
262 glxrender_free_window_pixmap(w, d, wd);
263 glDeleteTextures(1, &wd->texname);
268 glxrender_window_show(d_window_t *w)
273 d = screen_find_plugin_data(w->sc, plugin_id);
278 wd = window_find_plugin_data(w, plugin_id);
280 glxrender_window_free_data(w, d, wd);
282 wd = malloc(sizeof(window_data_t));
283 glGenTextures(1, &wd->texname);
284 wd->glpixmap = XCB_NONE;
286 window_add_plugin_data(w, plugin_id, wd);
290 glxrender_window_zombie_dead(d_window_t *w)
295 d = screen_find_plugin_data(w->sc, plugin_id);
296 wd = window_find_plugin_data(w, plugin_id);
298 glxrender_window_free_data(w, d, wd);
299 window_remove_plugin_data(w, plugin_id);
303 d->window_zombie_dead(w);
307 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
309 /* this might cause an error, oh well */
311 glBindTexture(GL_TEXTURE_2D, wd->texname);
312 d->release_func(w->sc->dpy->xlib_dpy,
313 wd->glpixmap, GLX_FRONT_LEFT_EXT);
314 glBindTexture(GL_TEXTURE_2D, 0);
316 //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap);
317 glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
318 wd->glpixmap = XCB_NONE;
323 glxrender_free_root_pixmap(d_screen_t *sc, data_t *d)
325 /* this might cause an error, oh well */
326 if (d->root_glpixmap) {
327 glBindTexture(GL_TEXTURE_2D, d->root_texname);
328 d->release_func(sc->dpy->xlib_dpy,
329 d->root_glpixmap, GLX_FRONT_LEFT_EXT);
330 glBindTexture(GL_TEXTURE_2D, 0);
332 //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap);
333 glXDestroyPixmap(sc->dpy->xlib_dpy, d->root_glpixmap);
334 d->root_glpixmap = XCB_NONE;
339 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
344 static int attrs[] = {
345 GLX_TEXTURE_FORMAT_EXT,
350 px = window_get_pixmap(w);
351 depth = window_get_depth(w);
355 if (!d->fbconfig[depth]) {
356 printf("no GL visual for depth %d\n", depth);
360 if (window_is_argb(w))
361 attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
363 attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
365 wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
370 glBindTexture(GL_TEXTURE_2D, wd->texname);
371 d->bind_func(w->sc->dpy->xlib_dpy,
372 wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
378 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
380 glBindTexture(GL_TEXTURE_2D, 0);
384 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
387 static int attrs[] = {
388 GLX_TEXTURE_FORMAT_EXT,
389 GLX_TEXTURE_FORMAT_RGB_EXT,
393 px = screen_get_root_pixmap(sc);
396 if (!d->fbconfig[sc->super->root_depth]) {
397 printf("no GL visual for depth %d\n", sc->super->root_depth);
401 d->root_glpixmap = glXCreatePixmap(sc->dpy->xlib_dpy,
402 d->fbconfig[sc->super->root_depth],
406 glBindTexture(GL_TEXTURE_2D, d->root_texname);
407 d->bind_func(sc->dpy->xlib_dpy,
408 d->root_glpixmap, GLX_FRONT_LEFT_EXT, NULL);
410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
413 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
414 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
416 glBindTexture(GL_TEXTURE_2D, 0);
420 glxrender_window_resize(d_window_t *w)
425 d = screen_find_plugin_data(w->sc, plugin_id);
426 wd = window_find_plugin_data(w, plugin_id);
432 glxrender_free_window_pixmap(w, d, wd);
436 glxrender_window_reshape(d_window_t *w)
441 d = screen_find_plugin_data(w->sc, plugin_id);
442 wd = window_find_plugin_data(w, plugin_id);
445 d->window_reshape(w);
448 glxrender_free_window_pixmap(w, d, wd);
452 glxrender_root_pixmap_change(d_screen_t *sc)
456 d = screen_find_plugin_data(sc, plugin_id);
457 glxrender_free_root_pixmap(sc, d);
460 d->screen_root_pixmap_change(sc);
464 glxrender_paint(d_screen_t *sc)
466 data_t *d = screen_find_plugin_data(sc, plugin_id);
469 //printf("painting\n");
473 for (it = list_bottom(sc->stacking); it; it = it->prev) {
474 d_window_t *w = it->data;
476 if (!window_is_input_only(w) &&
477 (window_is_mapped(w) || window_is_zombie(w)))
479 int x, y, width, height, bwidth;
483 window_get_area(w, &x, &y, &width, &height, &bwidth);
485 if (!(x < sc->super->width_in_pixels &&
486 y < sc->super->height_in_pixels &&
487 (x + width > 0 || x + width + d->xshadowoff > 0) &&
488 (y + height > 0 || y + height + d->yshadowoff > 0)))
493 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
495 wd = window_find_plugin_data(w, plugin_id);
498 glTranslatef(x + d->xshadowoff, y + d->yshadowoff, 0.0f);
500 paint_shadow(w, d, wd, 0, 0, width, height, bwidth);
501 glTranslatef(-d->xshadowoff, -d->yshadowoff, 0.0f);
502 paint_window(w, d, wd, opaque, 0, 0, width, height, bwidth);
508 //xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
509 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
511 /* call the function we replaced in the chain */
516 paint_root(d_screen_t *sc, data_t *d)
518 if (!d->root_glpixmap)
519 glxrender_update_root_pixmap(sc, d);
521 glClear(GL_COLOR_BUFFER_BIT);
523 glBindTexture(GL_TEXTURE_2D, d->root_texname);
527 glVertex2i(sc->super->width_in_pixels, 0);
529 glVertex2i(sc->super->width_in_pixels, sc->super->height_in_pixels);
531 glVertex2i(0, sc->super->height_in_pixels);
535 glBindTexture(GL_TEXTURE_2D, 0);
539 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
540 int x, int y, int width, int height, int bwidth)
542 uint16_t o = window_get_opacity(w);
545 glxrender_update_window_pixmap(w, d, wd);
547 glBindTexture(GL_TEXTURE_2D, wd->texname);
552 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
553 glColor4us(o, o, o, o);
560 glVertex2i(x + width + bwidth, y);
562 glVertex2i(x + width + bwidth,
563 y + height + bwidth);
565 glVertex2i(x, y + height + bwidth);
568 glBindTexture(GL_TEXTURE_2D, 0);
571 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
572 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
578 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
579 int x, int y, int width, int height, int bwidth)
581 float alpha = d->shadowalpha;
583 alpha *= window_get_opacity(w);
586 if (alpha < 0.01) return;
589 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
591 glColor4f(0.0f, 0.0f, 0.0f, alpha);
593 if (window_is_argb(w)) {
594 /* shape the shadow to the window's alpha levels */
595 glBindTexture(GL_TEXTURE_2D, wd->texname);
601 glVertex2i(x + width + bwidth, y);
603 glVertex2i(x + width + bwidth,
604 y + height + bwidth);
606 glVertex2i(x, y + height + bwidth);
609 glBindTexture(GL_TEXTURE_2D, 0);
612 /* draw a solid rectangle */
614 x + width + bwidth - 1, y + height + bwidth - 1);
616 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
617 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);