[cogl/cogl-1.14] Bind the dummy surface or drawable when current onscreen is destroyed



commit 1e00ff268ea44f0782caebc0c3c9008b12b99100
Author: Neil Roberts <neil linux intel com>
Date:   Thu Jan 24 16:28:09 2013 +0000

    Bind the dummy surface or drawable when current onscreen is destroyed
    
    Similar to commit 2c0cfdefbb9d1 for the SDL2 winsys, the GLX and EGL
    window systems need to bind the dummy surface or drawable when the
    currently bound onscreen is destroyed so that there will always be a
    valid context bound.
    
    Previously I got the idea that this would not be necessary on GLX
    because the documentation for glXDestroyDrawable states that the
    drawable won't actually be destroyed if it is currently bound until it
    becomes unbound. However it doesn't say what happens if the underlying
    X window is also destroyed and after testing it seems this causes a
    segfault in Mesa in GLX and an XError for EGLX.
    
    Reviewed-by: Robert Bragg <robert linux intel com>
    
    (cherry picked from commit 4a464eec8c5b5832b9fd6b69746ab4ab36229182)

 cogl/winsys/cogl-winsys-egl.c |   17 ++++++++++++++++-
 cogl/winsys/cogl-winsys-glx.c |   27 ++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 2 deletions(-)
---
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index 32a2d59..af8181b 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
+ * Copyright (C) 2007,2008,2009,2010,2011,2013 Intel Corporation.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -625,6 +625,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = framebuffer->context;
+  CoglDisplayEGL *egl_display = context->display->winsys;
   CoglRenderer *renderer = context->display->renderer;
   CoglRendererEGL *egl_renderer = renderer->winsys;
   CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
@@ -632,8 +633,22 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
   /* If we never successfully allocated then there's nothing to do */
   if (egl_onscreen == NULL)
     return;
+
   if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
     {
+      /* Cogl always needs a valid context bound to something so if we
+       * are destroying the onscreen that is currently bound we'll
+       * switch back to the dummy drawable. */
+      if (egl_display->dummy_surface != EGL_NO_SURFACE &&
+          (egl_display->current_draw_surface == egl_onscreen->egl_surface ||
+           egl_display->current_read_surface == egl_onscreen->egl_surface))
+        {
+          _cogl_winsys_egl_make_current (context->display,
+                                         egl_display->dummy_surface,
+                                         egl_display->dummy_surface,
+                                         egl_display->current_context);
+        }
+
       if (eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface)
           == EGL_FALSE)
         g_warning ("Failed to destroy EGL surface");
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 22078cc..f91e73a 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
+ * Copyright (C) 2007,2008,2009,2010,2011,2013 Intel Corporation.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -1046,12 +1046,15 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = framebuffer->context;
+  CoglContextGLX *glx_context = context->winsys;
+  CoglGLXDisplay *glx_display = context->display->winsys;
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (context->display->renderer);
   CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
   CoglXlibTrapState old_state;
   CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
   CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
+  GLXDrawable drawable;
 
   /* If we never successfully allocated then there's nothing to do */
   if (glx_onscreen == NULL)
@@ -1059,6 +1062,28 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
 
   _cogl_xlib_renderer_trap_errors (context->display->renderer, &old_state);
 
+  drawable =
+    glx_onscreen->glxwin == None ? xlib_onscreen->xwin : glx_onscreen->glxwin;
+
+  /* Cogl always needs a valid context bound to something so if we are
+   * destroying the onscreen that is currently bound we'll switch back
+   * to the dummy drawable. Although the documentation for
+   * glXDestroyWindow states that a currently bound window won't
+   * actually be destroyed until it is unbound, it looks like this
+   * doesn't work if the X window itself is destroyed */
+  if (drawable == glx_context->current_drawable)
+    {
+      GLXDrawable dummy_drawable = (glx_display->dummy_glxwin == None ?
+                                    glx_display->dummy_xwin :
+                                    glx_display->dummy_glxwin);
+
+      glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy,
+                                           dummy_drawable,
+                                           dummy_drawable,
+                                           glx_display->glx_context);
+      glx_context->current_drawable = dummy_drawable;
+    }
+
   if (glx_onscreen->glxwin != None)
     {
       glx_renderer->glXDestroyWindow (xlib_renderer->xdpy,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]