Improve handling of GL contexts.
authorgb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Wed, 31 Mar 2010 15:25:19 +0000 (15:25 +0000)
committergb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Wed, 31 Mar 2010 15:25:19 +0000 (15:25 +0000)
gst-libs/gst/vaapi/gstvaapitexture.c
gst-libs/gst/vaapi/gstvaapiutils_glx.c
gst-libs/gst/vaapi/gstvaapiutils_glx.h
gst-libs/gst/vaapi/gstvaapiwindow_glx.c

index 2022c29..155d7d4 100644 (file)
@@ -46,6 +46,7 @@ struct _GstVaapiTexturePrivate {
     GLenum               format;
     guint                width;
     guint                height;
+    GLContextState      *gl_context;
     void                *gl_surface;
     GLPixmapObject      *pixo;
     GLFramebufferObject *fbo;
@@ -103,6 +104,13 @@ gst_vaapi_texture_destroy(GstVaapiTexture *texture)
             glDeleteTextures(1, &texture_id);
         GST_VAAPI_OBJECT_ID(texture) = 0;
     }
+
+    if (priv->gl_context) {
+        GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+        gl_destroy_context(priv->gl_context);
+        GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+        priv->gl_context = NULL;
+    }
 }
 
 static gboolean
@@ -151,6 +159,18 @@ gst_vaapi_texture_create(GstVaapiTexture *texture)
 {
     GstVaapiTexturePrivate * const priv = texture->priv;
     GLuint texture_id;
+    GLContextState old_cs;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    gl_get_current_context(&old_cs);
+    priv->gl_context = gl_create_context(
+        GST_VAAPI_OBJECT_XDISPLAY(texture),
+        DefaultScreen(GST_VAAPI_OBJECT_XDISPLAY(texture)),
+        &old_cs
+    );
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+    if (!priv->gl_context)
+        return FALSE;
 
     if (priv->foreign_texture)
         texture_id = GST_VAAPI_OBJECT_ID(texture);
@@ -310,6 +330,7 @@ gst_vaapi_texture_init(GstVaapiTexture *texture)
     priv->format                = GL_NONE;
     priv->width                 = 0;
     priv->height                = 0;
+    priv->gl_context            = NULL;
     priv->gl_surface            = NULL;
     priv->pixo                  = NULL;
     priv->fbo                   = NULL;
index 93e8465..60a7bc7 100644 (file)
@@ -273,46 +273,165 @@ gl_resize(guint width, guint height)
 }
 
 /**
- * gl_make_current:
+ * gl_create_context:
  * @dpy: an X11 #Display
- * @win: an X11 #Window
- * @ctx: the requested GLX context
- * @state: an optional #GLContextState
+ * @screen: the associated screen of @dpy
+ * @parent: the parent #GLContextState, or %NULL if none is to be used
  *
- * Makes the @window GLX context the current GLX rendering context of
+ * Creates a GLX context sharing textures and displays lists with
+ * @parent, if not %NULL.
+ *
+ * Return value: the newly created GLX context
+ */
+GLContextState *
+gl_create_context(Display *dpy, int screen, GLContextState *parent)
+{
+    GLContextState *cs;
+    GLXFBConfig *fb_configs = NULL;
+    int n_fb_configs;
+
+    static GLint fb_config_attrs[] = {
+        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+        GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+        GLX_DOUBLEBUFFER,  True,
+        GLX_RED_SIZE,      1,
+        GLX_GREEN_SIZE,    1, 
+        GLX_BLUE_SIZE,     1,
+        None
+    };
+
+    cs = malloc(sizeof(*cs));
+    if (!cs)
+        goto error;
+
+    cs->display         = dpy;
+    cs->window          = parent ? parent->window : None;
+    cs->visual          = NULL;
+    cs->context         = NULL;
+    cs->swapped_buffers = FALSE;
+
+    fb_configs = glXChooseFBConfig(dpy, screen, fb_config_attrs, &n_fb_configs);
+    if (!fb_configs)
+        goto error;
+
+    cs->visual = glXGetVisualFromFBConfig(dpy, fb_configs[0]);
+    if (!cs->visual)
+        goto error;
+
+    cs->context = glXCreateNewContext(
+        dpy,
+        fb_configs[0],
+        GLX_RGBA_TYPE,
+        parent ? parent->context : NULL,
+        True
+    );
+    if (cs->context)
+        goto end;
+
+error:
+    gl_destroy_context(cs);
+    cs = NULL;
+end:
+    if (fb_configs)
+        XFree(fb_configs);
+    return cs;
+}
+
+/**
+ * gl_destroy_context:
+ * @cs: a #GLContextState
+ *
+ * Destroys the GLX context @cs
+ */
+void
+gl_destroy_context(GLContextState *cs)
+{
+    if (!cs)
+        return;
+
+    if (cs->visual) {
+        XFree(cs->visual);
+        cs->visual = NULL;
+    }
+
+    if (cs->display && cs->context) {
+        if (glXGetCurrentContext() == cs->context) {
+            /* XXX: if buffers were never swapped, the application
+               will crash later with the NVIDIA driver */
+            if (!cs->swapped_buffers)
+                gl_swap_buffers(cs);
+            glXMakeCurrent(cs->display, None, NULL);
+        }
+        glXDestroyContext(cs->display, cs->context);
+        cs->display = NULL;
+        cs->context = NULL;
+    }
+    free(cs);
+}
+
+/**
+ * gl_get_current_context:
+ * @cs: return location to the current #GLContextState
+ *
+ * Retrieves the current GLX context, display and drawable packed into
+ * the #GLContextState struct.
+ */
+void
+gl_get_current_context(GLContextState *cs)
+{
+    cs->display = glXGetCurrentDisplay();
+    cs->window  = glXGetCurrentDrawable();
+    cs->context = glXGetCurrentContext();
+}
+
+/**
+ * gl_set_current_context:
+ * @new_cs: the requested new #GLContextState
+ * @old_cs: return location to the context that was previously current
+ *
+ * Makes the @new_cs GLX context the current GLX rendering context of
  * the calling thread, replacing the previously current context if
  * there was one.
  *
- * If @state is non %NULL, the previously current GLX context and
+ * If @old_cs is non %NULL, the previously current GLX context and
  * window are recorded.
  *
  * Return value: %TRUE on success
  */
 gboolean
