13 //#include <GL/glext.h>
14 //#include <GL/glxext.h>
15 #include <GL/glxtokens.h>
23 void (*screen_paint)(d_screen_t *sc);
24 void (*screen_root_pixmap_change)(d_screen_t *sc);
25 void (*window_show)(d_window_t *w);
26 void (*window_zombie_dead)(d_window_t *w);
27 void (*window_resize)(d_window_t *w);
28 void (*window_reshape)(d_window_t *w);
34 uint32_t fbconfig[MAX_DEPTH + 1];
36 xcb_glx_context_t context;
37 xcb_glx_context_tag_t context_tag;
42 xcb_glx_pixmap_t glpixmap;
45 static uint32_t glxrender_visual_info(uint32_t *props, int vis, int numprops,
47 static gboolean glxrender_check_visual(d_screen_t *sc);
48 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
50 static void glxrender_paint(d_screen_t *sc);
51 static void glxrender_root_pixmap_change(d_screen_t *sc);
52 static void paint_root(d_screen_t *sc, data_t *d);
53 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
54 gboolean opaque, int x, int y, int width,
55 int height, int bwidth);
56 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
57 int x, int y, int width, int height, int bwidth);
58 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
60 static void glxrender_free_window_pixmap(d_window_t *w, window_data_t *wd);
61 static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
63 static void glxrender_window_show(d_window_t *window);
64 static void glxrender_window_zombie_dead(d_window_t *window);
65 static void glxrender_window_resize(d_window_t *window);
66 static void glxrender_window_reshape(d_window_t *window);
69 glxrender_init(d_screen_t *sc, int id)
72 xcb_generic_error_t *err;
73 xcb_glx_make_current_cookie_t curck;
74 xcb_glx_make_current_reply_t *currep;
78 data_t *d = malloc(sizeof(data_t));
79 d->screen_paint = sc->screen_paint;
80 d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
81 d->window_show = sc->window_show;
82 d->window_zombie_dead = sc->window_zombie_dead;
83 d->window_resize = sc->window_resize;
84 d->window_reshape = sc->window_reshape;
85 screen_add_plugin_data(sc, plugin_id, d);
87 sc->screen_paint = glxrender_paint;
88 sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
89 sc->window_show = glxrender_window_show;
90 sc->window_zombie_dead = glxrender_window_zombie_dead;
91 sc->window_resize = glxrender_window_resize;
92 sc->window_reshape = glxrender_window_reshape;
94 d->shadowalpha = 0x3333; /* 20% */
98 if (!glxrender_check_visual(sc)) {
99 printf("unable to use the overlay window for GLX\n");
103 if (!(glxrender_find_fb_config(sc, d))) {
104 printf("unable to find FB configs\n");
108 d->context = xcb_generate_id(sc->dpy->conn);
109 ck = xcb_glx_create_context_checked(sc->dpy->conn, d->context,
110 sc->overlay_visual, sc->num,
112 if ((err = xcb_request_check(sc->dpy->conn, ck))) {
113 printf("context creation failed\n");
114 display_error(sc->dpy, err);
119 curck = xcb_glx_make_current(sc->dpy->conn,
120 sc->overlay, d->context, XCB_NONE);
121 currep = xcb_glx_make_current_reply(sc->dpy->conn, curck, &err);
124 display_error(sc->dpy, err);
127 printf("make current failed\n");
130 d->context_tag = currep->context_tag;
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,
138 glMatrixMode(GL_MODELVIEW);
140 glClear(GL_COLOR_BUFFER_BIT);
141 glEnable(GL_TEXTURE_2D);
142 xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
143 glClearColor(0.4, 0.4, 0.4, 1.0);
146 glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
152 glxrender_visual_info(uint32_t *props, int vis, int numprops, uint32_t name)
156 assert(numprops > 14);
159 for (s = vis * numprops; s < vis*numprops + numprops; ++s)
160 printf("%x ", props[s]);
166 case GLX_VISUAL_ID: return props[s+0]; /* id number */
167 case GLX_X_VISUAL_TYPE: return props[s+1]; /* XCB_CLASS_TRUE_COLOR etc */
168 case GLX_USE_GL: return props[s+2]; /* boolean */
169 case GLX_RED_SIZE: return props[s+3]; /* number */
170 case GLX_GREEN_SIZE: return props[s+4]; /* number */
171 case GLX_BLUE_SIZE: return props[s+5]; /* number */
172 case GLX_ALPHA_SIZE: return props[s+6]; /* number */
173 case GLX_DOUBLEBUFFER: return props[s+11]; /* boolean */
174 case GLX_DEPTH_SIZE: return props[s+14]; /* number */
175 case GLX_STENCIL_SIZE: return props[s+15]; /* number */
181 glxrender_check_visual(d_screen_t *sc)
183 xcb_glx_get_visual_configs_cookie_t ck;
184 xcb_glx_get_visual_configs_reply_t *rep;
187 ck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
188 rep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, ck, NULL);
191 unsigned int i, nprops;
194 static int config[] = {
202 props = xcb_glx_get_visual_configs_property_list(rep);
203 nprops = rep->num_properties;
205 for (i = 0; i < rep->num_visuals; ++i) {
206 /* look for the overlay's visual */
207 if (glxrender_visual_info(props, i, nprops, GLX_VISUAL_ID) !=
213 if (!glxrender_visual_info(props, i, nprops, GLX_USE_GL)) {
214 printf("overlay visual does not support GL\n");
218 if (!glxrender_visual_info(props, i, nprops, GLX_DOUBLEBUFFER)) {
219 printf("overlay visual is not double buffered\n");
223 ok = TRUE; /* yippa ! */
232 glxrender_fbconfig_info(uint32_t *props, int con, int numprops, uint32_t name)
236 for (i = 0; i < numprops; ++i) {
237 if (props[i*2 + con*numprops*2] == name)
238 return props[i*2 + con*numprops*2 + 1];
244 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
246 xcb_glx_get_visual_configs_cookie_t vck;
247 xcb_glx_get_visual_configs_reply_t *vrep;
248 xcb_glx_get_fb_configs_cookie_t fbck;
249 xcb_glx_get_fb_configs_reply_t *fbrep;
250 xcb_depth_iterator_t depth_it;
251 unsigned int i, nvprops, nfbprops;
252 uint32_t *vprops, *fbprops;
253 uint32_t db, stencil, depthsize;
255 vck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
256 vrep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, vck, NULL);
257 if (!vrep) return FALSE;
259 fbck = xcb_glx_get_fb_configs(sc->dpy->conn, sc->num);
260 fbrep = xcb_glx_get_fb_configs_reply(sc->dpy->conn, fbck, NULL);
261 if (!fbrep) return FALSE;
263 vprops = xcb_glx_get_visual_configs_property_list(vrep);
264 nvprops = vrep->num_properties;
265 fbprops = xcb_glx_get_fb_configs_property_list(fbrep);
266 nfbprops = fbrep->num_properties;
268 for (i = 0; i <= MAX_DEPTH; ++i)
274 depth_it = xcb_screen_allowed_depths_iterator(&sc->super);
275 for (; depth_it.rem; xcb_depth_next(&depth_it)) {
279 xcb_visualtype_t *visuals;
283 if (depth_it.data->depth > MAX_DEPTH) continue;
285 printf("looking for depth %d\n", depth_it.data->depth);
287 visuals = xcb_depth_visuals(depth_it.data);
288 nvisuals = xcb_depth_visuals_length(depth_it.data);
290 /* pick the nicest visual for the depth */
291 for (j = 0; j < nvisuals; ++j) {
294 /* find the visual's properties */
295 for (k = 0; k < vrep->num_visuals; ++k)
296 if (glxrender_visual_info(vprops, k, nvprops, GLX_VISUAL_ID)
297 == visuals[j].visual_id)
301 if (k == vrep->num_visuals) continue;
303 val = glxrender_visual_info(vprops, k, nvprops, GLX_USE_GL);
306 val = glxrender_visual_info(vprops, k, nvprops, GLX_DOUBLEBUFFER);
307 if (!val > db) continue;
310 val = glxrender_visual_info(vprops, k, nvprops, GLX_STENCIL_SIZE);
311 if (!val > stencil) continue;
314 val = glxrender_visual_info(vprops, k, nvprops, GLX_DEPTH_SIZE);
315 if (!val > depthsize) continue;
318 /* use this visual */
319 vid = visuals[j].visual_id;
324 printf("found visual for depth %d\n", depth_it.data->depth);
326 for (k = 0; k < fbrep->num_FB_configs; ++k) {
329 //printf("root visual 0x%x\n", sc->super.root_visual);
330 //printf("overlay visual 0x%x\n", sc->overlay_visual);
332 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
334 //printf("x visual 0x%x\n", val);
335 if (val != vid) continue;
337 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
339 //printf("dbl buffer %s\n", val ? "yes" : "no");
342 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
344 //printf("depth size %d\n", val);
346 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
348 //printf("red size %d\n", val);
351 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
353 //printf("green size %d\n", val);
356 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
358 //printf("blue size %d\n", val);
361 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
363 //printf("alpha size %d\n", val);
366 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
368 //printf("rgba bit %s\n", val & GLX_RGBA_BIT ? "yes" : "no");
369 if (!(val & GLX_RGBA_BIT)) continue;
371 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
373 //printf("caveat 0x%x\n", val);
375 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
376 GLX_BIND_TO_TEXTURE_RGBA_EXT);
377 //printf("bind ext %s\n", val ? "yes" : "no");
380 d->fbconfig[depth_it.data->depth] =
381 glxrender_fbconfig_info(fbprops, i, nfbprops, GLX_FBCONFIG_ID);
392 glxrender_free(d_screen_t *sc)
394 data_t *d = screen_find_plugin_data(sc, plugin_id);
396 screen_remove_plugin_data(sc, plugin_id);
400 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
408 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
414 glxrender_window_free_data(d_window_t *w, window_data_t *wd)
416 glxrender_free_window_pixmap(w, wd);
417 glDeleteTextures(1, &wd->texname);
422 glxrender_window_show(d_window_t *w)
427 d = screen_find_plugin_data(w->sc, plugin_id);
432 wd = window_find_plugin_data(w, plugin_id);
434 glxrender_window_free_data(w, wd);
436 wd = malloc(sizeof(window_data_t));
437 glGenTextures(1, &wd->texname);
439 window_add_plugin_data(w, plugin_id, wd);
443 glxrender_window_zombie_dead(d_window_t *w)
448 d = screen_find_plugin_data(w->sc, plugin_id);
449 wd = window_find_plugin_data(w, plugin_id);
451 glxrender_window_free_data(w, wd);
452 window_remove_plugin_data(w, plugin_id);
456 d->window_zombie_dead(w);
460 glxrender_free_window_pixmap(d_window_t *w, window_data_t *wd)
462 /* this might cause an error, oh well */
464 glBindTexture(GL_TEXTURE_2D, wd->texname);
466 //d->releaseTexImageEXT(obt_display, lw->glpixmap,
467 // GLX_FRONT_LEFT_EXT);
469 glBindTexture(GL_TEXTURE_2D, 0);
471 xcb_glx_destroy_glx_pixmap(w->sc->dpy->conn, wd->glpixmap);
472 wd->glpixmap = XCB_NONE;
477 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
482 static const uint32_t attrs[] = {
483 GLX_TEXTURE_FORMAT_EXT,
484 GLX_TEXTURE_FORMAT_RGBA_EXT
487 px = window_get_pixmap(w);
488 depth = window_get_depth(w);
489 if (px && d->fbconfig[depth]) {
490 wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
491 xcb_glx_create_pixmap(w->sc->dpy->conn, w->sc->num, d->fbconfig[depth],
492 px, wd->glpixmap, 2, attrs);
494 glBindTexture(GL_TEXTURE_2D, wd->texname);
497 unsigned int len = 2 * sizeof(uint32_t);
498 uint32_t data[] = {wd->glpixmap, GLX_FRONT_LEFT_EXT};
499 xcb_void_cookie_t ck;
500 xcb_generic_error_t *err;
502 ck = xcb_glx_vendor_private(w->sc->dpy->conn,
503 GLX_BIND_TO_TEXTURE_RGBA_EXT,
506 if ((err = xcb_request_check(w->sc->dpy->conn, ck))) {
507 display_error(w->sc->dpy, err);
511 //d->bindTexImageEXT(obt_display, lw->glpixmap,
512 // GLX_FRONT_LEFT_EXT, NULL);
514 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
515 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
518 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
519 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
521 glBindTexture(GL_TEXTURE_2D, 0);
526 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
530 px = screen_get_root_pixmap(sc);
536 glxrender_window_resize(d_window_t *w)
541 d = screen_find_plugin_data(w->sc, plugin_id);
542 wd = window_find_plugin_data(w, plugin_id);
548 glxrender_free_window_pixmap(w, wd);
552 glxrender_window_reshape(d_window_t *w)
557 d = screen_find_plugin_data(w->sc, plugin_id);
558 wd = window_find_plugin_data(w, plugin_id);
561 d->window_reshape(w);
564 glxrender_free_window_pixmap(w, wd);
568 glxrender_root_pixmap_change(d_screen_t *sc)
572 d = screen_find_plugin_data(sc, plugin_id);
573 int a; /* XXX free things here */
574 //if (d->root_picture) {
575 // xcb_render_free_picture(sc->dpy->conn, d->root_picture);
576 // d->root_picture = XCB_NONE;
580 d->screen_root_pixmap_change(sc);
584 glxrender_paint(d_screen_t *sc)
586 data_t *d = screen_find_plugin_data(sc, plugin_id);
589 printf("painting\n");
593 for (it = list_bottom(sc->stacking); it; it = it->prev) {
594 d_window_t *w = it->data;
596 if (!window_is_input_only(w) &&
597 (window_is_mapped(w) || window_is_zombie(w)))
599 int x, y, width, height, bwidth;
603 window_get_area(w, &x, &y, &width, &height, &bwidth);
605 if (!(x < sc->super.width_in_pixels &&
606 y < sc->super.height_in_pixels &&
607 (x + width > 0 || x + width + d->xshadowoff > 0) &&
608 (y + height > 0 || y + height + d->yshadowoff > 0)))
613 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
615 wd = window_find_plugin_data(w, plugin_id);
617 paint_shadow(w, d, wd, x, y, width, height, bwidth);
618 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
622 xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
624 /* call the function we replaced in the chain */
629 paint_root(d_screen_t *sc, data_t *d)
631 //if (!d->root_picture)
632 glxrender_update_root_pixmap(sc, d);
634 glClear(GL_COLOR_BUFFER_BIT);
638 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
639 int x, int y, int width, int height, int bwidth)
642 glxrender_update_window_pixmap(w, d, wd);
645 glColor3f(1.0, 1.0, 1.0);
648 glVertex2i(x + width + bwidth, y);
650 glVertex2i(x + width + bwidth,
651 y + height + bwidth);
653 glVertex2i(x, y + height + bwidth);
659 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
660 int x, int y, int width, int height, int bwidth)
663 xcb_render_composite(w->sc->dpy->conn,
664 XCB_RENDER_PICT_OP_OVER,
669 x+d->xshadowoff, y+d->yshadowoff,
670 width + bwidth*2, height + bwidth *2);