From 5ecc332b1d5599714e76338ebdff7b9f606764a1 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 11 Mar 2008 00:47:12 -0400 Subject: [PATCH] i've reimplemented glXChooseFBConfig for xcb --- glxcompat.c | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++ glxcompat.h | 49 +++++++ glxrender.c | 41 +++++- screen.c | 2 +- 4 files changed, 484 insertions(+), 6 deletions(-) create mode 100644 glxcompat.c create mode 100644 glxcompat.h diff --git a/glxcompat.c b/glxcompat.c new file mode 100644 index 0000000..61cd93b --- /dev/null +++ b/glxcompat.c @@ -0,0 +1,398 @@ +#include "efence.h" + +#include "glxcompat.h" +#include +#include +#include +#include +#include +#include + +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_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_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; + return !!ptr; +} diff --git a/glxcompat.h b/glxcompat.h new file mode 100644 index 0000000..1e42997 --- /dev/null +++ b/glxcompat.h @@ -0,0 +1,49 @@ +#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 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); + +#endif diff --git a/glxrender.c b/glxrender.c index 511bdb1..8e89b00 100644 --- a/glxrender.c +++ b/glxrender.c @@ -5,6 +5,7 @@ #include "window.h" #include "display.h" #include "list.h" +#include "glxcompat.h" #include #include #include @@ -97,13 +98,13 @@ glxrender_init(d_screen_t *sc, int id) d->xshadowoff = 2; d->yshadowoff = 2; - if (!glxrender_check_visual(sc)) { - printf("unable to use the overlay window for GLX\n"); + if (!(glxrender_find_fb_config(sc, d))) { + printf("unable to find FB configs\n"); exit(1); } - if (!(glxrender_find_fb_config(sc, d))) { - printf("unable to find FB configs\n"); + if (!glxrender_check_visual(sc)) { + printf("unable to use the overlay window for GLX\n"); exit(1); } @@ -254,6 +255,37 @@ glxrender_find_fb_config(d_screen_t *sc, data_t *d) uint32_t *vprops, *fbprops; uint32_t db, stencil, depthsize; + { + static const uint32_t drawable_tfp_attrs[] = { + GLX_CONFIG_CAVEAT, GLX_NONE, + GLX_DOUBLEBUFFER, FALSE, + GLX_DEPTH_SIZE, 0, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_ALPHA_SIZE, 1, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */ + XCB_NONE + }; + + d_glx_fb_config_t *fbcons; + int i, numfb; + + fbcons = glxcompat_choose_fb_config(sc->dpy->conn, sc->num, + drawable_tfp_attrs, &numfb); + printf("found %d\n", numfb); + if (fbcons) { + for (i = 0; i < numfb; ++i) { + uint32_t v; + glxcompat_get_fb_config_attrib(fbcons[i], GLX_FBCONFIG_ID, &v); + printf("GLX_FBCONFIG_ID %x\n", v); + } + free(fbcons); + } + exit(0); + } + vck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num); vrep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, vck, NULL); if (!vrep) return FALSE; @@ -291,7 +323,6 @@ glxrender_find_fb_config(d_screen_t *sc, data_t *d) /* pick the nicest visual for the depth */ for (j = 0; j < nvisuals; ++j) { uint32_t val; - /* find the visual's properties */ for (k = 0; k < vrep->num_visuals; ++k) if (glxrender_visual_info(vprops, k, nvprops, GLX_VISUAL_ID) diff --git a/screen.c b/screen.c index 6d454c3..693c29c 100644 --- a/screen.c +++ b/screen.c @@ -156,7 +156,7 @@ screen_init(d_screen_t *sc) xcb_composite_redirect_subwindows(sc->dpy->conn, sc->super->root, XCB_COMPOSITE_REDIRECT_AUTOMATIC); -#if 1 +#if 0 redir_ck = xcb_composite_redirect_subwindows(sc->dpy->conn, sc->super->root, XCB_COMPOSITE_REDIRECT_MANUAL); -- 2.34.1