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 BindEXTFunc bind_func;
43 ReleaseEXTFunc release_func;
51 static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
53 static void glxrender_paint(d_screen_t *sc);
54 static void glxrender_root_pixmap_change(d_screen_t *sc);
55 static void paint_root(d_screen_t *sc, data_t *d);
56 static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
57 gboolean opaque, int x, int y, int width,
58 int height, int bwidth);
59 static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
60 int x, int y, int width, int height, int bwidth);
61 static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
63 static void glxrender_free_window_pixmap(d_window_t *w, data_t *d,
65 static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
67 static void glxrender_window_show(d_window_t *window);
68 static void glxrender_window_zombie_dead(d_window_t *window);
69 static void glxrender_window_resize(d_window_t *window);
70 static void glxrender_window_reshape(d_window_t *window);
73 glxrender_init(d_screen_t *sc, int id)
75 static int context_visual_config[] = {
86 d = malloc(sizeof(data_t));
87 d->screen_paint = sc->screen_paint;
88 d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
89 d->window_show = sc->window_show;
90 d->window_zombie_dead = sc->window_zombie_dead;
91 d->window_resize = sc->window_resize;
92 d->window_reshape = sc->window_reshape;
93 screen_add_plugin_data(sc, plugin_id, d);
95 sc->screen_paint = glxrender_paint;
96 sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
97 sc->window_show = glxrender_window_show;
98 sc->window_zombie_dead = glxrender_window_zombie_dead;
99 sc->window_resize = glxrender_window_resize;
100 sc->window_reshape = glxrender_window_reshape;
102 d->shadowalpha = 0.2f; /* 20% */
106 vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config);
108 printf("unable to find a valid double buffered GL context to use\n");
112 d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE);
113 glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context);
116 if (!(glxrender_find_fb_config(sc, d))) {
117 printf("unable to find FB configs\n");
121 glViewport(0, 0, sc->super->width_in_pixels, sc->super->height_in_pixels);
122 glMatrixMode(GL_PROJECTION);
124 glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0,
126 glMatrixMode(GL_MODELVIEW);
128 glEnable(GL_TEXTURE_2D);
130 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
131 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
134 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
135 glClear(GL_COLOR_BUFFER_BIT);
136 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
138 d->bind_func = (BindEXTFunc)
139 glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
140 d->release_func = (ReleaseEXTFunc)
141 glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
145 glxrender_find_fb_config(d_screen_t *sc, data_t *d)
147 static const int drawable_tfp_attrs[] = {
148 GLX_CONFIG_CAVEAT, GLX_NONE,
149 GLX_DOUBLEBUFFER, FALSE,
155 GLX_RENDER_TYPE, GLX_RGBA_BIT,
156 GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
159 int db, stencil, depth, numfb, i;
161 XVisualInfo tvis, *visinfo;
163 fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num,
164 drawable_tfp_attrs, &numfb);
165 if (!fbcons) return FALSE;
167 for (i = 0; i <= MAX_DEPTH; i++) {
177 printf("looking for depth %d\n", i);
180 visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask,
182 /* pick the nicest visual for the depth */
183 for (j = 0; j < count; j++) {
184 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_USE_GL, &value);
188 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER,
194 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE,
200 glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE,
206 /* use this visual */
207 vid = visinfo[j].visualid;
212 /* look for an fbconfig for this visual */
213 for (j = 0; j < numfb; ++j) {
214 glXGetFBConfigAttrib(sc->dpy->xlib_dpy, fbcons[j],
215 GLX_VISUAL_ID, &value);
216 if ((unsigned)value == vid) {
217 d->fbconfig[i] = fbcons[j];
219 printf("found visual 0x%x fbconfig 0x%x for depth %d\n",
220 (uint32_t)vid, (uint32_t)fbcons[j], i);
231 glxrender_free(d_screen_t *sc)
233 data_t *d = screen_find_plugin_data(sc, plugin_id);
235 screen_remove_plugin_data(sc, plugin_id);
239 glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
247 glxrender_timeout(struct d_screen *sc, const struct timeval *now)
253 glxrender_window_free_data(d_window_t *w, data_t *d, window_data_t *wd)
255 glxrender_free_window_pixmap(w, d, wd);
256 glDeleteTextures(1, &wd->texname);
261 glxrender_window_show(d_window_t *w)
266 d = screen_find_plugin_data(w->sc, plugin_id);
271 wd = window_find_plugin_data(w, plugin_id);
273 glxrender_window_free_data(w, d, wd);
275 wd = malloc(sizeof(window_data_t));
276 glGenTextures(1, &wd->texname);
277 wd->glpixmap = XCB_NONE;
279 window_add_plugin_data(w, plugin_id, wd);
283 glxrender_window_zombie_dead(d_window_t *w)
288 d = screen_find_plugin_data(w->sc, plugin_id);
289 wd = window_find_plugin_data(w, plugin_id);
291 glxrender_window_free_data(w, d, wd);
292 window_remove_plugin_data(w, plugin_id);
296 d->window_zombie_dead(w);
300 glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
302 /* this might cause an error, oh well */
304 glBindTexture(GL_TEXTURE_2D, wd->texname);
309 1 CARD8 opcode (X assigned)
310 1 16 GLX opcode (glXVendorPrivate)
312 4 1331 vendor specific opcode
314 4 GLX_DRAWABLE drawable
318 unsigned int len = (2 + 0) * sizeof(uint32_t);
323 xcb_glx_vendor_private(w->sc->dpy->conn,
326 len, (uint8_t*)data);
328 d->release_func(w->sc->dpy->xlib_dpy,
329 wd->glpixmap, GLX_FRONT_LEFT_EXT);
332 glBindTexture(GL_TEXTURE_2D, 0);
334 //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap);
335 glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap);
336 wd->glpixmap = XCB_NONE;
341 glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
346 static int attrs[] = {
347 GLX_TEXTURE_FORMAT_EXT,
352 px = window_get_pixmap(w);
353 depth = window_get_depth(w);
357 //printf("%x %d %x\n", px, depth, d->fbconfig[depth]);
358 if (!d->fbconfig[depth]) {
359 printf("no GL visual for depth %d\n", depth);
363 if (window_is_argb(w))
364 attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
366 attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
369 wd->glpixmap = xcb_generate_id(w->sc->dpy->conn);
370 printf("bind config 0x%x screen %d pixmap 0x%x glpixmap 0x%x "
372 d->fbconfig[depth], w->sc->num, px, wd->glpixmap,
373 sizeof(attrs)/sizeof(attrs[0]));
374 xcb_void_cookie_t ck =
375 xcb_glx_create_pixmap_checked(w->sc->dpy->conn, w->sc->num,
378 sizeof(attrs)/sizeof(attrs[0] - 1),
380 xcb_generic_error_t *err = xcb_request_check(w->sc->dpy->conn, ck);
382 display_error(w->sc->dpy, err);
384 wd->glpixmap = XCB_NONE;
388 wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy,
393 glBindTexture(GL_TEXTURE_2D, wd->texname);
398 1 CARD8 opcode (X assigned)
399 1 16 GLX opcode (glXVendorPrivate)
401 4 1330 vendor specific opcode
403 4 GLX_DRAWABLE drawable
405 4 CARD32 num_attributes
406 4*n LISTofATTRIBUTE_PAIR attribute, value pairs.
409 unsigned int len = (3 + 0) * sizeof(uint32_t);
415 xcb_glx_vendor_private(w->sc->dpy->conn,
418 len, (uint8_t*)data);
420 d->bind_func(w->sc->dpy->xlib_dpy,
421 wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
424 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
425 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
428 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
429 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
431 glBindTexture(GL_TEXTURE_2D, 0);
435 glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
439 px = screen_get_root_pixmap(sc);
445 glxrender_window_resize(d_window_t *w)
450 d = screen_find_plugin_data(w->sc, plugin_id);
451 wd = window_find_plugin_data(w, plugin_id);
457 glxrender_free_window_pixmap(w, d, wd);
461 glxrender_window_reshape(d_window_t *w)
466 d = screen_find_plugin_data(w->sc, plugin_id);
467 wd = window_find_plugin_data(w, plugin_id);
470 d->window_reshape(w);
473 glxrender_free_window_pixmap(w, d, wd);
477 glxrender_root_pixmap_change(d_screen_t *sc)
481 d = screen_find_plugin_data(sc, plugin_id);
482 int a; /* XXX free things here */
483 //if (d->root_picture) {
484 // xcb_render_free_picture(sc->dpy->conn, d->root_picture);
485 // d->root_picture = XCB_NONE;
489 d->screen_root_pixmap_change(sc);
493 glxrender_paint(d_screen_t *sc)
495 data_t *d = screen_find_plugin_data(sc, plugin_id);
498 //printf("painting\n");
502 for (it = list_bottom(sc->stacking); it; it = it->prev) {
503 d_window_t *w = it->data;
505 if (!window_is_input_only(w) &&
506 (window_is_mapped(w) || window_is_zombie(w)))
508 int x, y, width, height, bwidth;
512 window_get_area(w, &x, &y, &width, &height, &bwidth);
514 if (!(x < sc->super->width_in_pixels &&
515 y < sc->super->height_in_pixels &&
516 (x + width > 0 || x + width + d->xshadowoff > 0) &&
517 (y + height > 0 || y + height + d->yshadowoff > 0)))
522 opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
524 wd = window_find_plugin_data(w, plugin_id);
526 paint_shadow(w, d, wd, x, y, width, height, bwidth);
527 paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
531 //xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
532 glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay);
534 /* call the function we replaced in the chain */
539 paint_root(d_screen_t *sc, data_t *d)
541 //if (!d->root_picture)
542 glxrender_update_root_pixmap(sc, d);
544 glClear(GL_COLOR_BUFFER_BIT);
548 paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
549 int x, int y, int width, int height, int bwidth)
551 uint16_t o = window_get_opacity(w);
554 glxrender_update_window_pixmap(w, d, wd);
556 glBindTexture(GL_TEXTURE_2D, wd->texname);
561 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
562 glColor4us(o, o, o, o);
568 glVertex2i(x + width + bwidth, y);
570 glVertex2i(x + width + bwidth,
571 y + height + bwidth);
573 glVertex2i(x, y + height + bwidth);
577 glBindTexture(GL_TEXTURE_2D, 0);
580 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
581 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
587 paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
588 int x, int y, int width, int height, int bwidth)
590 int xoff = d->xshadowoff;
591 int yoff = d->yshadowoff;
592 float alpha = d->shadowalpha;
594 alpha *= window_get_opacity(w);
597 if (alpha < 0.01) return;
600 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
602 glColor4f(0.0f, 0.0f, 0.0f, alpha);
604 if (window_is_argb(w)) {
605 /* shape the shadow to the window's alpha levels */
606 glBindTexture(GL_TEXTURE_2D, wd->texname);
609 glVertex2i(x + xoff, y + yoff);
611 glVertex2i(x + width + bwidth + xoff, y + yoff);
613 glVertex2i(x + width + bwidth + xoff,
614 y + height + bwidth + yoff);
616 glVertex2i(x + xoff, y + height + bwidth + yoff);
620 glBindTexture(GL_TEXTURE_2D, 0);
623 /* draw a solid rectangle */
624 glRecti(x + xoff, y + yoff,
625 x + width + bwidth - 1 + xoff, y + height + bwidth - 1 + yoff);
627 glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
628 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);