From 5deb8fa213ce86759053be391966618ee0959f50 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 9 Jun 2009 16:20:32 +0100 Subject: [PATCH] [gl] Construct a dummy window for the initial context In order to make the initial context current we need a Drawable that matches the context. In general, the RootWindow may not match the desired context so we need to query the context and construct an appropriate Drawable. --- src/cairo-glx-context.c | 70 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/src/cairo-glx-context.c b/src/cairo-glx-context.c index 2fa5faf5a..05346a650 100644 --- a/src/cairo-glx-context.c +++ b/src/cairo-glx-context.c @@ -40,10 +40,13 @@ #include "cairo-gl-private.h" +#include + typedef struct _cairo_glx_context { cairo_gl_context_t base; Display *display; + Window dummy_window; GLXContext context; } cairo_glx_context_t; @@ -77,6 +80,61 @@ _glx_swap_buffers (void *abstract_ctx, static void _glx_destroy (void *abstract_ctx) { + cairo_glx_context_t *ctx = abstract_ctx; + + if (ctx->dummy_window != None) + XDestroyWindow (ctx->display, ctx->dummy_window); +} + +static cairo_status_t +_glx_dummy_ctx (Display *dpy, GLXContext gl_ctx, Window *dummy) +{ + int attr[3] = { GLX_FBCONFIG_ID, 0, None }; + GLXFBConfig *config; + XVisualInfo *vi; + Colormap cmap; + XSetWindowAttributes swa; + Window win = None; + int cnt; + + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + /* Create a dummy window created for the target GLX context that we can + * use to query the available GL/GLX extensions. + */ + glXQueryContext (dpy, gl_ctx, GLX_FBCONFIG_ID, &attr[1]); + + cnt = 0; + config = glXChooseFBConfig (dpy, DefaultScreen (dpy), attr, &cnt); + if (cnt == 0) + return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); + vi = glXGetVisualFromFBConfig (dpy, config[0]); + XFree (config); + + cmap = XCreateColormap (dpy, + RootWindow (dpy, vi->screen), + vi->visual, + AllocNone); + swa.colormap = cmap; + swa.border_pixel = 0; + win = XCreateWindow (dpy, RootWindow (dpy, vi->screen), + -1, -1, 1, 1, 0, + vi->depth, + InputOutput, + vi->visual, + CWBorderPixel | CWColormap, &swa); + XFreeColormap (dpy, cmap); + XFree (vi); + + XFlush (dpy); + if (! glXMakeCurrent (dpy, win, gl_ctx)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + XDestroyWindow (dpy, win); + win = None; + } + + *dummy = win; + return status; } cairo_gl_context_t * @@ -84,20 +142,18 @@ cairo_glx_context_create (Display *dpy, GLXContext gl_ctx) { cairo_glx_context_t *ctx; cairo_status_t status; + Window dummy = None; - /* Make our GL context active. While we'll be setting the destination - * drawable with each rendering operation, in order to set the context - * we have to choose a drawable. The root window happens to be convenient - * for this. - */ - if (! glXMakeCurrent (dpy, RootWindow (dpy, DefaultScreen (dpy)), gl_ctx)) - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); + status = _glx_dummy_ctx (dpy, gl_ctx, &dummy); + if (status) + return _cairo_gl_context_create_in_error (status); ctx = calloc (1, sizeof (cairo_glx_context_t)); if (ctx == NULL) return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); ctx->display = dpy; + ctx->dummy_window = dummy; ctx->context = gl_ctx; ctx->base.make_current = _glx_make_current;