-gl_make_current(Display *dpy, Window win, GLXContext ctx, GLContextState *state)
+gl_set_current_context(GLContextState *new_cs, GLContextState *old_cs)
 {
-    if (state) {
-        state->context = glXGetCurrentContext();
-        state->window  = glXGetCurrentDrawable();
-        if (state->context == ctx && state->window == win)
+    /* If display is NULL, this could be that new_cs was retrieved from
+       gl_get_current_context() with none set previously. If that case,
+       the other fields are also NULL and we don't return an error */
+    if (!new_cs->display)
+        return !new_cs->window && !new_cs->context;
+
+    if (old_cs) {
+        if (old_cs == new_cs)
+            return TRUE;
+        gl_get_current_context(old_cs);
+        if (old_cs->display == new_cs->display &&
+            old_cs->window  == new_cs->window  &&
+            old_cs->context == new_cs->context)
             return TRUE;
     }
-    return glXMakeCurrent(dpy, win, ctx);
+    return glXMakeCurrent(new_cs->display, new_cs->window, new_cs->context);
 }
 
 /**
  * gl_swap_buffers:
- * @dpy: an X11 #Display
- * @win: an X11 #Window
+ * @cs: a #GLContextState
  *
  * Promotes the contents of the back buffer of the @win window to
  * become the contents of the front buffer. This simply is wrapper
  * around glXSwapBuffers().
  */
 void
-gl_swap_buffers(Display *dpy, Window win)
+gl_swap_buffers(GLContextState *cs)
 {
-    glXSwapBuffers(dpy, win);
+    glXSwapBuffers(cs->display, cs->window);
+    cs->swapped_buffers = TRUE;
 }
 
 /**
index 3c83da2..a13adbd 100644 (file)
@@ -67,16 +67,31 @@ gl_resize(guint width, guint height)
 
 typedef struct _GLContextState GLContextState;
 struct _GLContextState {
-    GLXContext  context;
-    Window      window;
+    Display     *display;
+    Window       window;
+    XVisualInfo *visual;
+    GLXContext   context;
+    guint        swapped_buffers;
 };
 
+GLContextState *
+gl_create_context(Display *dpy, int screen, GLContextState *parent)
+    attribute_hidden;
+
+void
+gl_destroy_context(GLContextState *cs)
+    attribute_hidden;
+
+void
+gl_get_current_context(GLContextState *cs)
+    attribute_hidden;
+
 gboolean
-gl_make_current(Display *dpy, Window win, GLXContext ctx, GLContextState *state)
+gl_set_current_context(GLContextState *new_cs, GLContextState *old_cs)
     attribute_hidden;
 
 void
-gl_swap_buffers(Display *dpy, Window win)
+gl_swap_buffers(GLContextState *cs)
     attribute_hidden;
 
 typedef struct _GLTextureState GLTextureState;
index a1f9dc6..bd905e9 100644 (file)
@@ -43,14 +43,10 @@ G_DEFINE_TYPE(GstVaapiWindowGLX,
                                  GstVaapiWindowGLXPrivate))
 
 struct _GstVaapiWindowGLXPrivate {
-    XVisualInfo        *vi;
-    XVisualInfo         vi_static;
     Colormap            cmap;
-    GLXContext          context;
+    GLContextState     *gl_context;
     guint               is_constructed  : 1;
-    guint               foreign_context : 1;
     guint               foreign_window  : 1;
-    guint               swapped_buffers : 1;
 };
 
 enum {
@@ -59,9 +55,6 @@ enum {
     PROP_GLX_CONTEXT
 };
 
-static XVisualInfo *
-gst_vaapi_window_glx_create_visual(GstVaapiWindowGLX *window);
-
 /* Fill rectangle coords with capped bounds */
 static inline void
 fill_rect(
@@ -91,149 +84,114 @@ fill_rect(
     }
 }
 
-static inline void
-_gst_vaapi_window_glx_set_context(
-    GstVaapiWindowGLX *window,
-    GLXContext         context,
-    gboolean           is_foreign
-)
-{
-    GstVaapiWindowGLXPrivate * const priv = window->priv;
-
-    priv->context         = context;
-    priv->foreign_context = is_foreign;
-}
-
 static void
-gst_vaapi_window_glx_destroy_context(GstVaapiWindowGLX *window)
+_gst_vaapi_window_glx_destroy_context(GstVaapiWindowGLX *window)
 {
     GstVaapiWindowGLXPrivate * const priv = window->priv;
-    Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
 
-    if (priv->context) {
-        if (!priv->foreign_context) {
-            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
-            if (glXGetCurrentContext() == priv->context) {
-                /* XXX: if buffers were never swapped, the application
-                   will crash later with the NVIDIA driver */
-                if (!priv->swapped_buffers)
-                    gl_swap_buffers(dpy, GST_VAAPI_OBJECT_ID(window));
-                gl_make_current(dpy, None, NULL, NULL);
-            }
-            glXDestroyContext(dpy, priv->context);
-            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
-        }
-        priv->context         = NULL;
-        priv->foreign_context = FALSE;
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+    if (priv->gl_context) {
+        gl_destroy_context(priv->gl_context);
+        priv->gl_context = NULL;
     }
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
 }
 
 static gboolean
-gst_vaapi_window_glx_create_context(GstVaapiWindowGLX *window)
+_gst_vaapi_window_glx_create_context(
+    GstVaapiWindowGLX *window,
+    GLXContext         foreign_context
+)
 {
     GstVaapiWindowGLXPrivate * const priv = window->priv;
     Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
-    GLXContext                       ctx  = NULL;
-    GLContextState                   cs;
-    guint                            width, height;
-    gboolean                         has_errors = TRUE;
+    GLContextState                   parent_cs;
 
-    if (!gst_vaapi_window_glx_create_visual(window))
-        return FALSE;
+    parent_cs.display = dpy;
+    parent_cs.window  = None;
+    parent_cs.context = foreign_context;
 
     GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
-    ctx = glXCreateContext(dpy, priv->vi, NULL, True);
-    if (ctx && glXIsDirect(dpy, ctx)) {
-        _gst_vaapi_window_glx_set_context(window, ctx, FALSE);
-        if (gl_make_current(dpy, GST_VAAPI_OBJECT_ID(window), ctx, &cs)) {
-            glDisable(GL_DEPTH_TEST);
-            glDepthMask(GL_FALSE);
-            glDisable(GL_CULL_FACE);
-            glDrawBuffer(GL_BACK);
-            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-            glEnable(GL_BLEND);
-            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-            gst_vaapi_window_get_size(GST_VAAPI_WINDOW(window), &width, &height);
-            gl_resize(width, height);
-
-            gl_set_bgcolor(0);
-            glClear(GL_COLOR_BUFFER_BIT);
-            if (cs.context)
-                gl_make_current(dpy, cs.window, cs.context, NULL);
-            has_errors = FALSE;
-        }
+    priv->gl_context = gl_create_context(dpy, DefaultScreen(dpy), &parent_cs);
+    if (!priv->gl_context) {
+        GST_DEBUG("could not create GLX context");
+        goto end;
     }
-    else if (ctx)
-        glXDestroyContext(dpy, ctx);
-    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
 
-    return !has_errors;
+    if (!glXIsDirect(dpy, priv->gl_context->context)) {
+        GST_DEBUG("could not create a direct-rendering GLX context");
+        goto out_destroy_context;
+    }
+    goto end;
+
+out_destroy_context:
+    gl_destroy_context(priv->gl_context);
+    priv->gl_context = NULL;
+end:
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    return priv->gl_context != NULL;
 }
 
-static inline void
-gst_vaapi_window_glx_destroy_visual(GstVaapiWindowGLX *window)
+static gboolean
+_gst_vaapi_window_glx_ensure_context(
+    GstVaapiWindowGLX *window,
+    GLXContext         foreign_context
+)
 {
     GstVaapiWindowGLXPrivate * const priv = window->priv;
 
-    if (priv->vi) {
-        if (priv->vi != &priv->vi_static)
-            XFree(priv->vi);
-        priv->vi = NULL;
+    if (priv->gl_context) {
+        if (!foreign_context || foreign_context == priv->gl_context->context)
+            return TRUE;
+        _gst_vaapi_window_glx_destroy_context(window);
     }
+    return _gst_vaapi_window_glx_create_context(window, foreign_context);
 }
 
-static XVisualInfo *
-gst_vaapi_window_glx_create_visual(GstVaapiWindowGLX *window)
+static gboolean
+gst_vaapi_window_glx_ensure_context(
+    GstVaapiWindowGLX *window,
+    GLXContext         foreign_context
+)
 {
     GstVaapiWindowGLXPrivate * const priv = window->priv;
-    Display * const dpy = GST_VAAPI_OBJECT_XDISPLAY(window);
-    XWindowAttributes wattr;
-    int screen;
-    gboolean has_errors;
-
-    /* XXX: add and use a GstVaapiWindow:double-buffer property? */
-    static GLint gl_visual_attr[] = {
-        GLX_RGBA,
-        GLX_RED_SIZE,   1,
-        GLX_GREEN_SIZE, 1,
-        GLX_BLUE_SIZE,  1,
-        GLX_DOUBLEBUFFER,
-        GL_NONE
-    };
-
-    if (!priv->vi) {
-        /* XXX: add and use a GstVaapiDisplayX11:x11-screen property? */
-        screen = DefaultScreen(dpy);
-
-        GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
-        x11_trap_errors();
-        if (!priv->foreign_window)
-            priv->vi = glXChooseVisual(dpy, screen, gl_visual_attr);
-        else {
-            XGetWindowAttributes(dpy, GST_VAAPI_OBJECT_ID(window), &wattr);
-            if (XMatchVisualInfo(dpy, screen, wattr.depth, wattr.visual->class,
-                                 &priv->vi_static))
-                priv->vi = &priv->vi_static;
-        }
-        has_errors = x11_untrap_errors() != 0;
-        GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
+    GLContextState old_cs;
+    guint width, height;
 
-        if (has_errors)
-            return NULL;
+    if (!_gst_vaapi_window_glx_ensure_context(window, foreign_context))
+        return FALSE;
+
+    priv->gl_context->window = GST_VAAPI_OBJECT_ID(window);
+    if (!gl_set_current_context(priv->gl_context, &old_cs)) {
+        GST_DEBUG("could not make newly created GLX context current");
+        return FALSE;
     }
-    return priv->vi;
+
+    glDisable(GL_DEPTH_TEST);
+    glDepthMask(GL_FALSE);
+    glDisable(GL_CULL_FACE);
+    glDrawBuffer(GL_BACK);
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    gst_vaapi_window_get_size(GST_VAAPI_WINDOW(window), &width, &height);
+    gl_resize(width, height);
+
+    gl_set_bgcolor(0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    gl_set_current_context(&old_cs, NULL);
+    return TRUE;
 }
 
 static Visual *
 gst_vaapi_window_glx_get_visual(GstVaapiWindow *window)
 {
-    XVisualInfo *vi;
+    GstVaapiWindowGLX * const glx_window = GST_VAAPI_WINDOW_GLX(window);
 
-    vi = gst_vaapi_window_glx_create_visual(GST_VAAPI_WINDOW_GLX(window));
-    if (!vi)
+    if (!_gst_vaapi_window_glx_ensure_context(glx_window, NULL))
         return NULL;
-    return vi->visual;
+    return glx_window->priv->gl_context->visual->visual;
 }
 
 static void
@@ -259,33 +217,34 @@ gst_vaapi_window_glx_create_colormap(GstVaapiWindowGLX *window)
     Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
     int                              screen;
     XWindowAttributes                wattr;
-    XVisualInfo                     *vi;
-    gboolean                         has_errors;
+    gboolean                         success = FALSE;
 
     if (!priv->cmap) {
-        GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
-        x11_trap_errors();
         if (!priv->foreign_window) {
-            vi = gst_vaapi_window_glx_create_visual(window);
-            if (vi) {
-                /* XXX: add a GstVaapiDisplayX11:x11-screen property? */
-                screen     = DefaultScreen(dpy);
-                priv->cmap = XCreateColormap(
-                    dpy,
-                    RootWindow(dpy, screen),
-                    vi->visual,
-                    AllocNone
-                );
-            }
+            if (!_gst_vaapi_window_glx_ensure_context(window, NULL))
+                return None;
+            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+            x11_trap_errors();
+            /* XXX: add a GstVaapiDisplayX11:x11-screen property? */
+            screen     = DefaultScreen(dpy);
+            priv->cmap = XCreateColormap(
+                dpy,
+                RootWindow(dpy, screen),
+                priv->gl_context->visual->visual,
+                AllocNone
+            );
+            success = x11_untrap_errors() == 0;
+            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
         }
         else {
+            GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
+            x11_trap_errors();
             XGetWindowAttributes(dpy, GST_VAAPI_OBJECT_ID(window), &wattr);
             priv->cmap = wattr.colormap;
+            success = x11_untrap_errors() == 0;
+            GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
         }
-        has_errors = x11_untrap_errors() != 0;
-        GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
-
-        if (has_errors)
+        if (!success)
             return None;
     }
     return priv->cmap;
@@ -302,7 +261,7 @@ gst_vaapi_window_glx_resize(GstVaapiWindow *window, guint width, guint height)
 {
     GstVaapiWindowGLXPrivate * const priv = GST_VAAPI_WINDOW_GLX(window)->priv;
     Display * const                  dpy  = GST_VAAPI_OBJECT_XDISPLAY(window);
-    GLContextState                   cs;
+    GLContextState                   old_cs;
 
     if (!GST_VAAPI_WINDOW_CLASS(gst_vaapi_window_glx_parent_class)->
         resize(window, width, height))
@@ -310,10 +269,9 @@ gst_vaapi_window_glx_resize(GstVaapiWindow *window, guint width, guint height)
 
     GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
     XSync(dpy, False); /* make sure resize completed */
-    if (gl_make_current(dpy, GST_VAAPI_OBJECT_ID(window), priv->context, &cs)) {
+    if (gl_set_current_context(priv->gl_context, &old_cs)) {
         gl_resize(width, height);
-        if (cs.context)
-            gl_make_current(dpy, cs.window, cs.context, NULL);
+        gl_set_current_context(&old_cs, NULL);
     }
     GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
     return TRUE;
@@ -324,8 +282,7 @@ gst_vaapi_window_glx_finalize(GObject *object)
 {
     GstVaapiWindowGLX * const window = GST_VAAPI_WINDOW_GLX(object);
 
-    gst_vaapi_window_glx_destroy_context(window);
-    gst_vaapi_window_glx_destroy_visual(window);
+    _gst_vaapi_window_glx_destroy_context(window);
     gst_vaapi_window_glx_destroy_colormap(window);
 
     G_OBJECT_CLASS(gst_vaapi_window_glx_parent_class)->finalize(object);
@@ -377,8 +334,6 @@ gst_vaapi_window_glx_constructed(GObject *object)
     GstVaapiWindowGLXPrivate * const priv = GST_VAAPI_WINDOW_GLX(object)->priv;
     GObjectClass *parent_class;
 
-    priv->foreign_context = priv->context != NULL;
-
     parent_class = G_OBJECT_CLASS(gst_vaapi_window_glx_parent_class);
     if (parent_class->constructed)
         parent_class->constructed(object);
@@ -386,8 +341,8 @@ gst_vaapi_window_glx_constructed(GObject *object)
     priv->foreign_window =
         gst_vaapi_window_x11_is_foreign_xid(GST_VAAPI_WINDOW_X11(object));
 
-    priv->is_constructed = priv->foreign_context ||
-        gst_vaapi_window_glx_create_context(GST_VAAPI_WINDOW_GLX(object));
+    priv->is_constructed =
+        gst_vaapi_window_glx_ensure_context(GST_VAAPI_WINDOW_GLX(object), NULL);
 }
 
 static void
@@ -429,13 +384,10 @@ gst_vaapi_window_glx_init(GstVaapiWindowGLX *window)
     GstVaapiWindowGLXPrivate *priv = GST_VAAPI_WINDOW_GLX_GET_PRIVATE(window);
 
     window->priv                = priv;
-    priv->vi                    = NULL;
     priv->cmap                  = None;
-    priv->context               = NULL;
+    priv->gl_context            = NULL;
     priv->is_constructed        = FALSE;
-    priv->foreign_context       = FALSE;
     priv->foreign_window        = FALSE;
-    priv->swapped_buffers       = FALSE;
 }
 
 /**
@@ -505,7 +457,7 @@ gst_vaapi_window_glx_get_context(GstVaapiWindowGLX *window)
     g_return_val_if_fail(GST_VAAPI_IS_WINDOW_GLX(window), NULL);
     g_return_val_if_fail(window->priv->is_constructed, FALSE);
 
-    return window->priv->context;
+    return window->priv->gl_context->context;
 }
 
 /**
@@ -526,13 +478,7 @@ gst_vaapi_window_glx_set_context(GstVaapiWindowGLX *window, GLXContext ctx)
     g_return_val_if_fail(GST_VAAPI_IS_WINDOW_GLX(window), FALSE);
     g_return_val_if_fail(window->priv->is_constructed, FALSE);
 
-    gst_vaapi_window_glx_destroy_context(window);
-
-    if (ctx) {
-        _gst_vaapi_window_glx_set_context(window, ctx, TRUE);
-        return TRUE;
-    }
-    return gst_vaapi_window_glx_create_context(window);
+    return gst_vaapi_window_glx_ensure_context(window, ctx);
 }
 
 /**
@@ -554,12 +500,7 @@ gst_vaapi_window_glx_make_current(GstVaapiWindowGLX *window)
     g_return_val_if_fail(window->priv->is_constructed, FALSE);
 
     GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
-    success = gl_make_current(
-        GST_VAAPI_OBJECT_XDISPLAY(window),
-        GST_VAAPI_OBJECT_ID(window),
-        window->priv->context,
-        NULL
-    );
+    success = gl_set_current_context(window->priv->gl_context, NULL);
     GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
     return success;
 }
@@ -579,14 +520,8 @@ gst_vaapi_window_glx_swap_buffers(GstVaapiWindowGLX *window)
     g_return_if_fail(window->priv->is_constructed);
 
     GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
-    gl_swap_buffers(
-        GST_VAAPI_OBJECT_XDISPLAY(window),
-        GST_VAAPI_OBJECT_ID(window)
-    );
-    glClear(GL_COLOR_BUFFER_BIT);
+    gl_swap_buffers(window->priv->gl_context);
     GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
-
-    window->priv->swapped_buffers = TRUE;
 }
 
 /**