initialize gl on the overlay window
authorDana Jansens <danakj@orodu.net>
Mon, 10 Mar 2008 02:19:56 +0000 (22:19 -0400)
committerDana Jansens <danakj@orodu.net>
Mon, 10 Mar 2008 02:19:56 +0000 (22:19 -0400)
Makefile
dcompmgr.c
glxrender.c [new file with mode: 0644]
glxrender.h [new file with mode: 0644]
screen.c
screen.h

index 311914a..65ac859 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,9 +10,9 @@ PLIBS=
 EFLAGS=-DEFENCE
 ELIBS=-lefence
 
-CFLAGS=$(shell pkg-config --cflags xcb-composite xcb-damage glib-2.0) -ggdb -W -Wall $(PFLAGS)
+CFLAGS=$(shell pkg-config --cflags xcb-glx xcb-composite xcb-damage glib-2.0) -ggdb -W -Wall $(PFLAGS)
 LDFLAGS=$(PFLAGS)
-LIBS=$(shell pkg-config --libs xcb-composite xcb-damage glib-2.0) $(PLIBS)
+LIBS=$(shell pkg-config --libs xcb-glx xcb-composite xcb-damage glib-2.0) -lGL $(PLIBS)
 
 dcompmgr: $(objs)
        $(CC) -o $@ $^ $(LIBS) $(LDFLAGS)
index 8dcaa1f..47c6a1d 100644 (file)
@@ -9,6 +9,7 @@
 
 /* these can be plugins */
 #include "render.h"
+#include "glxrender.h"
 #include "fade.h"
 
 #include <glib.h>
@@ -277,6 +278,8 @@ timeouts(d_display_t *dpy, const struct timeval *now)
         d_screen_t *sc = it->data;
         struct timeval tv;
 
+        if (glxrender_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
+            glxrender_timeout(sc, now);
         if (render_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
             render_timeout(sc, now);
         if (fade_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
@@ -321,6 +324,12 @@ run(d_display_t *dpy)
             d_screen_t *sc = it->data;
             struct timeval next_timeout;
 
+            if (glxrender_next_timeout(sc, &next_timeout)) {
+                if (!ntime || time_compare(&next_timeout, &next) < 0) {
+                    next = next_timeout;
+                    ++ntime;
+                }
+            }
             if (render_next_timeout(sc, &next_timeout)) {
                 if (!ntime || time_compare(&next_timeout, &next) < 0) {
                     next = next_timeout;
@@ -401,7 +410,8 @@ setup_functions(d_display_t *dpy)
 
         /* these can be plugins.. */
         id = 1;
-        render_init(sc, id++);
+        glxrender_init(sc, id++);
+        //render_init(sc, id++);
         fade_init(sc, id++);
     }
 }
@@ -416,7 +426,8 @@ cleanup_functions(d_display_t *dpy)
 
         /* these can be plugins.. */
         fade_free(sc);
-        render_free(sc);
+        //render_free(sc);
+        glxrender_free(sc);
     }
 }
 
diff --git a/glxrender.c b/glxrender.c
new file mode 100644 (file)
index 0000000..d9fdf69
--- /dev/null
@@ -0,0 +1,459 @@
+#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);
+*/
+}
diff --git a/glxrender.h b/glxrender.h
new file mode 100644 (file)
index 0000000..7d75770
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef dc__glxrender_h
+#define dc__glxrender_h
+
+#include <sys/time.h>
+
+struct d_screen;
+
+void glxrender_init(struct d_screen *sc, int id);
+void glxrender_free(struct d_screen *sc);
+int glxrender_next_timeout(struct d_screen *sc, struct timeval *tv);
+void glxrender_timeout(struct d_screen *sc, const struct timeval *now);
+
+#endif
index 8314c00..3048703 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -185,6 +185,8 @@ screen_init(d_screen_t *sc)
     /* make the overlay window click-through */
     if (sc->overlay) {
         xcb_xfixes_region_t region;
+        xcb_get_window_attributes_cookie_t attr_ck;
+        xcb_get_window_attributes_reply_t *attr_rep;
 
         region = xcb_generate_id(sc->dpy->conn);
         xcb_xfixes_create_region(sc->dpy->conn, region, 0, NULL);
@@ -197,7 +199,17 @@ screen_init(d_screen_t *sc)
                                            XCB_SHAPE_SK_INPUT,
                                            0, 0, region);
         xcb_xfixes_destroy_region(sc->dpy->conn, region);
+
+        attr_ck = xcb_get_window_attributes(sc->dpy->conn, sc->overlay);
+        attr_rep = xcb_get_window_attributes_reply(sc->dpy->conn, attr_ck,
+                                                   NULL);
+        if (!attr_rep)
+            return FALSE;
+        sc->overlay_visual = attr_rep->visual;
+        free(attr_rep);
     }
+    else
+        return FALSE;
 #endif
 
     mask = SELECTION_MASK;
index 49d0ed2..12fe915 100644 (file)
--- a/screen.h
+++ b/screen.h
@@ -20,6 +20,7 @@ typedef struct d_screen {
     xcb_atom_t        selatom; /* ditto.. */
 
     xcb_window_t      overlay;
+    xcb_visualid_t    overlay_visual;
 
     struct timeval    next_repaint;
     gboolean          need_repaint;