From: Dana Jansens Date: Sat, 15 Mar 2008 22:07:49 +0000 (-0400) Subject: made the opengl renderer work - used Xlib's glX instead of xcb's which is all broked... X-Git-Url: http://git.openbox.org/?p=dana%2Fdcompmgr.git;a=commitdiff_plain;h=46fe04abe70e8d526395c67806902318082139de made the opengl renderer work - used Xlib's glX instead of xcb's which is all broked somehow. tricks were needed to make fading work, but it is good now! --- diff --git a/Makefile b/Makefile index 65ac859..63fc5ac 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,8 @@ sources = $(wildcard *.c) objs = $(sources:.c=.o) headers = $(wildcard *.h) +DFLAGS=-ggdb + # for profiling PFLAGS=-pg -fno-inline PLIBS= @@ -10,9 +12,9 @@ PLIBS= EFLAGS=-DEFENCE ELIBS=-lefence -CFLAGS=$(shell pkg-config --cflags xcb-glx 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) -W -Wall $(PFLAGS) $(DFLAGS) LDFLAGS=$(PFLAGS) -LIBS=$(shell pkg-config --libs xcb-glx xcb-composite xcb-damage glib-2.0) -lGL $(PLIBS) +LIBS=$(shell pkg-config --libs xcb-glx xcb-composite xcb-damage glib-2.0) -lGL $(PLIBS) -lX11 -lX11-xcb dcompmgr: $(objs) $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) diff --git a/display.c b/display.c index 5a18ec2..c3f25a4 100644 --- a/display.c +++ b/display.c @@ -213,12 +213,21 @@ d_display_t* display_open(const char *name) { d_display_t *dpy = NULL; - xcb_connection_t *conn; + xcb_connection_t *conn = NULL; + Display *xlib_dpy = NULL; - conn = xcb_connect(name, NULL); + xlib_dpy = XOpenDisplay(name); + if (xlib_dpy) { + conn = XGetXCBConnection(xlib_dpy); + + XSetEventQueueOwner(xlib_dpy, XCBOwnsEventQueue); + } + + //conn = xcb_connect(name, NULL); if (conn && !xcb_connection_has_error(conn)) { dpy = malloc(sizeof(d_display_t)); dpy->conn = conn; + dpy->xlib_dpy = xlib_dpy; dpy->ref = 1; dpy->fd = xcb_get_file_descriptor(conn); dpy->screens = list_new(); @@ -244,7 +253,8 @@ display_unref(d_display_t *dpy) screen_unref(it->data); list_unref(dpy->screens); - xcb_disconnect(dpy->conn); + //xcb_disconnect(dpy->conn); + XCloseDisplay(dpy->xlib_dpy); free(dpy); } } diff --git a/display.h b/display.h index 862dbd1..9aa1711 100644 --- a/display.h +++ b/display.h @@ -2,6 +2,7 @@ #define dc__display_h #include +#include #include @@ -18,6 +19,7 @@ typedef struct d_display_ext { typedef struct d_display { xcb_connection_t *conn; + Display *xlib_dpy; int ref; int fd; struct d_list *screens; diff --git a/glxcompat.c b/glxcompat.c deleted file mode 100644 index 8d0bcac..0000000 --- a/glxcompat.c +++ /dev/null @@ -1,410 +0,0 @@ -#include "efence.h" - -#include "glxcompat.h" -#include -#include -#include -#include -#include -#include - -#define DEBUG - -static uint32_t* -code_to_ptr(d_glx_fb_config_t *fb, uint32_t code) -{ - if (code == GLX_FBCONFIG_ID) return &fb->fbconfig_id; - if (code == GLX_VISUAL_ID) return &fb->visual_id; - if (code == GLX_BUFFER_SIZE) return &fb->buffer_size; - if (code == GLX_LEVEL) return &fb->level; - if (code == GLX_DOUBLEBUFFER) return &fb->doublebuffer; - if (code == GLX_STEREO) return &fb->stereo; - if (code == GLX_AUX_BUFFERS) return &fb->aux_buffers; - if (code == GLX_RED_SIZE) return &fb->red_size; - if (code == GLX_GREEN_SIZE) return &fb->green_size; - if (code == GLX_BLUE_SIZE) return &fb->blue_size; - if (code == GLX_ALPHA_SIZE) return &fb->alpha_size; - if (code == GLX_DEPTH_SIZE) return &fb->depth_size; - if (code == GLX_STENCIL_SIZE) return &fb->stencil_size; - if (code == GLX_ACCUM_RED_SIZE) return &fb->accum_red_size; - if (code == GLX_ACCUM_GREEN_SIZE) return &fb->accum_green_size; - if (code == GLX_ACCUM_BLUE_SIZE) return &fb->accum_blue_size; - if (code == GLX_ACCUM_ALPHA_SIZE) return &fb->accum_alpha_size; - if (code == GLX_RENDER_TYPE) return &fb->render_type; - if (code == GLX_DRAWABLE_TYPE) return &fb->drawable_type; - if (code == GLX_X_RENDERABLE) return &fb->x_renderable; - if (code == GLX_X_VISUAL_TYPE) return &fb->x_visual_type; - if (code == GLX_CONFIG_CAVEAT) return &fb->config_caveat; - if (code == GLX_TRANSPARENT_TYPE) return &fb->transparent_type; - if (code == GLX_TRANSPARENT_INDEX_VALUE) - return &fb->transparent_index_value; - if (code == GLX_TRANSPARENT_RED_VALUE) - return &fb->transparent_red_value; - if (code == GLX_TRANSPARENT_GREEN_VALUE) - return &fb->transparent_green_value; - if (code == GLX_TRANSPARENT_BLUE_VALUE) - return &fb->transparent_blue_value; - if (code == GLX_TRANSPARENT_ALPHA_VALUE) - return &fb->transparent_alpha_value; - if (code == GLX_BIND_TO_TEXTURE_RGBA_EXT) - return &fb->bind_to_texture_rgba_ext; - return NULL; -} - -#ifdef DEBUG -static const char* -code_to_string(uint32_t code) -{ - if (code == GLX_FBCONFIG_ID) return "GLX_FBCONFIG_ID"; - if (code == GLX_VISUAL_ID) return "GLX_VISUAL_ID"; - if (code == GLX_BUFFER_SIZE) return "GLX_BUFFER_SIZE"; - if (code == GLX_LEVEL) return "GLX_LEVEL"; - if (code == GLX_DOUBLEBUFFER) return "GLX_DOUBLEBUFFER"; - if (code == GLX_STEREO) return "GLX_STEREO"; - if (code == GLX_AUX_BUFFERS) return "GLX_AUX_BUFFERS"; - if (code == GLX_RED_SIZE) return "GLX_RED_SIZE"; - if (code == GLX_GREEN_SIZE) return "GLX_GREEN_SIZE"; - if (code == GLX_BLUE_SIZE) return "GLX_BLUE_SIZE"; - if (code == GLX_ALPHA_SIZE) return "GLX_ALPHA_SIZE"; - if (code == GLX_DEPTH_SIZE) return "GLX_DEPTH_SIZE"; - if (code == GLX_STENCIL_SIZE) return "GLX_STENCIL_SIZE"; - if (code == GLX_ACCUM_RED_SIZE) return "GLX_ACCUM_RED_SIZE"; - if (code == GLX_ACCUM_GREEN_SIZE) return "GLX_ACCUM_GREEN_SIZE"; - if (code == GLX_ACCUM_BLUE_SIZE) return "GLX_ACCUM_BLUE_SIZE"; - if (code == GLX_ACCUM_ALPHA_SIZE) return "GLX_ACCUM_ALPHA_SIZE"; - if (code == GLX_RENDER_TYPE) return "GLX_RENDER_TYPE"; - if (code == GLX_DRAWABLE_TYPE) return "GLX_DRAWABLE_TYPE"; - if (code == GLX_X_RENDERABLE) return "GLX_X_RENDERABLE"; - if (code == GLX_X_VISUAL_TYPE) return "GLX_X_VISUAL_TYPE"; - if (code == GLX_CONFIG_CAVEAT) return "GLX_CONFIG_CAVEAT"; - if (code == GLX_TRANSPARENT_TYPE) - return "GLX_TRANSPARENT_TYPE"; - if (code == GLX_TRANSPARENT_INDEX_VALUE) - return "GLX_TRANSPARENT_INDEX_VALUE"; - if (code == GLX_TRANSPARENT_RED_VALUE) - return "GLX_TRANSPARENT_RED_VALUE"; - if (code == GLX_TRANSPARENT_GREEN_VALUE) - return "GLX_TRANSPARENT_GREEN_VALUE"; - if (code == GLX_TRANSPARENT_BLUE_VALUE) - return "GLX_TRANSPARENT_BLUE_VALUE"; - if (code == GLX_TRANSPARENT_ALPHA_VALUE) - return "GLX_TRANSPARENT_ALPHA_VALUE"; - if (code == GLX_BIND_TO_TEXTURE_RGBA_EXT) - return "GLX_BIND_TO_TEXTURE_RGBA_EXT"; - return NULL; -} -#endif - -static void -default_config(d_glx_fb_config_t *fb) -{ - fb->fbconfig_id = GLX_DONT_CARE; - fb->buffer_size = 0; - fb->level = 0; - fb->doublebuffer = GLX_DONT_CARE; - fb->stereo = FALSE; - fb->aux_buffers = 0; - fb->red_size = 0; - fb->green_size = 0; - fb->blue_size = 0; - fb->alpha_size = 0; - fb->depth_size = 0; - fb->stencil_size = 0; - fb->accum_red_size = 0; - fb->accum_green_size = 0; - fb->accum_blue_size = 0; - fb->accum_alpha_size = 0; - fb->render_type = GLX_RGBA_BIT; - fb->drawable_type = GLX_WINDOW_BIT; - fb->x_renderable = GLX_DONT_CARE; - fb->x_visual_type = GLX_DONT_CARE; - fb->config_caveat = GLX_DONT_CARE; - fb->transparent_type = GLX_NONE; - fb->transparent_index_value = GLX_DONT_CARE; - fb->transparent_red_value = GLX_DONT_CARE; - fb->transparent_green_value = GLX_DONT_CARE; - fb->transparent_blue_value = GLX_DONT_CARE; - fb->transparent_alpha_value = GLX_DONT_CARE; - fb->bind_to_texture_rgba_ext = GLX_DONT_CARE; -} - -static gboolean -match_config(const d_glx_fb_config_t *match, const d_glx_fb_config_t *fb) -{ - if (match->fbconfig_id != GLX_DONT_CARE && - fb->fbconfig_id != match->fbconfig_id) - return FALSE; - if (fb->buffer_size < match->buffer_size) - return FALSE; - if (fb->level != match->level) - return FALSE; - if (match->doublebuffer != GLX_DONT_CARE && - fb->doublebuffer != match->doublebuffer) - return FALSE; - if (fb->stereo != match->stereo) - return FALSE; - if (fb->aux_buffers < match->aux_buffers) - return FALSE; - if (match->red_size != 0 && match->red_size == GLX_DONT_CARE && - fb->red_size < match->red_size) - return FALSE; - if (match->green_size != 0 && match->green_size == GLX_DONT_CARE && - fb->green_size < match->green_size) - return FALSE; - if (match->blue_size != 0 && match->blue_size == GLX_DONT_CARE && - fb->blue_size < match->blue_size) - return FALSE; - if (match->alpha_size != 0 && match->alpha_size == GLX_DONT_CARE && - fb->alpha_size < match->alpha_size) - return FALSE; - if (fb->depth_size < match->depth_size) - return FALSE; - if (fb->stencil_size < match->stencil_size) - return FALSE; - if (fb->accum_red_size < match->accum_red_size) - return FALSE; - if (fb->accum_green_size < match->accum_green_size) - return FALSE; - if (fb->accum_blue_size < match->accum_blue_size) - return FALSE; - if (fb->accum_alpha_size < match->accum_alpha_size) - return FALSE; - if ((fb->render_type & match->render_type) != match->render_type) - return FALSE; - if ((fb->drawable_type & match->drawable_type) != match->drawable_type) - return FALSE; - if (match->x_renderable != GLX_DONT_CARE && - fb->x_renderable != match->x_renderable) - return FALSE; - if (match->x_visual_type != GLX_DONT_CARE && - (match->drawable_type & GLX_WINDOW_BIT) && - match->x_renderable != FALSE && - fb->x_visual_type != match->x_visual_type) - return FALSE; - if (match->config_caveat != GLX_DONT_CARE && - fb->config_caveat != match->config_caveat) - return FALSE; - if (fb->transparent_type != match->transparent_type) - return FALSE; - if (match->transparent_type == GLX_TRANSPARENT_INDEX && - match->transparent_index_value != GLX_DONT_CARE && - fb->transparent_index_value != match->transparent_index_value) - return FALSE; - if (match->transparent_type == GLX_TRANSPARENT_RGB && - match->transparent_red_value != GLX_DONT_CARE && - fb->transparent_red_value != match->transparent_red_value) - return FALSE; - if (match->transparent_type == GLX_TRANSPARENT_RGB && - match->transparent_green_value != GLX_DONT_CARE && - fb->transparent_green_value != match->transparent_green_value) - return FALSE; - if (match->transparent_type == GLX_TRANSPARENT_RGB && - match->transparent_blue_value != GLX_DONT_CARE && - fb->transparent_blue_value != match->transparent_blue_value) - return FALSE; - if (match->transparent_type == GLX_TRANSPARENT_RGB && - match->transparent_alpha_value != GLX_DONT_CARE && - fb->transparent_alpha_value != match->transparent_alpha_value) - return FALSE; - if (match->bind_to_texture_rgba_ext != GLX_DONT_CARE && - fb->bind_to_texture_rgba_ext != match->bind_to_texture_rgba_ext) - return FALSE; - return TRUE; -} - -static void -build_config(uint32_t *props, uint32_t nprops, d_glx_fb_config_t *test) -{ - uint32_t i; - - //assert(nprops == sizeof(d_glx_fb_config_t) / sizeof(uint32_t)); - - for (i = 0; i < nprops * 2; i += 2) { - uint32_t *val = code_to_ptr(test, props[i]); - if (val) *val = props[i+1]; - -#ifdef DEBUG - { - const char *s = code_to_string(props[i]); - if (s) - printf("%s\t%x\n", s, props[i+1]); - else - printf("UNKNOWN %x\t%x\n", props[i], props[i+1]); - } -#endif - } -#ifdef DEBUG - printf("\n\n"); -#endif -} - -static d_glx_fb_config_t sort_match; - -int compare_config(const void *va, const void *vb) -{ - const d_glx_fb_config_t *a = va, *b = vb; - uint32_t av, bv; - - if (a->config_caveat != b->config_caveat) { - if (a->config_caveat == GLX_NONE) return -1; - if (b->config_caveat == GLX_NONE) return 1; - if (a->config_caveat == GLX_SLOW_CONFIG) return -1; - if (b->config_caveat == GLX_SLOW_CONFIG) return 1; - } - - av = bv = 0; - if (sort_match.red_size != 0 && sort_match.red_size != GLX_DONT_CARE) { - av += a->red_size; - bv += b->red_size; - } - if (sort_match.green_size != 0 && sort_match.green_size != GLX_DONT_CARE) { - av += a->green_size; - bv += b->green_size; - } - if (sort_match.blue_size != 0 && sort_match.blue_size != GLX_DONT_CARE) { - av += a->blue_size; - bv += b->blue_size; - } - if (sort_match.alpha_size != 0 && sort_match.alpha_size != GLX_DONT_CARE) { - av += a->alpha_size; - bv += b->alpha_size; - } - if (av != bv) - return av > bv ? -1 : 1; - - if (a->buffer_size < b->buffer_size) - return -1; - if (b->buffer_size < a->buffer_size) - return 1; - - if (a->doublebuffer == FALSE && b->doublebuffer == TRUE) - return -1; - if (b->doublebuffer == FALSE && a->doublebuffer == TRUE) - return 1; - - if (a->aux_buffers < b->aux_buffers) - return -1; - if (b->aux_buffers < a->aux_buffers) - return 1; - - if (a->depth_size > b->depth_size) - return -1; - if (b->depth_size > a->depth_size) - return 1; - - if (a->stencil_size < b->stencil_size) - return -1; - if (b->stencil_size < a->stencil_size) - return 1; - - av = bv = 0; - if (sort_match.accum_red_size != 0 && - sort_match.accum_red_size != GLX_DONT_CARE) - { - av += a->accum_red_size; - bv += b->accum_red_size; - } - if (sort_match.accum_green_size != 0 && - sort_match.accum_green_size != GLX_DONT_CARE) - { - av += a->accum_green_size; - bv += b->accum_green_size; - } - if (sort_match.accum_blue_size != 0 && - sort_match.accum_blue_size != GLX_DONT_CARE) - { - av += a->accum_blue_size; - bv += b->accum_blue_size; - } - if (sort_match.accum_alpha_size != 0 && - sort_match.accum_alpha_size != GLX_DONT_CARE) - { - av += a->accum_alpha_size; - bv += b->accum_alpha_size; - } - if (av != bv) - return av > bv ? -1 : 1; - - if (a->x_visual_type != b->x_visual_type) { - if (a->x_visual_type == GLX_TRUE_COLOR) return -1; - if (b->x_visual_type == GLX_TRUE_COLOR) return 1; - if (a->x_visual_type == GLX_DIRECT_COLOR) return -1; - if (b->x_visual_type == GLX_DIRECT_COLOR) return 1; - if (a->x_visual_type == GLX_PSEUDO_COLOR) return -1; - if (b->x_visual_type == GLX_PSEUDO_COLOR) return 1; - if (a->x_visual_type == GLX_STATIC_COLOR) return -1; - if (b->x_visual_type == GLX_STATIC_COLOR) return 1; - if (a->x_visual_type == GLX_GRAY_SCALE) return -1; - if (b->x_visual_type == GLX_GRAY_SCALE) return 1; - } - - return 0; -} - -d_glx_fb_config_t* -glxcompat_choose_fb_config(xcb_connection_t *conn, int screen, - const uint32_t *attrs, int *nret) -{ - xcb_glx_get_fb_configs_cookie_t ck; - xcb_glx_get_fb_configs_reply_t *rep; - uint32_t *props; - const uint32_t *attr_it; - unsigned int nprops, ncon, i; - d_glx_fb_config_t *ret, match, test; - - *nret = 0; - ret = NULL; - - ck = xcb_glx_get_fb_configs(conn, screen); - rep = xcb_glx_get_fb_configs_reply(conn, ck, NULL); - if (!rep) return ret; - - props = xcb_glx_get_fb_configs_property_list(rep); - ncon = rep->num_FB_configs; - nprops = rep->num_properties; - assert(xcb_glx_get_fb_configs_property_list_length(rep) == - (int)(ncon * nprops * 2)); - - default_config(&match); - - for (attr_it = attrs; *attr_it != XCB_NONE; attr_it+=2) { - uint32_t *val = code_to_ptr(&match, attr_it[0]); - if (val) *val = attr_it[1]; - } - - for (i = 0; i < ncon; ++i) { - default_config(&test); - build_config(&props[i*(nprops*2)], nprops, &test); - if (match_config(&match, &test)) { - ++*nret; - ret = realloc(ret, sizeof(d_glx_fb_config_t) * *nret); - ret[*nret-1] = test; - } - } - - if (*nret) { - sort_match = match; - qsort(ret, *nret, sizeof(d_glx_fb_config_t), compare_config); - } - - return ret; -} - -gboolean -glxcompat_get_fb_config_attrib(d_glx_fb_config_t fb, - uint32_t name, - uint32_t *value) -{ - uint32_t *ptr = code_to_ptr(&fb, name); - //assert(ptr != NULL); - if (ptr) *value = *ptr; - else *value = 0; - return !!ptr; -} - -xcb_visualid_t -glxcompat_choose_visual(xcb_connection_t *conn, - int screen, - const uint32_t *attrs) -{ -} diff --git a/glxcompat.h b/glxcompat.h deleted file mode 100644 index f52d34e..0000000 --- a/glxcompat.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef dc_glxcompat_h -#define dc_glxcompat_h - -#include -#include - -typedef struct d_glx_fb_config d_glx_fb_config_t; - -struct d_glx_fb_config { - uint32_t fbconfig_id; - uint32_t visual_id; - uint32_t buffer_size; - uint32_t level; - uint32_t doublebuffer; - uint32_t stereo; - uint32_t aux_buffers; - uint32_t red_size; - uint32_t green_size; - uint32_t blue_size; - uint32_t alpha_size; - uint32_t depth_size; - uint32_t stencil_size; - uint32_t accum_red_size; - uint32_t accum_green_size; - uint32_t accum_blue_size; - uint32_t accum_alpha_size; - uint32_t render_type; - uint32_t drawable_type; - uint32_t x_renderable; - uint32_t x_visual_type; - uint32_t config_caveat; - uint32_t transparent_type; - uint32_t transparent_index_value; - uint32_t transparent_red_value; - uint32_t transparent_green_value; - uint32_t transparent_blue_value; - uint32_t transparent_alpha_value; - uint32_t bind_to_texture_rgba_ext; -}; - -d_glx_fb_config_t* glxcompat_choose_fb_config(xcb_connection_t *conn, - int screen, - const uint32_t *attrs, - int *nret); - -gboolean glxcompat_get_fb_config_attrib(d_glx_fb_config_t fb, - uint32_t name, - uint32_t *value); - -xcb_visualid_t glxcompat_choose_visual(xcb_connection_t *conn, - int screen, - const uint32_t *attrs); - - -#endif diff --git a/glxrender.c b/glxrender.c index 7973fbc..63fa91c 100644 --- a/glxrender.c +++ b/glxrender.c @@ -4,23 +4,26 @@ #include "screen.h" #include "window.h" #include "display.h" -#include "list.h" #include "glxcompat.h" +#include "list.h" #include #include #include #include -#include -//#include -//#include -#include #include +#include +#include +#include +#include #define MAX_DEPTH 32 static int plugin_id; +typedef void (*BindEXTFunc)(Display *, GLXDrawable, int, const int *); +typedef void (*ReleaseEXTFunc)(Display *, GLXDrawable, int); + typedef struct { void (*screen_paint)(d_screen_t *sc); void (*screen_root_pixmap_change)(d_screen_t *sc); @@ -33,20 +36,19 @@ typedef struct { int xshadowoff; int yshadowoff; - uint32_t fbconfig[MAX_DEPTH + 1]; + GLXFBConfig fbconfig[MAX_DEPTH + 1]; + + GLXContext context; - xcb_glx_context_t context; - xcb_glx_context_tag_t context_tag; + BindEXTFunc bind_func; + ReleaseEXTFunc release_func; } data_t; typedef struct { GLuint texname; - xcb_glx_pixmap_t glpixmap; + GLXPixmap glpixmap; } window_data_t; -static uint32_t glxrender_visual_info(uint32_t *props, int vis, int numprops, - uint32_t name); -static gboolean glxrender_check_visual(d_screen_t *sc); static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d); static void glxrender_paint(d_screen_t *sc); @@ -71,15 +73,18 @@ 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; - xcb_visualid_t vis; + static int context_visual_config[] = { + GLX_DEPTH_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_RGBA, + XCB_NONE + }; + XVisualInfo *vi; + data_t *d; plugin_id = id; - data_t *d = malloc(sizeof(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; @@ -99,136 +104,48 @@ glxrender_init(d_screen_t *sc, int id) d->xshadowoff = 2; d->yshadowoff = 2; - if (!(glxrender_find_fb_config(sc, d))) { - printf("unable to find FB configs\n"); + vi = glXChooseVisual(sc->dpy->xlib_dpy, sc->num, context_visual_config); + if (!vi) { + printf("unable to find a valid double buffered GL context to use\n"); exit(1); } - if (!glxrender_check_visual(sc)) { - printf("unable to use the overlay window for GLX\n"); - exit(1); - } + d->context = glXCreateContext(sc->dpy->xlib_dpy, vi, NULL, GL_TRUE); + glXMakeCurrent(sc->dpy->xlib_dpy, sc->overlay, d->context); - 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, GL_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"); + if (!(glxrender_find_fb_config(sc, d))) { + printf("unable to find FB configs\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); + glOrtho(0, sc->super->width_in_pixels, sc->super->height_in_pixels, 0, + -100.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, GL_ONE_MINUS_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); -/* - glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); - glEnable(GL_BLEND); -*/ -} - -static uint32_t -glxrender_visual_info(uint32_t *props, int vis, int numprops, uint32_t name) -{ - int s; - - assert(numprops > 15); - - /* - for (s = vis * numprops; s < vis*numprops + numprops; ++s) - printf("%x ", props[s]); - printf("\n"); - */ - - s = vis * numprops; - switch (name) { - case GLX_VISUAL_ID: return props[s+0]; /* id number */ - case GLX_X_VISUAL_TYPE: return props[s+1]; /* XCB_CLASS_TRUE_COLOR etc */ - case GLX_USE_GL: return props[s+2]; /* boolean */ - case GLX_RED_SIZE: return props[s+3]; /* number */ - case GLX_GREEN_SIZE: return props[s+4]; /* number */ - case GLX_BLUE_SIZE: return props[s+5]; /* number */ - case GLX_ALPHA_SIZE: return props[s+6]; /* number */ - case GLX_DOUBLEBUFFER: return props[s+11]; /* boolean */ - case GLX_DEPTH_SIZE: return props[s+14]; /* number */ - case GLX_STENCIL_SIZE: return props[s+15]; /* number */ - default: assert(0); - } -} - -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 *props; - unsigned int i, nprops; - - props = xcb_glx_get_visual_configs_property_list(rep); - nprops = rep->num_properties; - - for (i = 0; i < rep->num_visuals; ++i) { - /* look for the overlay's visual */ - if (glxrender_visual_info(props, i, nprops, GLX_VISUAL_ID) != - sc->overlay_visual) - { - continue; - } - if (!glxrender_visual_info(props, i, nprops, GLX_USE_GL)) { - printf("overlay visual does not support GL\n"); - break; - } - - if (!glxrender_visual_info(props, i, nprops, GLX_DOUBLEBUFFER)) { - printf("overlay visual is not double buffered\n"); - break; - } - - ok = TRUE; /* yippa ! */ - } + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay); - free(rep); - } - return ok; + d->bind_func = (BindEXTFunc) + glXGetProcAddress((const guchar*)"glXBindTexImageEXT"); + d->release_func = (ReleaseEXTFunc) + glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT"); } static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d) { - static const uint32_t drawable_tfp_attrs[] = { + static const int drawable_tfp_attrs[] = { GLX_CONFIG_CAVEAT, GLX_NONE, GLX_DOUBLEBUFFER, FALSE, GLX_DEPTH_SIZE, 0, @@ -240,60 +157,74 @@ glxrender_find_fb_config(d_screen_t *sc, data_t *d) GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */ XCB_NONE }; - xcb_depth_iterator_t depth_it; - d_glx_fb_config_t *fbcons; - int numfb; + int db, stencil, depth, numfb, i; + GLXFBConfig *fbcons; + XVisualInfo tvis, *visinfo; - fbcons = glxcompat_choose_fb_config(sc->dpy->conn, sc->num, - drawable_tfp_attrs, &numfb); + fbcons = glXChooseFBConfig(sc->dpy->xlib_dpy, sc->num, + drawable_tfp_attrs, &numfb); if (!fbcons) return FALSE; - memset(d->fbconfig, 0, (MAX_DEPTH + 1) * sizeof(d->fbconfig[0])); - - depth_it = xcb_screen_allowed_depths_iterator(sc->super); - for (; depth_it.rem; xcb_depth_next(&depth_it)) { - int j, k; - xcb_visualtype_t *visuals; - int nvisuals; - - if (depth_it.data->depth > MAX_DEPTH) continue; - - printf("looking for depth %d\n", depth_it.data->depth); + for (i = 0; i <= MAX_DEPTH; i++) { + int j, count, value; + VisualID vid; + + vid = 0; + d->fbconfig[i] = 0; + db = 32767; + stencil = 32767; + depth = 32767; + + printf("looking for depth %d\n", i); + + tvis.depth = i; + visinfo = XGetVisualInfo(sc->dpy->xlib_dpy, VisualDepthMask, + &tvis, &count); + /* pick the nicest visual for the depth */ + for (j = 0; j < count; j++) { + glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_USE_GL, &value); + if (!value) + continue; - visuals = xcb_depth_visuals(depth_it.data); - nvisuals = xcb_depth_visuals_length(depth_it.data); + glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DOUBLEBUFFER, + &value); + if (value > db) + continue; + db = value; - /* look for an fbconfig for this depth */ - for (j = 0; j < numfb; ++j) { - uint32_t vid, fbid; - gboolean use; + glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_STENCIL_SIZE, + &value); + if (value > stencil) + continue; + stencil = value; - //glxcompat_get_fb_config_attrib(fbcons[j], GLX_FBCONFIG_ID, &v); - //printf("trying fbconfig 0x%x\n", v); + glXGetConfig(sc->dpy->xlib_dpy, &visinfo[j], GLX_DEPTH_SIZE, + &value); + if (value > depth) + continue; + depth = value; - glxcompat_get_fb_config_attrib(fbcons[j], GLX_VISUAL_ID, &vid); - glxcompat_get_fb_config_attrib(fbcons[j], GLX_FBCONFIG_ID, &fbid); + /* use this visual */ + vid = visinfo[j].visualid; + } - use = FALSE; - for (k = 0; k < nvisuals; ++k) - //if (vid == visuals[k].visual_id) { - if ((vid == 0x80 && depth_it.data->depth == 32) || - vid == 0x59) { - use = TRUE; - break; - } + if (!vid) continue; - if (use) { - d->fbconfig[depth_it.data->depth] = fbid; + /* look for an fbconfig for this visual */ + for (j = 0; j < numfb; ++j) { + glXGetFBConfigAttrib(sc->dpy->xlib_dpy, fbcons[j], + GLX_VISUAL_ID, &value); + if ((unsigned)value == vid) { + d->fbconfig[i] = fbcons[j]; printf("found visual 0x%x fbconfig 0x%x for depth %d\n", - vid, fbid, depth_it.data->depth); + (uint32_t)vid, (uint32_t)fbcons[j], i); break; } } } - free(fbcons); + XFree(fbcons); return TRUE; } @@ -384,6 +315,7 @@ glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd) 4 GLX_DRAWABLE drawable 4 INT32 buffer */ + /* unsigned int len = (2 + 0) * sizeof(uint32_t); uint32_t data[] = { wd->glpixmap, @@ -393,11 +325,15 @@ glxrender_free_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd) 1331, d->context_tag, len, (uint8_t*)data); + */ + d->release_func(w->sc->dpy->xlib_dpy, + wd->glpixmap, GLX_FRONT_LEFT_EXT); } glBindTexture(GL_TEXTURE_2D, 0); - xcb_glx_destroy_glx_pixmap(w->sc->dpy->conn, wd->glpixmap); + //xcb_glx_destroy_pixmap(w->sc->dpy->conn, wd->glpixmap); + glXDestroyPixmap(w->sc->dpy->xlib_dpy, wd->glpixmap); wd->glpixmap = XCB_NONE; } } @@ -408,64 +344,92 @@ glxrender_update_window_pixmap(d_window_t *w, data_t *d, window_data_t *wd) xcb_pixmap_t px; uint8_t depth; - static const uint32_t attrs[] = { + static int attrs[] = { GLX_TEXTURE_FORMAT_EXT, - GLX_TEXTURE_FORMAT_RGBA_EXT + XCB_NONE, + XCB_NONE }; px = window_get_pixmap(w); depth = window_get_depth(w); + + if (!px) return; + //printf("%x %d %x\n", px, depth, d->fbconfig[depth]); - if (px && !d->fbconfig[depth]) + if (!d->fbconfig[depth]) { printf("no GL visual for depth %d\n", depth); - else if (px) { + return; + } + + if (window_is_argb(w)) + attrs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT; + else + attrs[1] = GLX_TEXTURE_FORMAT_RGB_EXT; + +/* wd->glpixmap = xcb_generate_id(w->sc->dpy->conn); printf("bind config 0x%x screen %d pixmap 0x%x glpixmap 0x%x " "nattr %d\n", d->fbconfig[depth], w->sc->num, px, wd->glpixmap, sizeof(attrs)/sizeof(attrs[0])); - xcb_glx_create_pixmap(w->sc->dpy->conn, w->sc->num, + xcb_void_cookie_t ck = + xcb_glx_create_pixmap_checked(w->sc->dpy->conn, w->sc->num, d->fbconfig[depth], px, wd->glpixmap, - sizeof(attrs)/sizeof(attrs[0]), + sizeof(attrs)/sizeof(attrs[0] - 1), attrs); - - glBindTexture(GL_TEXTURE_2D, wd->texname); - - { - /* - BindTexImageEXT - 1 CARD8 opcode (X assigned) - 1 16 GLX opcode (glXVendorPrivate) - 2 6+n request length - 4 1330 vendor specific opcode - 4 CARD32 context tag - 4 GLX_DRAWABLE drawable - 4 INT32 buffer - 4 CARD32 num_attributes - 4*n LISTofATTRIBUTE_PAIR attribute, value pairs. - */ - unsigned int len = (3 + 0) * sizeof(uint32_t); - uint32_t data[] = { - wd->glpixmap, - GLX_FRONT_LEFT_EXT, - 0 - }; - xcb_glx_vendor_private(w->sc->dpy->conn, - 1330, - d->context_tag, - len, (uint8_t*)data); + xcb_generic_error_t *err = xcb_request_check(w->sc->dpy->conn, ck); + if (err) { + display_error(w->sc->dpy, err); + free(err); + wd->glpixmap = XCB_NONE; + return; } +/*/ + wd->glpixmap = glXCreatePixmap(w->sc->dpy->xlib_dpy, + d->fbconfig[depth], + px, attrs); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBindTexture(GL_TEXTURE_2D, wd->texname); - glBindTexture(GL_TEXTURE_2D, 0); + { + /* + BindTexImageEXT + 1 CARD8 opcode (X assigned) + 1 16 GLX opcode (glXVendorPrivate) + 2 6+n request length + 4 1330 vendor specific opcode + 4 CARD32 context tag + 4 GLX_DRAWABLE drawable + 4 INT32 buffer + 4 CARD32 num_attributes + 4*n LISTofATTRIBUTE_PAIR attribute, value pairs. + */ + /* + unsigned int len = (3 + 0) * sizeof(uint32_t); + uint32_t data[] = { + wd->glpixmap, + GLX_FRONT_LEFT_EXT, + 0 + }; + xcb_glx_vendor_private(w->sc->dpy->conn, + 1330, + d->context_tag, + len, (uint8_t*)data); + */ + d->bind_func(w->sc->dpy->xlib_dpy, + wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL); } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glBindTexture(GL_TEXTURE_2D, 0); } static void @@ -560,12 +524,13 @@ glxrender_paint(d_screen_t *sc) 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); + 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); + //xcb_glx_swap_buffers(sc->dpy->conn, d->context_tag, sc->overlay); + glXSwapBuffers(sc->dpy->xlib_dpy, sc->overlay); /* call the function we replaced in the chain */ d->screen_paint(sc); @@ -584,12 +549,21 @@ 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) { + uint16_t o = window_get_opacity(w); + if (!wd->glpixmap) glxrender_update_window_pixmap(w, d, wd); 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); - glColor3f(1.0, 1.0, 1.0); glVertex2i(x, y); glTexCoord2f(1, 0); glVertex2i(x + width + bwidth, y); @@ -600,6 +574,14 @@ paint_window(d_window_t *w, data_t *d, window_data_t *wd, gboolean opaque, glVertex2i(x, y + height + bwidth); glTexCoord2f(0, 0); 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 diff --git a/screen.c b/screen.c index 6d454c3..325c7d4 100644 --- a/screen.c +++ b/screen.c @@ -42,6 +42,7 @@ screen_new(struct d_display *dpy, int num, xcb_screen_t *xcb) sc->ref = 1; sc->dpy = dpy; sc->num = num; + sc->root_pixmap_waiting = FALSE; sc->need_repaint = TRUE; diff --git a/window.c b/window.c index b14de39..f9a3d23 100644 --- a/window.c +++ b/window.c @@ -53,6 +53,8 @@ typedef struct { xcb_get_geometry_cookie_t ck_get_geom; gboolean waiting_opac; xcb_get_property_cookie_t ck_get_opac; + gboolean waiting_pixmap; + xcb_void_cookie_t ck_pixmap; } d_window_priv_t; static void window_get_attributes_reply(d_window_priv_t *w); @@ -79,6 +81,7 @@ window_new(xcb_window_t id, struct d_screen *sc) w->type = DC_WINDOW_TYPE_INVALID; w->opacity = 0xffff; w->user_opacity = 0xffff; + w->waiting_pixmap = FALSE; screen_stacking_add(sc, (d_window_t*)w); @@ -125,6 +128,18 @@ window_get_pixmap(d_window_t *pubw) { d_window_priv_t *w = (d_window_priv_t*)pubw; + if (w->waiting_pixmap) { + xcb_generic_error_t *err; + + err = xcb_request_check(w->sc->dpy->conn, w->ck_pixmap); + if (err) { + w->pixmap = XCB_NONE; + display_error(w->sc->dpy, err); + free(err); + } + w->waiting_pixmap = FALSE; + } + return w->pixmap; } @@ -178,7 +193,10 @@ window_update_pixmap(d_window_priv_t *w) the X server just doesn't reply. if we check it, we end up hanging sometimes waiting for the reply */ w->pixmap = xcb_generate_id(w->sc->dpy->conn); - xcb_composite_name_window_pixmap(w->sc->dpy->conn, w->id, w->pixmap); + w->ck_pixmap = + xcb_composite_name_window_pixmap_checked(w->sc->dpy->conn, + w->id, w->pixmap); + w->waiting_pixmap = TRUE; //printf("requested pixmap sequence %u\n", w->ck_get_pixmap.sequence); //fflush(stdout); xcb_flush(w->sc->dpy->conn);