From: Dana Jansens Date: Sun, 16 Mar 2008 01:12:36 +0000 (-0400) Subject: use the depth buffer when rendering in gl, but it's pretty slow right now. add ... X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=e68f4eac036627a2f31583849329b5daff912bb7;p=dana%2Fdcompmgr.git use the depth buffer when rendering in gl, but it's pretty slow right now. add --gl and --xrender to choose which rendering method you want to use, and --help for help. --- diff --git a/dcompmgr.c b/dcompmgr.c index fc18efe..d0ee687 100644 --- a/dcompmgr.c +++ b/dcompmgr.c @@ -22,17 +22,52 @@ #include #include +typedef enum { + USE_RENDER, + USE_OPENGL +} render_type_t; + typedef struct { - int foo; + render_type_t render; } d_options_t; static gboolean quit = FALSE; static gboolean running = FALSE; +static void +print_help(void) +{ + const char *s = +"\n" +"Usage: dcompmgr [OPTIONS]\n" +"\n" +"Options:\n" +" --gl Use OpenGL for drawing\n" +" --xrender Use XRender for drawing (the default)\n" +"\n" +"Copyright (C) 2008 Dana Jansens\n" +"\n" +""; + printf(s); +} + static void read_options(int argc, char **argv, d_options_t *opts) { - opts->foo = argc && argv; + int i; + + opts->render = USE_RENDER; + + for (i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--gl") == 0) + opts->render = USE_OPENGL; + else if (strcmp(argv[i], "--xrender") == 0) + opts->render = USE_RENDER; + else if (strcmp(argv[i], "--help") == 0) { + print_help(); + exit(0); + } + } } static void @@ -399,7 +434,7 @@ run(d_display_t *dpy) } static void -setup_functions(d_display_t *dpy) +setup_functions(d_display_t *dpy, d_options_t *opts) { d_list_it_t *it; @@ -410,8 +445,12 @@ setup_functions(d_display_t *dpy) /* these can be plugins.. */ id = 1; - glxrender_init(sc, id++); - //render_init(sc, id++); + + if (opts->render == USE_RENDER) + render_init(sc, id++); + else + glxrender_init(sc, id++); + fade_init(sc, id++); } } @@ -426,7 +465,7 @@ cleanup_functions(d_display_t *dpy) /* these can be plugins.. */ fade_free(sc); - //render_free(sc); + render_free(sc); glxrender_free(sc); } } @@ -483,7 +522,7 @@ main(int argc, char **argv) signal(SIGTERM, signal_quit_handler); signal(SIGQUIT, signal_quit_handler); - setup_functions(dpy); + setup_functions(dpy, &opts); { /* some of the windows may already be visible */ diff --git a/glxrender.c b/glxrender.c index 1c5ad24..ed17279 100644 --- a/glxrender.c +++ b/glxrender.c @@ -33,6 +33,7 @@ typedef struct { 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_move)(d_window_t *w); void (*window_resize)(d_window_t *w); void (*window_reshape)(d_window_t *w); @@ -65,11 +66,11 @@ 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); -static void paint_shadow(d_window_t *w, data_t *d, window_data_t *wd, - int x, int y); + GLfloat z); +static void paint_shadow(data_t *d, window_data_t *wd, GLfloat z); static void glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd); +static void glxrender_update_window_region(d_window_t *w, window_data_t *wd); static void glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd); static void glxrender_free_root_pixmap(d_screen_t *sc, data_t *d); @@ -77,6 +78,7 @@ 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_move(d_window_t *window); static void glxrender_window_resize(d_window_t *window); static void glxrender_window_reshape(d_window_t *window); @@ -100,6 +102,7 @@ glxrender_init(d_screen_t *sc, int id) d->window_show = sc->window_show; d->window_zombie_dead = sc->window_zombie_dead; d->window_resize = sc->window_resize; + d->window_move = sc->window_move; d->window_reshape = sc->window_reshape; screen_add_plugin_data(sc, plugin_id, d); @@ -108,6 +111,7 @@ glxrender_init(d_screen_t *sc, int id) sc->window_show = glxrender_window_show; sc->window_zombie_dead = glxrender_window_zombie_dead; sc->window_resize = glxrender_window_resize; + sc->window_move = glxrender_window_move; sc->window_reshape = glxrender_window_reshape; d->shadowalpha = 0.2f; /* 20% */ @@ -137,13 +141,14 @@ glxrender_init(d_screen_t *sc, int id) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay); d->bind_func = (BindEXTFunc) @@ -245,8 +250,10 @@ void glxrender_free(d_screen_t *sc) { data_t *d = screen_find_plugin_data(sc, plugin_id); - glxrender_free_root_pixmap(sc, d); - free(d); + if (d) { + glxrender_free_root_pixmap(sc, d); + free(d); + } screen_remove_plugin_data(sc, plugin_id); } @@ -328,6 +335,8 @@ glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd) glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap); wd->glpixmap = XCB_NONE; + } + if (wd->nrects) { free(wd->texcoords); free(wd->vertices); wd->nrects = 0; @@ -394,25 +403,61 @@ glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd) glBindTexture(GL_TEXTURE_2D, 0); - { - int x, y, width, height, bwidth; - - window_get_area(w, &x, &y, &width, &height, &bwidth); - - wd->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * 4); - wd->texcoords[LEFT] = 0.0f; - wd->texcoords[TOP] = 0.0f; - wd->texcoords[RIGHT] = 1.0f; - wd->texcoords[BOTTOM] = 1.0f; + glxrender_update_window_region(w, wd); +} - wd->vertices = (GLint*)malloc(sizeof(GLint) * 4); - wd->vertices[LEFT] = 0; - wd->vertices[TOP] = 0; - wd->vertices[RIGHT] = width + bwidth; - wd->vertices[BOTTOM] = height + bwidth; +static void +glxrender_update_window_region(d_window_t *w, window_data_t *wd) +{ + xcb_xfixes_region_t reg; + xcb_xfixes_fetch_region_cookie_t ck; + xcb_xfixes_fetch_region_reply_t *rep; + xcb_rectangle_t area, *rects; + int nrects, i, x, y, wid, hei, bwid; + + reg = window_get_region(w); + ck = xcb_xfixes_fetch_region_unchecked(w->sc->dpy->conn, reg); + + window_get_area(w, &x, &y, &wid, &hei, &bwid); + area.x = x; + area.y = y; + area.width = wid + bwid * 2; + area.height = hei + bwid * 2; + + rep = xcb_xfixes_fetch_region_reply(w->sc->dpy->conn, ck, NULL); + if (!rep) { + rects = &area; + nrects = 1; + } + else { + rects = xcb_xfixes_fetch_region_rectangles(rep); + nrects = xcb_xfixes_fetch_region_rectangles_length(rep); + } - wd->nrects = 1; + wd->texcoords = (GLfloat*)malloc(sizeof(GLfloat) * (nrects * 4)); + wd->vertices = (GLint*)malloc(sizeof(GLint) * (nrects * 4)); + wd->nrects = nrects; + + for (i = 0; i < nrects * 4; i += 4) { + wd->texcoords[i+LEFT] = + (GLfloat)(rects[i].x - area.x) / (GLfloat)area.width; + wd->texcoords[i+TOP] = + (GLfloat)(rects[i].y - area.y) / (GLfloat)area.height; + wd->texcoords[i+RIGHT] = + (GLfloat)(rects[i].x - area.x + rects[i].width) / + (GLfloat)area.width; + wd->texcoords[i+BOTTOM] = + (GLfloat)(rects[i].y - area.y + rects[i].height) / + (GLfloat)area.height; + + wd->vertices[i+LEFT] = rects[i].x; + wd->vertices[i+TOP] = rects[i].y; + wd->vertices[i+RIGHT] = rects[i].x + rects[i].width; + wd->vertices[i+BOTTOM] = rects[i].y + rects[i].height; } + + if (rep) + free(rep); } static void @@ -468,6 +513,22 @@ glxrender_window_resize(d_window_t *w) glxrender_update_window_pixmap(w, d, wd); } +static void +glxrender_window_move(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_move(w); + + assert(wd != NULL); + glxrender_update_window_region(w, wd); +} + static void glxrender_window_reshape(d_window_t *w) { @@ -502,11 +563,55 @@ glxrender_paint(d_screen_t *sc) { data_t *d = screen_find_plugin_data(sc, plugin_id); d_list_it_t *it; + GLfloat z; //printf("painting\n"); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* add 0.1f to keep everything above the root */ + z = list_length(sc->stacking) * 0.1f + 0.1f; + for (it = list_top(sc->stacking); it; it = it->next) { + 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; + + if (opaque) { + wd = window_find_plugin_data(w, plugin_id); + + //glPushMatrix(); + + paint_window(w, d, wd, z + 0.05f); + + //glPopMatrix(); + } + + z -= 0.1f; + } + } + paint_root(sc, d); + glEnable(GL_BLEND); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + for (it = list_bottom(sc->stacking); it; it = it->prev) { d_window_t *w = it->data; @@ -516,6 +621,8 @@ glxrender_paint(d_screen_t *sc) int x, y, width, height, bwidth; gboolean opaque; window_data_t *wd; + uint16_t opac; + GLfloat alpha; window_get_area(w, &x, &y, &width, &height, &bwidth); @@ -527,22 +634,37 @@ glxrender_paint(d_screen_t *sc) continue; } - opaque = !window_is_argb(w) && window_get_opacity(w) == 0xffff; + opac = window_get_opacity(w); + opaque = !window_is_argb(w) && opac == 0xffff; wd = window_find_plugin_data(w, plugin_id); - glPushMatrix(); + //glPushMatrix(); + + /* black shadow */ + alpha = d->shadowalpha; + alpha *= opac; + alpha /= 0xffff; + if (alpha >= 0.01) { + glColor4f(0.0f, 0.0f, 0.0f, alpha); + paint_shadow(d, wd, z); + } - glTranslatef(d->xshadowoff, d->yshadowoff, 0.0f); - paint_shadow(w, d, wd, x, y); + if (!opaque) { + glColor4us(opac, opac, opac, opac); + paint_window(w, d, wd, z + 0.05f); + } - glTranslatef(-d->xshadowoff, -d->yshadowoff, 0.0f); - paint_window(w, d, wd, opaque, x, y); + //glPopMatrix(); - glPopMatrix(); + z += 0.1f; } } + glColor4f(0.0f, 0.0f, 0.0f, 0.0f); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glDisable(GL_BLEND); + //xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay); glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay); @@ -556,28 +678,24 @@ paint_root(d_screen_t *sc, data_t *d) if (!d->root_glpixmap) glxrender_update_root_pixmap(sc, d); - glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, d->root_texname); glBegin(GL_QUADS); glTexCoord2f(0, 0); - glVertex2i(0, 0); + glVertex3i(0, 0, 0); glTexCoord2f(1, 0); - glVertex2i(sc->super->width_in_pixels, 0); + glVertex3i(sc->super->width_in_pixels, 0, 0); glTexCoord2f(1, 1); - glVertex2i(sc->super->width_in_pixels, sc->super->height_in_pixels); + glVertex3i(sc->super->width_in_pixels, sc->super->height_in_pixels, 0); glTexCoord2f(0, 1); - glVertex2i(0, sc->super->height_in_pixels); + glVertex3i(0, sc->super->height_in_pixels, 0); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); } static void -paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque, - int x, int y) +paint_window(d_window_t *w, data_t *d, window_data_t *wd, GLfloat z) { - uint16_t o = window_get_opacity(w); int i; if (!wd->glpixmap) @@ -587,73 +705,46 @@ paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque, glBindTexture(GL_TEXTURE_2D, wd->texname); - if (!opaque) { - glEnable(GL_BLEND); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glColor4us(o, o, o, o); - } - glBegin(GL_QUADS); for (i = 0; i < wd->nrects * 4; i += 4) { - // XXX use glVertex3i glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]); - glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+TOP]); + glVertex3f(wd->vertices[i+LEFT], wd->vertices[i+TOP], z); glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]); - glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+TOP]); + glVertex3f(wd->vertices[i+RIGHT], wd->vertices[i+TOP], z); glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]); - glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+BOTTOM]); + glVertex3f(wd->vertices[i+RIGHT], wd->vertices[i+BOTTOM], z); glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]); - glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+BOTTOM]); + glVertex3f(wd->vertices[i+LEFT], wd->vertices[i+BOTTOM], z); } glEnd(); glBindTexture(GL_TEXTURE_2D, 0); - - if (!opaque) { - glColor4f(0.0f, 0.0f, 0.0f, 0.0f); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDisable(GL_BLEND); - } } static void -paint_shadow(d_window_t *w, data_t *d, window_data_t *wd, int x, int y) +paint_shadow(data_t *d, window_data_t *wd, GLfloat z) { - float alpha = d->shadowalpha; + int xoff = d->xshadowoff; + int yoff = d->yshadowoff; int i; if (wd->nrects < 1) return; - alpha *= window_get_opacity(w); - alpha /= 0xffff; - - if (alpha < 0.01) return; - - glEnable(GL_BLEND); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - /* black shadow */ - glColor4f(0.0f, 0.0f, 0.0f, alpha); - /* shape the shadow to the window */ glBindTexture(GL_TEXTURE_2D, wd->texname); glBegin(GL_QUADS); for (i = 0; i < wd->nrects * 4; i += 4) { glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+TOP]); - glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+TOP]); + glVertex3f(xoff+wd->vertices[i+LEFT], yoff+wd->vertices[i+TOP], z); glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+TOP]); - glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+TOP]); + glVertex3f(xoff+wd->vertices[i+RIGHT], yoff+wd->vertices[i+TOP], z); glTexCoord2f(wd->texcoords[i+RIGHT], wd->texcoords[i+BOTTOM]); - glVertex2i(x + wd->vertices[i+RIGHT], y + wd->vertices[i+BOTTOM]); + glVertex3f(xoff+wd->vertices[i+RIGHT], yoff+wd->vertices[i+BOTTOM], z); glTexCoord2f(wd->texcoords[i+LEFT], wd->texcoords[i+BOTTOM]); - glVertex2i(x + wd->vertices[i+LEFT], y + wd->vertices[i+BOTTOM]); + glVertex3f(xoff+wd->vertices[i+LEFT], yoff+wd->vertices[i+BOTTOM], z); } glEnd(); glBindTexture(GL_TEXTURE_2D, 0); - - glColor4f(0.0f, 0.0f, 0.0f, 0.0f); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDisable(GL_BLEND); } diff --git a/render.c b/render.c index 552039c..26bbe60 100644 --- a/render.c +++ b/render.c @@ -168,17 +168,19 @@ void render_free(d_screen_t *sc) { data_t *d = screen_find_plugin_data(sc, plugin_id); - free(d->pict_formats); - xcb_render_free_picture(sc->dpy->conn, d->solid_bg); - if (d->root_picture) - xcb_render_free_picture(sc->dpy->conn, d->root_picture); - xcb_render_free_picture(sc->dpy->conn, d->overlay_picture); - xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer); - xcb_xfixes_destroy_region(sc->dpy->conn, d->all_region); - xcb_xfixes_destroy_region(sc->dpy->conn, d->damaged_region); - xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region); - xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_paint_region); - free(d); + if (d) { + free(d->pict_formats); + xcb_render_free_picture(sc->dpy->conn, d->solid_bg); + if (d->root_picture) + xcb_render_free_picture(sc->dpy->conn, d->root_picture); + xcb_render_free_picture(sc->dpy->conn, d->overlay_picture); + xcb_render_free_picture(sc->dpy->conn, d->overlay_buffer); + xcb_xfixes_destroy_region(sc->dpy->conn, d->all_region); + xcb_xfixes_destroy_region(sc->dpy->conn, d->damaged_region); + xcb_xfixes_destroy_region(sc->dpy->conn, d->paint_region); + xcb_xfixes_destroy_region(sc->dpy->conn, d->shadow_paint_region); + free(d); + } screen_remove_plugin_data(sc, plugin_id); } diff --git a/window.c b/window.c index f9a3d23..7b5230b 100644 --- a/window.c +++ b/window.c @@ -153,6 +153,7 @@ window_update_user_opacity(d_window_t *pubw) w->sc->dpy->a.net_wm_window_opacity, w->sc->dpy->a.cardinal, 0, 1); w->waiting_opac = TRUE; + xcb_flush(w->sc->dpy->conn); } static void @@ -172,6 +173,7 @@ window_update_region(d_window_priv_t *w) w->id, XCB_SHAPE_SK_BOUNDING); window_get_area((d_window_t*)w, &x, &y, &wi, &hei, &bw); xcb_xfixes_translate_region(w->sc->dpy->conn, w->region, x+bw, y+bw); + xcb_flush(w->sc->dpy->conn); } static void