Revision: 296 http://trac.macosforge.org/projects/xquartz/changeset/296 Author: gstaplin@apple.com Date: 2009-03-08 13:48:53 -0700 (Sun, 08 Mar 2009) Log Message: ----------- Work around a surface destruction issue on withdraw/unmap, by recreating the surface in 2 possible paths (glViewport and glXSwapBuffers). This isn't ideal, but it fixes the test case, and should resolve the issue with most apps. There may be an app or 2 that have redraw issues even after this. The old libGL had black windows after a withdraw/unmap remap pattern, due to surfaces being destroyed, and the old libGL didn't recreate them. The old libGL also leaked surfaces in some cases. Modified Paths: -------------- AppleSGLX/trunk/apple_glx.c AppleSGLX/trunk/apple_glx_context.c AppleSGLX/trunk/apple_glx_context.h AppleSGLX/trunk/apple_xgl_api_viewport.c AppleSGLX/trunk/glxcmds.c Modified: AppleSGLX/trunk/apple_glx.c =================================================================== --- AppleSGLX/trunk/apple_glx.c 2009-03-08 04:08:32 UTC (rev 295) +++ AppleSGLX/trunk/apple_glx.c 2009-03-08 20:48:53 UTC (rev 296) @@ -141,6 +141,8 @@ void apple_glx_swap_buffers(void *ptr) { struct apple_glx_context *ac = ptr; + + /* This may not be needed with CGLFlushDrawable: */ glFlush(); apple_cgl.flush_drawable(ac->context_obj); } Modified: AppleSGLX/trunk/apple_glx_context.c =================================================================== --- AppleSGLX/trunk/apple_glx_context.c 2009-03-08 04:08:32 UTC (rev 295) +++ AppleSGLX/trunk/apple_glx_context.c 2009-03-08 20:48:53 UTC (rev 296) @@ -142,6 +142,7 @@ ac->need_update = false; ac->is_current = false; ac->made_current = false; + ac->last_surface_window = None; apple_visual_create_pfobj(&ac->pixel_format_obj, mode, &ac->double_buffered, /*offscreen*/ false); @@ -291,7 +292,7 @@ oldac->is_current = false; if(NULL == ac) { - /*Clear the current context.*/ + /*Clear the current context for this thread.*/ apple_cgl.set_current_context(NULL); if(oldac) { @@ -301,6 +302,9 @@ oldac->drawable->destroy(oldac->drawable); oldac->drawable = NULL; } + + /* Invalidate this to prevent surface recreation. */ + oldac->last_surface_window = None; } return false; @@ -321,6 +325,9 @@ ac->drawable->destroy(ac->drawable); ac->drawable = NULL; } + + /* Invalidate this to prevent surface recreation. */ + ac->last_surface_window = None; apple_glx_diagnostic("%s: drawable is None, error is: %d\n", __func__, error); @@ -389,6 +396,9 @@ ac->thread_id = pthread_self(); + /* This will be set if the pending_destroy code indicates it should be: */ + ac->last_surface_window = None; + switch(ac->drawable->type) { case APPLE_GLX_DRAWABLE_PBUFFER: case APPLE_GLX_DRAWABLE_SURFACE: @@ -408,10 +418,19 @@ return false; } -bool apple_glx_is_current_drawable(void *ptr, GLXDrawable drawable) { +bool apple_glx_is_current_drawable(Display *dpy, void *ptr, + GLXDrawable drawable) { struct apple_glx_context *ac = ptr; + + if(ac->drawable && ac->drawable->drawable == drawable) { + return true; + } else if(NULL == ac->drawable && None != ac->last_surface_window) { + apple_glx_context_update(dpy, ac); - return (ac->drawable && ac->drawable->drawable == drawable); + return (ac->drawable && ac->drawable->drawable == drawable); + } + + return false; } bool apple_glx_copy_context(void *currentptr, void *srcptr, void *destptr, @@ -484,9 +503,19 @@ return updated; } -void apple_glx_context_update(void *ptr) { +void apple_glx_context_update(Display *dpy, void *ptr) { struct apple_glx_context *ac = ptr; + if(NULL == ac->drawable && None != ac->last_surface_window) { + bool failed; + + /* Attempt to recreate the surface for a destroyed drawable. */ + failed = apple_glx_make_current_context(dpy, ac, ac, ac->last_surface_window); + + apple_glx_diagnostic("%s: surface recreation failed? %s\n", __func__, + failed ? "YES" : "NO"); + } + if(ac->need_update) { xp_update_gl_context(ac->context_obj); ac->need_update = false; @@ -509,6 +538,8 @@ d = ac->drawable; + ac->last_surface_window = d->drawable; + ac->drawable = NULL; /* Modified: AppleSGLX/trunk/apple_glx_context.h =================================================================== --- AppleSGLX/trunk/apple_glx_context.h 2009-03-08 04:08:32 UTC (rev 295) +++ AppleSGLX/trunk/apple_glx_context.h 2009-03-08 20:48:53 UTC (rev 296) @@ -50,6 +50,13 @@ bool need_update; bool is_current; /* True if the context is current in some thread. */ bool made_current; /* True if the context has ever been made current. */ + + /* + * last_surface is set by the pending_destroy code handler for a drawable. + * Due to a CG difference, we have to recreate a surface if the window + * is unmapped and mapped again. + */ + Window last_surface_window; struct apple_glx_context *previous, *next; }; @@ -59,7 +66,7 @@ void apple_glx_destroy_context(void **ptr, Display *dpy); bool apple_glx_make_current_context(Display *dpy, void *oldptr, void *ptr, GLXDrawable drawable); -bool apple_glx_is_current_drawable(void *ptr, GLXDrawable drawable); +bool apple_glx_is_current_drawable(Display *dpy, void *ptr, GLXDrawable drawable); bool apple_glx_copy_context(void *currentptr, void *srcptr, void *destptr, unsigned long mask, int *errorptr, @@ -67,6 +74,6 @@ int apple_glx_context_surface_changed(unsigned int uid, pthread_t caller); -void apple_glx_context_update(void *ptr); +void apple_glx_context_update(Display *dpy, void *ptr); #endif /*APPLE_GLX_CONTEXT_H*/ Modified: AppleSGLX/trunk/apple_xgl_api_viewport.c =================================================================== --- AppleSGLX/trunk/apple_xgl_api_viewport.c 2009-03-08 04:08:32 UTC (rev 295) +++ AppleSGLX/trunk/apple_xgl_api_viewport.c 2009-03-08 20:48:53 UTC (rev 296) @@ -34,9 +34,10 @@ void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { GLXContext gc = __glXGetCurrentContext(); + Display *dpy = glXGetCurrentDisplay(); if(gc && gc->apple) - apple_glx_context_update(gc->apple); + apple_glx_context_update(dpy, gc->apple); __gl_api.Viewport(x, y, width, height); } Modified: AppleSGLX/trunk/glxcmds.c =================================================================== --- AppleSGLX/trunk/glxcmds.c 2009-03-08 04:08:32 UTC (rev 295) +++ AppleSGLX/trunk/glxcmds.c 2009-03-08 20:48:53 UTC (rev 296) @@ -610,7 +610,7 @@ PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable) { GLXContext gc = glXGetCurrentContext(); - if(gc && apple_glx_is_current_drawable(gc->apple, drawable)) { + if(gc && apple_glx_is_current_drawable(dpy, gc->apple, drawable)) { apple_glx_swap_buffers(gc->apple); } else { __glXSendError(dpy, GLXBadCurrentWindow, 0, X_GLXSwapBuffers, false);