[Mesa-dev] [PATCH v2 3/4] glx: guard swap-interval functions against destroyed drawables

Nicolai Hähnle nhaehnle at gmail.com
Thu Feb 2 17:19:27 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

The GLX specification says about glXDestroyPixmap:

    "The storage for the GLX pixmap will be freed when it is not current
     to any client."

So arguably, functions like glXSwapIntervalMESA can be called after
glXDestroyPixmap has been called for the currently bound GLXPixmap.
In that case, the GLXDRIDrawable no longer exists, and so we just skip
those calls.

Cc: 17.0 <mesa-stable at lists.freedesktop.org>
---
 src/glx/dri3_glx.c |  4 ++++
 src/glx/glxcmds.c  | 18 +++++++++++++++---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index 2d40f0a..42a94f9 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -557,20 +557,22 @@ dri3_destroy_screen(struct glx_screen *base)
    free(psc);
 }
 
 /** dri3_set_swap_interval
  *
  * Record the application swap interval specification,
  */
 static int
 dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
 {
+   assert(pdraw != NULL);
+
    struct dri3_drawable *priv =  (struct dri3_drawable *) pdraw;
    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
    struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
 
    if (psc->config)
       psc->config->configQueryi(psc->driScreen,
                                 "vblank_mode", &vblank_mode);
 
    switch (vblank_mode) {
    case DRI_CONF_VBLANK_NEVER:
@@ -590,20 +592,22 @@ dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
    return 0;
 }
 
 /** dri3_get_swap_interval
  *
  * Return the stored swap interval
  */
 static int
 dri3_get_swap_interval(__GLXDRIdrawable *pdraw)
 {
+   assert(pdraw != NULL);
+
    struct dri3_drawable *priv =  (struct dri3_drawable *) pdraw;
 
   return priv->swap_interval;
 }
 
 static void
 dri3_bind_tex_image(Display * dpy,
                     GLXDrawable drawable,
                     int buffer, const int *attrib_list)
 {
diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c
index 6c7bbfd..53c9f9c 100644
--- a/src/glx/glxcmds.c
+++ b/src/glx/glxcmds.c
@@ -1754,21 +1754,25 @@ __glXSwapIntervalSGI(int interval)
       return GLX_BAD_VALUE;
    }
 
    psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
 
 #ifdef GLX_DIRECT_RENDERING
    if (gc->isDirect && psc && psc->driScreen &&
           psc->driScreen->setSwapInterval) {
       __GLXDRIdrawable *pdraw =
 	 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
-      psc->driScreen->setSwapInterval(pdraw, interval);
+      /* Simply ignore the command if the GLX drawable has been destroyed but
+       * the context is still bound.
+       */
+      if (pdraw)
+         psc->driScreen->setSwapInterval(pdraw, interval);
       return 0;
    }
 #endif
 
    dpy = gc->currentDpy;
    opcode = __glXSetupForCommand(dpy);
    if (!opcode) {
       return 0;
    }
 
@@ -1800,21 +1804,28 @@ __glXSwapIntervalMESA(unsigned int interval)
 #ifdef GLX_DIRECT_RENDERING
    struct glx_context *gc = __glXGetCurrentContext();
 
    if (gc != &dummyContext && gc->isDirect) {
       struct glx_screen *psc;
 
       psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
       if (psc && psc->driScreen && psc->driScreen->setSwapInterval) {
          __GLXDRIdrawable *pdraw =
 	    GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
-	 return psc->driScreen->setSwapInterval(pdraw, interval);
+
+         /* Simply ignore the command if the GLX drawable has been destroyed but
+          * the context is still bound.
+          */
+         if (!pdraw)
+            return 0;
+
+         return psc->driScreen->setSwapInterval(pdraw, interval);
       }
    }
 #endif
 
    return GLX_BAD_CONTEXT;
 }
 
 
 static int
 __glXGetSwapIntervalMESA(void)
@@ -1822,21 +1833,22 @@ __glXGetSwapIntervalMESA(void)
 #ifdef GLX_DIRECT_RENDERING
    struct glx_context *gc = __glXGetCurrentContext();
 
    if (gc != &dummyContext && gc->isDirect) {
       struct glx_screen *psc;
 
       psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
       if (psc && psc->driScreen && psc->driScreen->getSwapInterval) {
          __GLXDRIdrawable *pdraw =
 	    GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
-	 return psc->driScreen->getSwapInterval(pdraw);
+         if (pdraw)
+            return psc->driScreen->getSwapInterval(pdraw);
       }
    }
 #endif
 
    return 0;
 }
 
 
 /*
 ** GLX_SGI_video_sync
-- 
2.9.3



More information about the mesa-dev mailing list