14 //#include <GL/glext.h>
15 //#include <GL/glxext.h>
16 #include <GL/glxtokens.h>
24 void (*screen_paint)(d_screen_t *sc);
25 void (*screen_root_pixmap_change)(d_screen_t *sc);
26 void (*window_show)(d_window_t *w);
27 void (*window_zombie_dead)(d_window_t *w);
28 void (*window_resize)(d_window_t *w);
29 void (*window_reshape)(d_window_t *w);
35 uint32_t fbconfig[MAX_DEPTH + 1];
37 xcb_glx_context_t context;
38 xcb_glx_context_tag_t context_tag;
43 xcb_glx_pixmap_t glpixmap;
46 static uint32_t glxrender_visual_info(uint32_t *props, int vis, int numprops,
48 static gboolean glxrender_check_visual(d_screen_t *sc);
49 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
51 static void glxrender_paint(d_screen_t *sc);
52 static void glxrender_root_pixmap_change(d_screen_t *sc);
53 static void paint_root(d_screen_t *sc, data_t *d);
54 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
55 gboolean opaque, int x, int y, int width,
56 int height, int bwidth);
57 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
58 int x, int y, int width, int height, int bwidth);
59 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
61 static void glxrender_free_window_pixmap(d_window_t *w, data_t *d,
63 static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
65 static void glxrender_window_show(d_window_t *window);
66 static void glxrender_window_zombie_dead(d_window_t *window);
67 static void glxrender_window_resize(d_window_t *window);
68 static void glxrender_window_reshape(d_window_t *window);
71 glxrender_init(d_screen_t *sc, int id)
74 xcb_generic_error_t *err;
75 xcb_glx_make_current_cookie_t curck;
76 xcb_glx_make_current_reply_t *currep;
80 data_t *d = malloc(sizeof(data_t));
81 d->screen_paint = sc->screen_paint;
82 d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
83 d->window_show = sc->window_show;
84 d->window_zombie_dead = sc->window_zombie_dead;
85 d->window_resize = sc->window_resize;
86 d->window_reshape = sc->window_reshape;
87 screen_add_plugin_data(sc, plugin_id, d);
89 sc->screen_paint = glxrender_paint;
90 sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
91 sc->window_show = glxrender_window_show;
92 sc->window_zombie_dead = glxrender_window_zombie_dead;
93 sc->window_resize = glxrender_window_resize;
94 sc->window_reshape = glxrender_window_reshape;
96 d->shadowalpha = 0x3333; /* 20% */
100 if (!glxrender_check_visual(sc)) {
101 printf("unable to use the overlay window for GLX\n");
105 if (!(glxrender_find_fb_config(sc, d))) {
106 printf("unable to find FB configs\n");
110 d->context = xcb_generate_id(sc->dpy->conn);
111 ck = xcb_glx_create_context_checked(sc->dpy->conn, d->context,
112 sc->overlay_visual, sc->num,
114 if ((err = xcb_request_check(sc->dpy->conn, ck))) {
115 printf("context creation failed\n");
116 display_error(sc->dpy, err);
121 curck = xcb_glx_make_current(sc->dpy->conn,
122 sc->overlay, d->context, XCB_NONE);
123 currep = xcb_glx_make_current_reply(sc->dpy->conn, curck, &err);
126 display_error(sc->dpy, err);
129 printf("make current failed\n");
132 d->context_tag = currep->context_tag;
135 glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
136 glMatrixMode(GL_PROJECTION);
138 glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels,
140 glMatrixMode(GL_MODELVIEW);
142 glClear(GL_COLOR_BUFFER_BIT);
143 glEnable(GL_TEXTURE_2D);
144 xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
145 glClearColor(0.4, 0.4, 0.4, 1.0);
148 glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
154 glxrender_visual_info(uint32_t *props, int vis, int numprops, uint32_t name)
158 assert(numprops > 14);
161 for (s = vis * numprops; s < vis*numprops + numprops; ++s)
162 printf("%x ", props[s]);
168 case GLX_VISUAL_ID: return props[s+0]; /* id number */
169 case GLX_X_VISUAL_TYPE: return props[s+1]; /* XCB_CLASS_TRUE_COLOR etc */
170 case GLX_USE_GL: return props[s+2]; /* boolean */
171 case GLX_RED_SIZE: return props[s+3]; /* number */
172 case GLX_GREEN_SIZE: return props[s+4]; /* number */
173 case GLX_BLUE_SIZE: return props[s+5]; /* number */
174 case GLX_ALPHA_SIZE: return props[s+6]; /* number */
175 case GLX_DOUBLEBUFFER: return props[s+11]; /* boolean */
176 case GLX_DEPTH_SIZE: return props[s+14]; /* number */
177 case GLX_STENCIL_SIZE: return props[s+15]; /* number */
183 glxrender_check_visual(d_screen_t *sc)
185 xcb_glx_get_visual_configs_cookie_t ck;
186 xcb_glx_get_visual_configs_reply_t *rep;
189 ck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
190 rep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, ck, NULL);
193 unsigned int i, nprops;
196 static int config[] = {
204 props = xcb_glx_get_visual_configs_property_list(rep);
205 nprops = rep->num_properties;
207 for (i = 0; i < rep->num_visuals; ++i) {
208 /* look for the overlay's visual */
209 if (glxrender_visual_info(props, i, nprops, GLX_VISUAL_ID) !=
215 if (!glxrender_visual_info(props, i, nprops, GLX_USE_GL)) {
216 printf("overlay visual does not support GL\n");
220 if (!glxrender_visual_info(props, i, nprops, GLX_DOUBLEBUFFER)) {
221 printf("overlay visual is not double buffered\n");
225 ok = TRUE; /* yippa ! */
234 glxrender_fbconfig_info(uint32_t *props, int con, int numprops, uint32_t name)
238 for (i = 0; i < numprops; ++i) {
239 if (props[i*2 + con*numprops*2] == name)
240 return props[i*2 + con*numprops*2 + 1];
246 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
248 xcb_glx_get_visual_configs_cookie_t vck;
249 xcb_glx_get_visual_configs_reply_t *vrep;
250 xcb_glx_get_fb_configs_cookie_t fbck;
251 xcb_glx_get_fb_configs_reply_t *fbrep;
252 xcb_depth_iterator_t depth_it;
253 unsigned int i, nvprops, nfbprops;
254 uint32_t *vprops, *fbprops;
255 uint32_t db, stencil, depthsize;
257 vck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
258 vrep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, vck, NULL);
259 if (!vrep) return FALSE;
261 fbck = xcb_glx_get_fb_configs(sc->dpy->conn, sc->num);
262 fbrep = xcb_glx_get_fb_configs_reply(sc->dpy->conn, fbck, NULL);
263 if (!fbrep) return FALSE;
265 vprops = xcb_glx_get_visual_configs_property_list(vrep);
266 nvprops = vrep->num_properties;
267 fbprops = xcb_glx_get_fb_configs_property_list(fbrep);
268 nfbprops = fbrep->num_properties;
270 memset(d->fbconfig, 0, (MAX_DEPTH + 1) * sizeof(d->fbconfig[0]));
275 depth_it = xcb_screen_allowed_depths_iterator(sc->super);
276 for (; depth_it.rem; xcb_depth_next(&depth_it)) {
280 xcb_visualtype_t *visuals;
284 if (depth_it.data->depth > MAX_DEPTH) continue;
286 printf("looking for depth %d\n", depth_it.data->depth);
288 visuals = xcb_depth_visuals(depth_it.data);
289 nvisuals = xcb_depth_visuals_length(depth_it.data);
291 /* pick the nicest visual for the depth */
292 for (j = 0; j < nvisuals; ++j) {
295 /* find the visual's properties */
296 for (k = 0; k < vrep->num_visuals; ++k)
297 if (glxrender_visual_info(vprops, k, nvprops, GLX_VISUAL_ID)
298 == visuals[j].visual_id)
302 if (k == vrep->num_visuals) continue;
304 val = glxrender_visual_info(vprops, k, nvprops, GLX_USE_GL);
307 val = glxrender_visual_info(vprops, k, nvprops, GLX_DOUBLEBUFFER);
308 if (!val > db) continue;
311 val = glxrender_visual_info(vprops, k, nvprops, GLX_STENCIL_SIZE);
312 if (!val > stencil) continue;
315 val = glxrender_visual_info(vprops, k, nvprops, GLX_DEPTH_SIZE);
316 if (!val > depthsize) continue;
319 /* try this visual */
320 vid = visuals[j].visual_id;
322 /* look for an fbconfig for this visual */
323 for (k = 0; k < fbrep->num_FB_configs; ++k) {
326 //printf("root visual 0x%x\n", sc->super.root_visual);
327 //printf("overlay visual 0x%x\n", sc->overlay_visual);
329 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
331 //printf("x visual 0x%x\n", val);
332 if (val != vid) continue;
334 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
336 printf("dbl buffer %s\n", val ? "yes" : "no");
339 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
341 printf("depth size %d\n", val);
343 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
345 printf("red size %d\n", val);
348 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
350 printf("green size %d\n", val);
353 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
355 printf("blue size %d\n", val);
358 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
360 printf("alpha size %d\n", val);
361 //if (depth_it.data->depth == 32 && !val) continue;
363 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
365 printf("rgba bit %s\n", val & GLX_RGBA_BIT ? "yes" : "no");
366 if (!(val & GLX_RGBA_BIT)) continue;
368 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
370 printf("caveat 0x%x\n", val);
372 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
373 GLX_BIND_TO_TEXTURE_RGBA_EXT);
374 printf("bind ext %s\n", val ? "yes" : "no");
377 d->fbconfig[depth_it.data->depth] =
378 glxrender_fbconfig_info(fbprops, i, nfbprops,
383 if (d->fbconfig[depth_it.data->depth])
384 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
385 vid, d->fbconfig[depth_it.data->depth],
386 depth_it.data->depth);
396 glxrender_free(d_screen_t *sc)
398 data_t *d = screen_find_plugin_data(sc, plugin_id);
400 screen_remove_plugin_data(sc, plugin_id);
404 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
412 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
418 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
420 glxrender_free_window_pixmap(w, d, wd);
421 glDeleteTextures(1, &wd->texname);
426 glxrender_window_show(d_window_t *w)
431 d = screen_find_plugin_data(w->sc, plugin_id);
436 wd = window_find_plugin_data(w, plugin_id);
438 glxrender_window_free_data(w, d, wd);
440 wd = malloc(sizeof(window_data_t));
441 glGenTextures(1, &wd->texname);
442 wd->glpixmap = XCB_NONE;
444 window_add_plugin_data(w, plugin_id, wd);
448 glxrender_window_zombie_dead(d_window_t *w)
453 d = screen_find_plugin_data(w->sc, plugin_id);
454 wd = window_find_plugin_data(w, plugin_id);
456 glxrender_window_free_data(w, d, wd);
457 window_remove_plugin_data(w, plugin_id);
461 d->window_zombie_dead(w);
465 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
467 /* this might cause an error, oh well */
469 glBindTexture(GL_TEXTURE_2D, wd->texname);
474 1 CARD8 opcode (X assigned)
475 1 16 GLX opcode (glXVendorPrivate)
477 4 1331 vendor specific opcode
479 4 GLX_DRAWABLE drawable
482 unsigned int len = (2 + 0) * sizeof(uint32_t);
487 xcb_glx_vendor_private(w->sc->dpy->conn,
490 len, (uint8_t*)data);
493 glBindTexture(GL_TEXTURE_2D, 0);
495 xcb_glx_destroy_glx_pixmap(w->sc->dpy->conn, wd->glpixmap);
496 wd->glpixmap = XCB_NONE;
501 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
506 static const uint32_t attrs[] = {
507 GLX_TEXTURE_FORMAT_EXT,
508 GLX_TEXTURE_FORMAT_RGBA_EXT,
511 px = window_get_pixmap(w);
512 depth = window_get_depth(w);
513 if (px && d->fbconfig[depth]) {
514 wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
515 printf("creating pixmap fbcon 0x%x\n", d->fbconfig[depth]);
516 xcb_glx_create_pixmap(w->sc->dpy->conn, w->sc->num, d->fbconfig[depth],
517 px, wd->glpixmap, 2, attrs);
519 glBindTexture(GL_TEXTURE_2D, wd->texname);
524 1 CARD8 opcode (X assigned)
525 1 16 GLX opcode (glXVendorPrivate)
527 4 1330 vendor specific opcode
529 4 GLX_DRAWABLE drawable
531 4 CARD32 num_attributes
532 4*n LISTofATTRIBUTE_PAIR attribute, value pairs.
534 unsigned int len = (4 + 0) * sizeof(uint32_t);
541 xcb_glx_vendor_private(w->sc->dpy->conn,
544 len, (uint8_t*)data);
547 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
548 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
550 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
551 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
552 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
554 glBindTexture(GL_TEXTURE_2D, 0);
559 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
563 px = screen_get_root_pixmap(sc);
569 glxrender_window_resize(d_window_t *w)
574 d = screen_find_plugin_data(w->sc, plugin_id);
575 wd = window_find_plugin_data(w, plugin_id);
581 glxrender_free_window_pixmap(w, d, wd);
585 glxrender_window_reshape(d_window_t *w)
590 d = screen_find_plugin_data(w->sc, plugin_id);
591 wd = window_find_plugin_data(w, plugin_id);
594 d->window_reshape(w);
597 glxrender_free_window_pixmap(w, d, wd);
601 glxrender_root_pixmap_change(d_screen_t *sc)
605 d = screen_find_plugin_data(sc, plugin_id);
606 int a; /* XXX free things here */
607 //if (d->root_picture) {
608 // xcb_render_free_picture(sc->dpy->conn, d->root_picture);
609 // d->root_picture = XCB_NONE;
613 d->screen_root_pixmap_change(sc);
617 glxrender_paint(d_screen_t *sc)
619 data_t *d = screen_find_plugin_data(sc, plugin_id);
622 //printf("painting\n");
626 for (it = list_bottom(sc->stacking); it; it = it->prev) {
627 d_window_t *w = it->data;
629 if (!window_is_input_only(w) &&
630 (window_is_mapped(w) || window_is_zombie(w)))
632 int x, y, width, height, bwidth;
636 window_get_area(w, &x, &y, &width, &height, &bwidth);
638 if (!(x < sc->super->width_in_pixels &&
639 y < sc->super->height_in_pixels &&
640 (x + width > 0 || x + width + d->xshadowoff > 0) &&
641 (y + height > 0 || y + height + d->yshadowoff > 0)))
646 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
648 wd = window_find_plugin_data(w, plugin_id);
650 paint_shadow(w, d, wd, x, y, width, height, bwidth);
651 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
655 xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
657 /* call the function we replaced in the chain */
662 paint_root(d_screen_t *sc, data_t *d)
664 //if (!d->root_picture)
665 glxrender_update_root_pixmap(sc, d);
667 glClear(GL_COLOR_BUFFER_BIT);
671 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
672 int x, int y, int width, int height, int bwidth)
675 glxrender_update_window_pixmap(w, d, wd);
677 glBindTexture(GL_TEXTURE_2D, wd->texname);
679 glColor3f(1.0, 1.0, 1.0);
682 glVertex2i(x + width + bwidth, y);
684 glVertex2i(x + width + bwidth,
685 y + height + bwidth);
687 glVertex2i(x, y + height + bwidth);
693 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
694 int x, int y, int width, int height, int bwidth)
697 xcb_render_composite(w->sc->dpy->conn,
698 XCB_RENDER_PICT_OP_OVER,
703 x+d->xshadowoff, y+d->yshadowoff,
704 width + bwidth*2, height + bwidth *2);