15 //#include <GL/glext.h>
16 //#include <GL/glxext.h>
17 #include <GL/glxtokens.h>
25 void (*screen_paint)(d_screen_t *sc);
26 void (*screen_root_pixmap_change)(d_screen_t *sc);
27 void (*window_show)(d_window_t *w);
28 void (*window_zombie_dead)(d_window_t *w);
29 void (*window_resize)(d_window_t *w);
30 void (*window_reshape)(d_window_t *w);
36 uint32_t fbconfig[MAX_DEPTH + 1];
38 xcb_glx_context_t context;
39 xcb_glx_context_tag_t context_tag;
44 xcb_glx_pixmap_t glpixmap;
47 static uint32_t glxrender_visual_info(uint32_t *props, int vis, int numprops,
49 static gboolean glxrender_check_visual(d_screen_t *sc);
50 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
52 static void glxrender_paint(d_screen_t *sc);
53 static void glxrender_root_pixmap_change(d_screen_t *sc);
54 static void paint_root(d_screen_t *sc, data_t *d);
55 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
56 gboolean opaque, int x, int y, int width,
57 int height, int bwidth);
58 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
59 int x, int y, int width, int height, int bwidth);
60 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
62 static void glxrender_free_window_pixmap(d_window_t *w, data_t *d,
64 static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
66 static void glxrender_window_show(d_window_t *window);
67 static void glxrender_window_zombie_dead(d_window_t *window);
68 static void glxrender_window_resize(d_window_t *window);
69 static void glxrender_window_reshape(d_window_t *window);
72 glxrender_init(d_screen_t *sc, int id)
75 xcb_generic_error_t *err;
76 xcb_glx_make_current_cookie_t curck;
77 xcb_glx_make_current_reply_t *currep;
81 data_t *d = malloc(sizeof(data_t));
82 d->screen_paint = sc->screen_paint;
83 d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
84 d->window_show = sc->window_show;
85 d->window_zombie_dead = sc->window_zombie_dead;
86 d->window_resize = sc->window_resize;
87 d->window_reshape = sc->window_reshape;
88 screen_add_plugin_data(sc, plugin_id, d);
90 sc->screen_paint = glxrender_paint;
91 sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
92 sc->window_show = glxrender_window_show;
93 sc->window_zombie_dead = glxrender_window_zombie_dead;
94 sc->window_resize = glxrender_window_resize;
95 sc->window_reshape = glxrender_window_reshape;
97 d->shadowalpha = 0x3333; /* 20% */
101 if (!(glxrender_find_fb_config(sc, d))) {
102 printf("unable to find FB configs\n");
106 if (!glxrender_check_visual(sc)) {
107 printf("unable to use the overlay window for GLX\n");
111 d->context = xcb_generate_id(sc->dpy->conn);
112 ck = xcb_glx_create_context_checked(sc->dpy->conn, d->context,
113 sc->overlay_visual, sc->num,
115 if ((err = xcb_request_check(sc->dpy->conn, ck))) {
116 printf("context creation failed\n");
117 display_error(sc->dpy, err);
122 curck = xcb_glx_make_current(sc->dpy->conn,
123 sc->overlay, d->context, XCB_NONE);
124 currep = xcb_glx_make_current_reply(sc->dpy->conn, curck, &err);
127 display_error(sc->dpy, err);
130 printf("make current failed\n");
133 d->context_tag = currep->context_tag;
136 glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
137 glMatrixMode(GL_PROJECTION);
139 glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels,
141 glMatrixMode(GL_MODELVIEW);
143 glClear(GL_COLOR_BUFFER_BIT);
144 glEnable(GL_TEXTURE_2D);
145 xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
146 glClearColor(0.4, 0.4, 0.4, 1.0);
149 glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
155 glxrender_visual_info(uint32_t *props, int vis, int numprops, uint32_t name)
159 assert(numprops > 14);
162 for (s = vis * numprops; s < vis*numprops + numprops; ++s)
163 printf("%x ", props[s]);
169 case GLX_VISUAL_ID: return props[s+0]; /* id number */
170 case GLX_X_VISUAL_TYPE: return props[s+1]; /* XCB_CLASS_TRUE_COLOR etc */
171 case GLX_USE_GL: return props[s+2]; /* boolean */
172 case GLX_RED_SIZE: return props[s+3]; /* number */
173 case GLX_GREEN_SIZE: return props[s+4]; /* number */
174 case GLX_BLUE_SIZE: return props[s+5]; /* number */
175 case GLX_ALPHA_SIZE: return props[s+6]; /* number */
176 case GLX_DOUBLEBUFFER: return props[s+11]; /* boolean */
177 case GLX_DEPTH_SIZE: return props[s+14]; /* number */
178 case GLX_STENCIL_SIZE: return props[s+15]; /* number */
184 glxrender_check_visual(d_screen_t *sc)
186 xcb_glx_get_visual_configs_cookie_t ck;
187 xcb_glx_get_visual_configs_reply_t *rep;
190 ck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
191 rep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, ck, NULL);
194 unsigned int i, nprops;
197 static int config[] = {
205 props = xcb_glx_get_visual_configs_property_list(rep);
206 nprops = rep->num_properties;
208 for (i = 0; i < rep->num_visuals; ++i) {
209 /* look for the overlay's visual */
210 if (glxrender_visual_info(props, i, nprops, GLX_VISUAL_ID) !=
216 if (!glxrender_visual_info(props, i, nprops, GLX_USE_GL)) {
217 printf("overlay visual does not support GL\n");
221 if (!glxrender_visual_info(props, i, nprops, GLX_DOUBLEBUFFER)) {
222 printf("overlay visual is not double buffered\n");
226 ok = TRUE; /* yippa ! */
235 glxrender_fbconfig_info(uint32_t *props, int con, int numprops, uint32_t name)
239 for (i = 0; i < numprops; ++i) {
240 if (props[i*2 + con*numprops*2] == name)
241 return props[i*2 + con*numprops*2 + 1];
247 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
249 xcb_glx_get_visual_configs_cookie_t vck;
250 xcb_glx_get_visual_configs_reply_t *vrep;
251 xcb_glx_get_fb_configs_cookie_t fbck;
252 xcb_glx_get_fb_configs_reply_t *fbrep;
253 xcb_depth_iterator_t depth_it;
254 unsigned int i, nvprops, nfbprops;
255 uint32_t *vprops, *fbprops;
256 uint32_t db, stencil, depthsize;
259 static const uint32_t drawable_tfp_attrs[] = {
260 GLX_CONFIG_CAVEAT, GLX_NONE,
261 GLX_DOUBLEBUFFER, FALSE,
267 GLX_RENDER_TYPE, GLX_RGBA_BIT,
268 GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
272 d_glx_fb_config_t *fbcons;
275 fbcons = glxcompat_choose_fb_config(sc->dpy->conn, sc->num,
276 drawable_tfp_attrs, &numfb);
277 printf("found %d\n", numfb);
279 for (i = 0; i < numfb; ++i) {
281 glxcompat_get_fb_config_attrib(fbcons[i], GLX_FBCONFIG_ID, &v);
282 printf("GLX_FBCONFIG_ID %x\n", v);
289 vck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
290 vrep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, vck, NULL);
291 if (!vrep) return FALSE;
293 fbck = xcb_glx_get_fb_configs(sc->dpy->conn, sc->num);
294 fbrep = xcb_glx_get_fb_configs_reply(sc->dpy->conn, fbck, NULL);
295 if (!fbrep) return FALSE;
297 vprops = xcb_glx_get_visual_configs_property_list(vrep);
298 nvprops = vrep->num_properties;
299 fbprops = xcb_glx_get_fb_configs_property_list(fbrep);
300 nfbprops = fbrep->num_properties;
302 memset(d->fbconfig, 0, (MAX_DEPTH + 1) * sizeof(d->fbconfig[0]));
307 depth_it = xcb_screen_allowed_depths_iterator(sc->super);
308 for (; depth_it.rem; xcb_depth_next(&depth_it)) {
312 xcb_visualtype_t *visuals;
316 if (depth_it.data->depth > MAX_DEPTH) continue;
318 printf("looking for depth %d\n", depth_it.data->depth);
320 visuals = xcb_depth_visuals(depth_it.data);
321 nvisuals = xcb_depth_visuals_length(depth_it.data);
323 /* pick the nicest visual for the depth */
324 for (j = 0; j < nvisuals; ++j) {
326 /* find the visual's properties */
327 for (k = 0; k < vrep->num_visuals; ++k)
328 if (glxrender_visual_info(vprops, k, nvprops, GLX_VISUAL_ID)
329 == visuals[j].visual_id)
333 if (k == vrep->num_visuals) continue;
335 val = glxrender_visual_info(vprops, k, nvprops, GLX_USE_GL);
338 val = glxrender_visual_info(vprops, k, nvprops, GLX_DOUBLEBUFFER);
339 if (!val > db) continue;
342 val = glxrender_visual_info(vprops, k, nvprops, GLX_STENCIL_SIZE);
343 if (!val > stencil) continue;
346 val = glxrender_visual_info(vprops, k, nvprops, GLX_DEPTH_SIZE);
347 if (!val > depthsize) continue;
350 /* try this visual */
351 vid = visuals[j].visual_id;
353 /* look for an fbconfig for this visual */
354 for (k = 0; k < fbrep->num_FB_configs; ++k) {
357 //printf("root visual 0x%x\n", sc->super.root_visual);
358 //printf("overlay visual 0x%x\n", sc->overlay_visual);
360 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
362 //printf("x visual 0x%x\n", val);
363 if (val != vid) continue;
365 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
366 GLX_BIND_TO_TEXTURE_TARGETS_EXT);
367 printf("BIND TO TARGETS %x\n", val);
369 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
371 printf("dbl buffer %s\n", val ? "yes" : "no");
374 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
376 printf("depth size %d\n", val);
378 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
380 printf("red size %d\n", val);
383 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
385 printf("green size %d\n", val);
388 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
390 printf("blue size %d\n", val);
393 val = glxrender_fbconfig_info(fbprops, k, nfbprops,
395 printf("alpha size %d\n", val);
396 //if (depth_it.data->depth == 32 && !val) continue;
398 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
400 printf("rgba bit %s\n", val & GLX_RGBA_BIT ? "yes" : "no");
401 if (!(val & GLX_RGBA_BIT)) continue;
403 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
405 printf("caveat 0x%x\n", val);
407 val = glxrender_fbconfig_info(fbprops, j, nfbprops,
408 GLX_BIND_TO_TEXTURE_RGBA_EXT);
409 printf("bind ext %s\n", val ? "yes" : "no");
412 d->fbconfig[depth_it.data->depth] =
413 glxrender_fbconfig_info(fbprops, i, nfbprops,
418 if (d->fbconfig[depth_it.data->depth])
419 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
420 vid, d->fbconfig[depth_it.data->depth],
421 depth_it.data->depth);
431 glxrender_free(d_screen_t *sc)
433 data_t *d = screen_find_plugin_data(sc, plugin_id);
435 screen_remove_plugin_data(sc, plugin_id);
439 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
447 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
453 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
455 glxrender_free_window_pixmap(w, d, wd);
456 glDeleteTextures(1, &wd->texname);
461 glxrender_window_show(d_window_t *w)
466 d = screen_find_plugin_data(w->sc, plugin_id);
471 wd = window_find_plugin_data(w, plugin_id);
473 glxrender_window_free_data(w, d, wd);
475 wd = malloc(sizeof(window_data_t));
476 glGenTextures(1, &wd->texname);
477 wd->glpixmap = XCB_NONE;
479 window_add_plugin_data(w, plugin_id, wd);
483 glxrender_window_zombie_dead(d_window_t *w)
488 d = screen_find_plugin_data(w->sc, plugin_id);
489 wd = window_find_plugin_data(w, plugin_id);
491 glxrender_window_free_data(w, d, wd);
492 window_remove_plugin_data(w, plugin_id);
496 d->window_zombie_dead(w);
500 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
502 /* this might cause an error, oh well */
504 glBindTexture(GL_TEXTURE_2D, wd->texname);
509 1 CARD8 opcode (X assigned)
510 1 16 GLX opcode (glXVendorPrivate)
512 4 1331 vendor specific opcode
514 4 GLX_DRAWABLE drawable
517 unsigned int len = (2 + 0) * sizeof(uint32_t);
522 xcb_glx_vendor_private(w->sc->dpy->conn,
525 len, (uint8_t*)data);
528 glBindTexture(GL_TEXTURE_2D, 0);
530 xcb_glx_destroy_glx_pixmap(w->sc->dpy->conn, wd->glpixmap);
531 wd->glpixmap = XCB_NONE;
536 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
541 static const uint32_t attrs[] = {
542 GLX_TEXTURE_FORMAT_EXT,
543 GLX_TEXTURE_FORMAT_RGBA_EXT
546 px = window_get_pixmap(w);
547 depth = window_get_depth(w);
548 if (px && d->fbconfig[depth]) {
549 wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
550 printf("creating pixmap fbcon 0x%x\n", d->fbconfig[depth]);
552 xcb_void_cookie_t ck =
553 xcb_glx_create_pixmap_checked(w->sc->dpy->conn, w->sc->num,
556 sizeof(attrs)/sizeof(attrs[0]),
559 xcb_generic_error_t *err;
560 err = xcb_request_check(w->sc->dpy->conn, ck);
562 printf("error creating pixmap\n");
563 display_error(w->sc->dpy, err);
568 glBindTexture(GL_TEXTURE_2D, wd->texname);
573 1 CARD8 opcode (X assigned)
574 1 16 GLX opcode (glXVendorPrivate)
576 4 1330 vendor specific opcode
578 4 GLX_DRAWABLE drawable
580 4 CARD32 num_attributes
581 4*n LISTofATTRIBUTE_PAIR attribute, value pairs.
583 unsigned int len = (3 + 0) * sizeof(uint32_t);
589 xcb_glx_vendor_private(w->sc->dpy->conn,
592 len, (uint8_t*)data);
595 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
596 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
598 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
599 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
600 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
602 glBindTexture(GL_TEXTURE_2D, 0);
607 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
611 px = screen_get_root_pixmap(sc);
617 glxrender_window_resize(d_window_t *w)
622 d = screen_find_plugin_data(w->sc, plugin_id);
623 wd = window_find_plugin_data(w, plugin_id);
629 glxrender_free_window_pixmap(w, d, wd);
633 glxrender_window_reshape(d_window_t *w)
638 d = screen_find_plugin_data(w->sc, plugin_id);
639 wd = window_find_plugin_data(w, plugin_id);
642 d->window_reshape(w);
645 glxrender_free_window_pixmap(w, d, wd);
649 glxrender_root_pixmap_change(d_screen_t *sc)
653 d = screen_find_plugin_data(sc, plugin_id);
654 int a; /* XXX free things here */
655 //if (d->root_picture) {
656 // xcb_render_free_picture(sc->dpy->conn, d->root_picture);
657 // d->root_picture = XCB_NONE;
661 d->screen_root_pixmap_change(sc);
665 glxrender_paint(d_screen_t *sc)
667 data_t *d = screen_find_plugin_data(sc, plugin_id);
670 //printf("painting\n");
674 for (it = list_bottom(sc->stacking); it; it = it->prev) {
675 d_window_t *w = it->data;
677 if (!window_is_input_only(w) &&
678 (window_is_mapped(w) || window_is_zombie(w)))
680 int x, y, width, height, bwidth;
684 window_get_area(w, &x, &y, &width, &height, &bwidth);
686 if (!(x < sc->super->width_in_pixels &&
687 y < sc->super->height_in_pixels &&
688 (x + width > 0 || x + width + d->xshadowoff > 0) &&
689 (y + height > 0 || y + height + d->yshadowoff > 0)))
694 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
696 wd = window_find_plugin_data(w, plugin_id);
698 paint_shadow(w, d, wd, x, y, width, height, bwidth);
699 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
703 xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
705 /* call the function we replaced in the chain */
710 paint_root(d_screen_t *sc, data_t *d)
712 //if (!d->root_picture)
713 glxrender_update_root_pixmap(sc, d);
715 glClear(GL_COLOR_BUFFER_BIT);
719 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
720 int x, int y, int width, int height, int bwidth)
723 glxrender_update_window_pixmap(w, d, wd);
725 glBindTexture(GL_TEXTURE_2D, wd->texname);
727 glColor3f(1.0, 1.0, 1.0);
730 glVertex2i(x + width + bwidth, y);
732 glVertex2i(x + width + bwidth,
733 y + height + bwidth);
735 glVertex2i(x, y + height + bwidth);
741 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
742 int x, int y, int width, int height, int bwidth)
745 xcb_render_composite(w->sc->dpy->conn,
746 XCB_RENDER_PICT_OP_OVER,
751 x+d->xshadowoff, y+d->yshadowoff,
752 width + bwidth*2, height + bwidth *2);