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)
This commit is contained in:
Neil Roberts 2013-01-24 16:28:09 +00:00
parent da7971f6be
commit 1e00ff268e
2 changed files with 42 additions and 2 deletions

View File

@ -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");

View File

@ -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,