--- /dev/null
+#include "efence.h"
+
+#include "render.h"
+#include "screen.h"
+#include "window.h"
+#include "display.h"
+#include "list.h"
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include <xcb/glx.h>
+//#include <GL/glext.h>
+//#include <GL/glxext.h>
+#include <GL/glxtokens.h>
+#include <GL/gl.h>
+
+static int plugin_id;
+
+typedef struct {
+ void (*screen_paint)(d_screen_t *sc);
+ void (*screen_root_pixmap_change)(d_screen_t *sc);
+ void (*window_show)(d_window_t *w);
+ void (*window_zombie_dead)(d_window_t *w);
+ void (*window_resize)(d_window_t *w);
+ void (*window_reshape)(d_window_t *w);
+
+ uint16_t shadowalpha;
+ int xshadowoff;
+ int yshadowoff;
+
+ xcb_glx_context_t context;
+ xcb_glx_context_tag_t context_tag;
+} data_t;
+
+typedef struct {
+ GLuint texname;
+ xcb_glx_pixmap_t glpixmap;
+} window_data_t;
+
+static gboolean glxrender_check_visual(d_screen_t *sc);
+
+static void glxrender_paint(d_screen_t *sc);
+static void glxrender_root_pixmap_change(d_screen_t *sc);
+static void paint_root(d_screen_t *sc, data_t *d);
+static void paint_window(d_window_t *window, data_t *d, window_data_t *wd,
+ gboolean opaque, int x, int y, int width,
+ int height, int bwidth);
+static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
+ int x, int y, int width, int height, int bwidth);
+static void glxrender_update_window_pixmap(d_window_t *w, data_t *d,
+ window_data_t *wd);
+static void glxrender_free_window_pixmap(d_window_t *w, window_data_t *wd);
+static void glxrender_update_root_pixmap(d_screen_t *sc, data_t *d);
+
+static void glxrender_window_show(d_window_t *window);
+static void glxrender_window_zombie_dead(d_window_t *window);
+static void glxrender_window_resize(d_window_t *window);
+static void glxrender_window_reshape(d_window_t *window);
+
+void
+glxrender_init(d_screen_t *sc, int id)
+{
+ xcb_void_cookie_t ck;
+ xcb_generic_error_t *err;
+ xcb_glx_make_current_cookie_t curck;
+ xcb_glx_make_current_reply_t *currep;
+
+ plugin_id = id;
+
+ data_t *d = malloc(sizeof(data_t));
+ d->screen_paint = sc->screen_paint;
+ d->screen_root_pixmap_change = sc->screen_root_pixmap_change;
+ d->window_show = sc->window_show;
+ d->window_zombie_dead = sc->window_zombie_dead;
+ d->window_resize = sc->window_resize;
+ d->window_reshape = sc->window_reshape;
+ screen_add_plugin_data(sc, plugin_id, d);
+
+ sc->screen_paint = glxrender_paint;
+ sc->screen_root_pixmap_change = glxrender_root_pixmap_change;
+ sc->window_show = glxrender_window_show;
+ sc->window_zombie_dead = glxrender_window_zombie_dead;
+ sc->window_resize = glxrender_window_resize;
+ sc->window_reshape = glxrender_window_reshape;
+
+ d->shadowalpha = 0x3333; /* 20% */
+ d->xshadowoff = 2;
+ d->yshadowoff = 2;
+
+ if (!glxrender_check_visual(sc)) {
+ printf("unable to use the overlay window for GLX\n");
+ exit(1);
+ }
+
+ d->context = xcb_generate_id(sc->dpy->conn);
+ ck = xcb_glx_create_context_checked(sc->dpy->conn, d->context,
+ sc->overlay_visual, sc->num,
+ XCB_NONE, TRUE);
+ if ((err = xcb_request_check(sc->dpy->conn, ck))) {
+ printf("context creation failed\n");
+ display_error(sc->dpy, err);
+ free(err);
+ exit(1);
+ }
+
+ curck = xcb_glx_make_current(sc->dpy->conn,
+ sc->overlay, d->context, XCB_NONE);
+ currep = xcb_glx_make_current_reply(sc->dpy->conn, curck, &err);
+ if (!currep) {
+ if (err) {
+ display_error(sc->dpy, err);
+ free(err);
+ }
+ printf("make current failed\n");
+ exit(1);
+ }
+ d->context_tag = currep->context_tag;
+ free(currep);
+
+ glViewport(0, 0, sc->super.width_in_pixels, sc->super.height_in_pixels);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, sc->super.width_in_pixels, sc->super.height_in_pixels,
+ 0.0, -1.0, 100.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glClear(GL_COLOR_BUFFER_BIT);
+ glEnable(GL_TEXTURE_2D);
+ xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
+ glClearColor(0.4, 0.4, 0.4, 1.0);
+
+/*
+ glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+ glEnable(GL_BLEND);
+*/
+}
+
+static gboolean
+glxrender_check_visual(d_screen_t *sc)
+{
+ xcb_glx_get_visual_configs_cookie_t ck;
+ xcb_glx_get_visual_configs_reply_t *rep;
+ gboolean ok = FALSE;
+
+ ck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
+ rep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, ck, NULL);
+ if (rep) {
+ uint32_t *list;
+ unsigned int i, j;
+ int len;
+ gboolean depth, doublebuffer, rgba;
+
+/*
+ static int config[] = {
+ GLX_DEPTH_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ GLX_RGBA,
+ XCB_NONE
+ };
+*/
+
+ list = xcb_glx_get_visual_configs_property_list(rep);
+ len = xcb_glx_get_visual_configs_property_list_length(rep);
+ printf("got %d %d, %d\n", rep->num_visuals, rep->num_properties, len);
+
+ for (i = 0; i < rep->num_visuals; ++i) {
+ const int
+ ID = 0,
+ CLASS = 1,
+ USE_GL = 2,
+ RED_DEPTH = 3,
+ BLUE_DEPTH = 4,
+ GREEN_DEPTH = 5,
+ ALPHA_DEPTH = 6,
+ DOUBLE_BUFFER = 11,
+ DEPTH_SIZE = 14;
+ int s = i * rep->num_properties;
+
+ depth = doublebuffer = rgba = FALSE;
+
+ /* look for the overlay's visual */
+ if (list[s+ID] != sc->overlay_visual) continue;
+
+ printf("0x%x ", list[s+ID]);
+ printf("%d ", list[s+CLASS]);
+ printf("%s ", list[s+USE_GL] ? "yes" : "no");
+ printf("%d ", list[s+RED_DEPTH]);
+ printf("%d ", list[s+GREEN_DEPTH]);
+ printf("%d ", list[s+BLUE_DEPTH]);
+ printf("%d ", list[s+ALPHA_DEPTH]);
+ printf("%s ", list[s+DOUBLE_BUFFER] ? "yes" : "no");
+ printf("%d ", list[s+DEPTH_SIZE]);
+
+ printf("\n");
+ for (j = 0; j < rep->num_properties; ++j)
+ printf("%d ", list[i*rep->num_properties+j]);
+ printf("\n");
+
+ if (!list[s+USE_GL]) {
+ printf("overlay visual does not support GL\n");
+ break;
+ }
+
+ if (!list[s+DOUBLE_BUFFER]) {
+ printf("overlay visual is not double buffered\n");
+ break;
+ }
+
+ ok = TRUE; /* yippa ! */
+ }
+
+ free(rep);
+ }
+ return ok;
+}
+
+void
+glxrender_free(d_screen_t *sc)
+{
+ data_t *d = screen_find_plugin_data(sc, plugin_id);
+ free(d);
+ screen_remove_plugin_data(sc, plugin_id);
+}
+
+int
+glxrender_next_timeout(struct d_screen *sc, struct timeval *tv)
+{
+ (void)sc;
+ (void)tv;
+ return FALSE;
+}
+
+void
+glxrender_timeout(struct d_screen *sc, const struct timeval *now)
+{
+ (void)sc; (void)now;
+}
+
+void
+glxrender_window_free_data(d_window_t *w, window_data_t *wd)
+{
+ glxrender_free_window_pixmap(w, wd);
+ glDeleteTextures(1, &wd->texname);
+ free(wd);
+}
+
+static void
+glxrender_window_show(d_window_t *w)
+{
+ data_t *d;
+ window_data_t *wd;
+
+ d = screen_find_plugin_data(w->sc, plugin_id);
+
+ /* pass it on */
+ d->window_show(w);
+
+ wd = window_find_plugin_data(w, plugin_id);
+ if (wd)
+ glxrender_window_free_data(w, wd);
+
+ wd = malloc(sizeof(window_data_t));
+ glGenTextures(1, &wd->texname);
+
+ window_add_plugin_data(w, plugin_id, wd);
+}
+
+static void
+glxrender_window_zombie_dead(d_window_t *w)
+{
+ data_t *d;
+ window_data_t *wd;
+
+ d = screen_find_plugin_data(w->sc, plugin_id);
+ wd = window_find_plugin_data(w, plugin_id);
+ if (wd) {
+ glxrender_window_free_data(w, wd);
+ window_remove_plugin_data(w, plugin_id);
+ }
+
+ /* pass it on */
+ d->window_zombie_dead(w);
+}
+
+static void
+glxrender_free_window_pixmap(d_window_t *w, window_data_t *wd)
+{
+ /* this might cause an error, oh well */
+ //if (wd->picture) {
+ // xcb_render_free_picture(w->sc->dpy->conn, wd->picture);
+ // wd->picture = XCB_NONE;
+ //}
+}
+
+static void
+glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd)
+{
+ xcb_pixmap_t px;
+
+ px = window_get_pixmap(w);
+}
+
+static void
+glxrender_update_root_pixmap(d_screen_t *sc, data_t *d)
+{
+ xcb_pixmap_t px;
+
+ px = screen_get_root_pixmap(sc);
+ if (px) {
+ }
+}
+
+static void
+glxrender_window_resize(d_window_t *w)
+{
+ data_t *d;
+ window_data_t *wd;
+
+ d = screen_find_plugin_data(w->sc, plugin_id);
+ wd = window_find_plugin_data(w, plugin_id);
+
+ /* pass it on */
+ d->window_resize(w);
+
+ assert(wd != NULL);
+ glxrender_free_window_pixmap(w, wd);
+}
+
+static void
+glxrender_window_reshape(d_window_t *w)
+{
+ data_t *d;
+ window_data_t *wd;
+
+ d = screen_find_plugin_data(w->sc, plugin_id);
+ wd = window_find_plugin_data(w, plugin_id);
+
+ /* pass it on */
+ d->window_reshape(w);
+
+ assert(wd != NULL);
+ glxrender_free_window_pixmap(w, wd);
+}
+
+static void
+glxrender_root_pixmap_change(d_screen_t *sc)
+{
+ data_t *d;
+
+ d = screen_find_plugin_data(sc, plugin_id);
+ int a; /* XXX free things here */
+ //if (d->root_picture) {
+ // xcb_render_free_picture(sc->dpy->conn, d->root_picture);
+ // d->root_picture = XCB_NONE;
+ //}
+
+ /* pass it on */
+ d->screen_root_pixmap_change(sc);
+}
+
+static void
+glxrender_paint(d_screen_t *sc)
+{
+ data_t *d = screen_find_plugin_data(sc, plugin_id);
+ d_list_it_t *it;
+
+ paint_root(sc, d);
+
+ for (it = list_bottom(sc->stacking); it; it = it->prev) {
+ d_window_t *w = it->data;
+
+ if (!window_is_input_only(w) &&
+ (window_is_mapped(w) || window_is_zombie(w)))
+ {
+ int x, y, width, height, bwidth;
+ gboolean opaque;
+ window_data_t *wd;
+
+ window_get_area(w, &x, &y, &width, &height, &bwidth);
+
+ if (!(x < sc->super.width_in_pixels &&
+ y < sc->super.height_in_pixels &&
+ (x + width > 0 || x + width + d->xshadowoff > 0) &&
+ (y + height > 0 || y + height + d->yshadowoff > 0)))
+ {
+ continue;
+ }
+
+ opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff;
+
+ wd = window_find_plugin_data(w, plugin_id);
+
+ paint_shadow(w, d, wd, x, y, width, height, bwidth);
+ paint_window(w, d, wd, opaque, x, y, width, height, bwidth);
+ }
+ }
+
+ xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay);
+
+ /* call the function we replaced in the chain */
+ d->screen_paint(sc);
+}
+
+static void
+paint_root(d_screen_t *sc, data_t *d)
+{
+ //if (!d->root_picture)
+ glxrender_update_root_pixmap(sc, d);
+}
+
+static void
+paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque,
+ int x, int y, int width, int height, int bwidth)
+{
+ //if (!wd->picture)
+ glxrender_update_window_pixmap(w, d, wd);
+
+ //printf("-- paint window 0x%x picture 0x%x --\n", w->id, wd->picture);
+/*
+ if (wd->picture) {
+ xcb_render_picture_t alphamap;
+ int op;
+
+ if (opaque) {
+ op = XCB_RENDER_PICT_OP_SRC;
+ alphamap = XCB_NONE;
+ }
+ else {
+ op = XCB_RENDER_PICT_OP_OVER;
+ alphamap = wd->alpha_picture;
+ }
+
+ xcb_render_composite(w->sc->dpy->conn,
+ op,
+ wd->picture,
+ alphamap,
+ d->overlay_buffer,
+ 0, 0, 0, 0,
+ x, y, width + bwidth*2, height + bwidth *2);
+ }
+*/
+}
+
+static void
+paint_shadow(d_window_t *w, data_t *d, window_data_t *wd,
+ int x, int y, int width, int height, int bwidth)
+{
+/*
+ xcb_render_composite(w->sc->dpy->conn,
+ XCB_RENDER_PICT_OP_OVER,
+ wd->shadow_picture,
+ wd->picture,
+ d->overlay_buffer,
+ 0, 0, 0, 0,
+ x+d->xshadowoff, y+d->yshadowoff,
+ width + bwidth*2, height + bwidth *2);
+*/
+}