From: Dana Jansens Date: Mon, 10 Mar 2008 02:19:56 +0000 (-0400) Subject: initialize gl on the overlay window X-Git-Url: http://git.openbox.org/?p=dana%2Fdcompmgr.git;a=commitdiff_plain;h=4d828729d15d59ec77c4917565e974757218c977 initialize gl on the overlay window --- diff --git a/Makefile b/Makefile index 311914a..65ac859 100644 --- 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) diff --git a/dcompmgr.c b/dcompmgr.c index 8dcaa1f..47c6a1d 100644 --- a/dcompmgr.c +++ b/dcompmgr.c @@ -9,6 +9,7 @@ /* these can be plugins */ #include "render.h" +#include "glxrender.h" #include "fade.h" #include @@ -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 index 0000000..d9fdf69 --- /dev/null +++ b/glxrender.c @@ -0,0 +1,459 @@ +#include "efence.h" + +#include "render.h" +#include "screen.h" +#include "window.h" +#include "display.h" +#include "list.h" +#include +#include +#include + +#include +//#include +//#include +#include +#include + +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 index 0000000..7d75770 --- /dev/null +++ b/glxrender.h @@ -0,0 +1,13 @@ +#ifndef dc__glxrender_h +#define dc__glxrender_h + +#include + +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 diff --git a/screen.c b/screen.c index 8314c00..3048703 100644 --- 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; diff --git a/screen.h b/screen.h index 49d0ed2..12fe915 100644 --- 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;