[PATCH] dix/glx/composite: fixup colormap visuals correctly.

Dave Airlie airlied at redhat.com
Sun Sep 27 19:40:57 PDT 2009


One of the first accurate comments I've come across:
/*
 * Fix up any existing installed colormaps -- we'll assume that
 * the only ones created so far have been installed.  If this
 * isn't true, we'll have to walk the resource database looking
 * for all colormaps.
 */
Guess what, it was right, installed colormaps are useless information
due to render installing a bunch, this meant every so often we'd have
a colormap pointing at a visual that wasn't there anymore since the
realloc moved it, then we'd free the colormap on server exit and
explode.

This patch does it right, it walks the resource list for colormaps
and re-writes the visual bits in them.

Fixes fd.o bug #19470.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 composite/compinit.c |   34 +---------------------------------
 dix/colormap.c       |   29 +++++++++++++++++++++++++++++
 glx/glxscreens.c     |   33 +++------------------------------
 include/colormap.h   |    3 +++
 4 files changed, 36 insertions(+), 63 deletions(-)

diff --git a/composite/compinit.c b/composite/compinit.c
index 6159e4e..daf01d3 100644
--- a/composite/compinit.c
+++ b/composite/compinit.c
@@ -249,11 +249,7 @@ compAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs,
 		       CompAlternateVisual *alt)
 {
     VisualPtr	    visual, visuals;
-    int		    i;
     int		    numVisuals;
-    XID		    *installedCmaps;
-    ColormapPtr	    installedCmap;
-    int		    numInstalledCmaps;
     DepthPtr	    depth;
     PictFormatPtr   pPictFormat;
     VisualID	    *vid;
@@ -281,43 +277,15 @@ compAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs,
     if (!vid)
 	return FALSE;
 
-    /* Find the installed colormaps */
-    installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID));
-    if (!installedCmaps) {
-	xfree(vid);
-	return FALSE;
-    }
-    numInstalledCmaps = pScreen->ListInstalledColormaps(pScreen, 
-	    installedCmaps);
-
     /* realloc the visual array to fit the new one in place */
     numVisuals = pScreen->numVisuals;
     visuals = xrealloc(pScreen->visuals, (numVisuals + 1) * sizeof(VisualRec));
     if (!visuals) {
 	xfree(vid);
-	xfree(installedCmaps);
 	return FALSE;
     }
 
-    /*
-     * Fix up any existing installed colormaps -- we'll assume that
-     * the only ones created so far have been installed.  If this
-     * isn't true, we'll have to walk the resource database looking
-     * for all colormaps.
-     */
-    for (i = 0; i < numInstalledCmaps; i++) {
-	int j, rc;
-
-	rc = dixLookupResourceByType((pointer *)&installedCmap,
-				     installedCmaps[i], RT_COLORMAP,
-				     serverClient, DixReadAccess);
-	if (rc != Success)
-	    continue;
-	j = installedCmap->pVisual - pScreen->visuals;
-	installedCmap->pVisual = &visuals[j];
-    }
-
-    xfree(installedCmaps);
+    ColormapFixVisuals(pScreen, visuals);
 
     pScreen->visuals = visuals;
     visual = visuals + pScreen->numVisuals; /* the new one */
diff --git a/dix/colormap.c b/dix/colormap.c
index a5a006e..771fefc 100644
--- a/dix/colormap.c
+++ b/dix/colormap.c
@@ -2690,3 +2690,32 @@ IsMapInstalled(Colormap map, WindowPtr pWin)
     xfree(pmaps);
     return (found);
 }
+
+struct colormap_lookup_data {
+    ScreenPtr pScreen;
+    VisualPtr visuals;
+};
+
+static void _colormap_find_resource(pointer value, XID id,
+				    pointer cdata)
+{
+    struct colormap_lookup_data *cmap_data = cdata;
+    VisualPtr visuals = cmap_data->visuals;
+    ScreenPtr pScreen = cmap_data->pScreen;
+    ColormapPtr cmap = value;
+    int j;
+    
+    j = cmap->pVisual - pScreen->visuals;
+    cmap->pVisual = &visuals[j];
+}
+
+/* something has realloced the visuals, instead of breaking
+   ABI fix it up here - glx and compsite did this wrong */
+void
+ColormapFixVisuals(ScreenPtr pScreen, VisualPtr visuals)
+{
+    struct colormap_lookup_data cdata;
+    cdata.visuals = visuals;
+    cdata.pScreen = pScreen;
+    FindClientResourcesByType(serverClient, RT_COLORMAP, _colormap_find_resource, &cdata);
+}
diff --git a/glx/glxscreens.c b/glx/glxscreens.c
index 81faddd..f93acde 100644
--- a/glx/glxscreens.c
+++ b/glx/glxscreens.c
@@ -250,12 +250,10 @@ GLint glxConvertToXVisualType(int visualType)
 static VisualPtr
 AddScreenVisuals(ScreenPtr pScreen, int count, int d)
 {
-    XID		*installedCmaps, *vids, vid;
-    int		 numInstalledCmaps, numVisuals, i, j;
+    XID		 *vids, vid;
+    int		 numVisuals, i;
     VisualPtr	 visuals;
-    ColormapPtr	 installedCmap;
     DepthPtr	 depth;
-    int		 rc;
 
     depth = NULL;
     for (i = 0; i < pScreen->numDepths; i++) {
@@ -267,45 +265,20 @@ AddScreenVisuals(ScreenPtr pScreen, int count, int d)
     if (depth == NULL)
 	return NULL;
 
-    /* Find the installed colormaps */
-    installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID));
-    if (!installedCmaps)
-	return NULL;
-
-    numInstalledCmaps = pScreen->ListInstalledColormaps(pScreen, installedCmaps);
-
     /* realloc the visual array to fit the new one in place */
     numVisuals = pScreen->numVisuals;
     visuals = xrealloc(pScreen->visuals, (numVisuals + count) * sizeof(VisualRec));
     if (!visuals) {
-	xfree(installedCmaps);
 	return NULL;
     }
 
     vids = xrealloc(depth->vids, (depth->numVids + count) * sizeof(XID));
     if (vids == NULL) {
-	xfree(installedCmaps);
 	xfree(visuals);
 	return NULL;
     }
 
-    /*
-     * Fix up any existing installed colormaps -- we'll assume that
-     * the only ones created so far have been installed.  If this
-     * isn't true, we'll have to walk the resource database looking
-     * for all colormaps.
-     */
-    for (i = 0; i < numInstalledCmaps; i++) {
-	rc = dixLookupResourceByType((pointer *)&installedCmap,
-				     installedCmaps[i], RT_COLORMAP,
-				     serverClient, DixReadAccess);
-	if (rc != Success)
-	    continue;
-	j = installedCmap->pVisual - pScreen->visuals;
-	installedCmap->pVisual = &visuals[j];
-    }
-
-    xfree(installedCmaps);
+    ColormapFixVisuals(pScreen, visuals);
 
     for (i = 0; i < count; i++) {
 	vid = FakeClientID(0);
diff --git a/include/colormap.h b/include/colormap.h
index a3467c9..88585ec 100644
--- a/include/colormap.h
+++ b/include/colormap.h
@@ -179,4 +179,7 @@ extern _X_EXPORT int IsMapInstalled(
     Colormap /*map*/,
     WindowPtr /*pWin*/);
 
+extern _X_EXPORT void ColormapFixVisuals(
+    ScreenPtr /*pScreen*/, 
+    VisualPtr /*visuals*/);
 #endif /* CMAP_H */
-- 
1.6.4.2



More information about the xorg-devel mailing list