[RFC] [PATCH 1/8] [xserver] dix: add a mechanism for iterating through all subresources

Erkki Seppälä erkki.seppala at vincit.fi
Mon Dec 27 06:56:55 PST 2010


The mechanism allows iterating even through subresources that don't
have specific XID's. When such 'resources' are iterated, the XID for
them will be zero. A resource type can assign an iteration function
for its subresources with SetResourceTypeFindSubResFunc; by default
resources are assumed not to contain subresources.

The purpose of this extension is to enable accurate accounting of
the resources a resource consumes or uses.

This patch provides the subresource iteration functions for Windows
and GCs.

Reviewed-by: Rami Ylimäki <rami.ylimaki at vincit.fi>
---
 dix/resource.c     |  125 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 include/resource.h |   18 +++++++
 2 files changed, 142 insertions(+), 1 deletions(-)

diff --git a/dix/resource.c b/dix/resource.c
index 72c0761..66fc2ab 100644
--- a/dix/resource.c
+++ b/dix/resource.c
@@ -187,6 +187,7 @@ RESTYPE TypeMask;
 struct ResourceType {
     DeleteType deleteFunc;
     SizeType sizeFunc;
+    FindTypeSubResources findSubResFunc;
     int errorValue;
 };
 
@@ -212,6 +213,25 @@ GetDefaultBytes(pointer value, XID id, ResourceSizePtr size)
 }
 
 /**
+ * Used by all resources that don't specify a function to iterate
+ * through subresources. Currently this is used for all resources with
+ * insignificant memory usage.
+ *
+ * @see FindSubResources, SetResourceTypeFindSubResFunc
+ *
+ * @param[in] value Pointer to resource object.
+ *
+ * @param[in] func Function to call for each subresource.
+
+ * @param[out] cdata Pointer to opaque data.
+ */
+static void
+DefaultFindSubRes(pointer value, FindAllRes func, pointer cdata)
+{
+    /* do nothing */
+}
+
+/**
  * Calculate drawable size in bytes. Reference counting is not taken
  * into account.
  *
@@ -304,13 +324,45 @@ GetWindowBytes(pointer value, XID id, ResourceSizePtr size)
 }
 
 /**
+ * Iterate through subresources of a window. The purpose of this
+ * function is to gather accurate information on what resources
+ * a resource uses.
+ *
+ * @note Currently only sub-pixmaps are iterated
+ *
+ * @param[in] value  Pointer to a window
+ *
+ * @param[in] func   Function to call with each subresource
+ *
+ * @param[out] cdata Pointer to opaque data
+ */
+static void
+FindWindowSubRes(pointer value, FindAllRes func, pointer cdata)
+{
+    WindowPtr window = value;
+
+    /* Currently only pixmap subresources are reported to clients. */
+
+    if (window->backgroundState == BackgroundPixmap)
+    {
+        PixmapPtr pixmap = window->background.pixmap;
+        func(window->background.pixmap, pixmap->drawable.id, RT_PIXMAP, cdata);
+    }
+    if (window->border.pixmap && !window->borderIsPixel)
+    {
+        PixmapPtr pixmap = window->border.pixmap;
+        func(window->background.pixmap, pixmap->drawable.id, RT_PIXMAP, cdata);
+    }
+}
+
+/**
  * Calculate graphics context size in bytes. The purpose of this
  * function is to estimate memory usage that can be attributed to all
  * pixmap references of the graphics context.
  *
  * @param[in] value Pointer to a graphics context.
  *
- * @param[in] id Resource ID of graphics context.
+ * @param[in] id    Resource ID of graphics context.
  *
  * @param[out] size Estimate of memory usage attributed to a all
  *                  pixmap references of a graphics context.
@@ -341,56 +393,98 @@ GetGcBytes(pointer value, XID id, ResourceSizePtr size)
     }
 }
 
+/**
+ * Iterate through subresources of a graphics context. The purpose of
+ * this function is to gather accurate information on what resources a
+ * resource uses.
+ *
+ * @note Currently only sub-pixmaps are iterated
+ *
+ * @param[in] value  Pointer to a window
+ *
+ * @param[in] func   Function to call with each subresource
+ *
+ * @param[out] cdata Pointer to opaque data
+ */
+static void
+FindGCSubRes(pointer value, FindAllRes func, pointer cdata)
+{
+    GCPtr gc = value;
+
+    /* Currently only pixmap subresources are reported to clients. */
+
+    if (gc->stipple)
+    {
+        PixmapPtr pixmap = gc->stipple;
+        func(pixmap, pixmap->drawable.id, RT_PIXMAP, cdata);
+    }
+    if (gc->tile.pixmap && !gc->tileIsPixel)
+    {
+        PixmapPtr pixmap = gc->tile.pixmap;
+        func(pixmap, pixmap->drawable.id, RT_PIXMAP, cdata);
+    }
+}
+
 static struct ResourceType *resourceTypes;
 static const struct ResourceType predefTypes[] = {
     [RT_NONE & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = (DeleteType)NoopDDA,
 	.sizeFunc = GetDefaultBytes,
+        .findSubResFunc = DefaultFindSubRes,
 	.errorValue = BadValue,
     },
     [RT_WINDOW & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = DeleteWindow,
 	.sizeFunc = GetWindowBytes,
+        .findSubResFunc = FindWindowSubRes,
 	.errorValue = BadWindow,
     },
     [RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = dixDestroyPixmap,
 	.sizeFunc = GetPixmapBytes,
+        .findSubResFunc = DefaultFindSubRes,
 	.errorValue = BadPixmap,
     },
     [RT_GC & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = FreeGC,
 	.sizeFunc = GetGcBytes,
+        .findSubResFunc = FindGCSubRes,
 	.errorValue = BadGC,
     },
     [RT_FONT & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = CloseFont,
 	.sizeFunc = GetDefaultBytes,
+        .findSubResFunc = DefaultFindSubRes,
 	.errorValue = BadFont,
     },
     [RT_CURSOR & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = FreeCursor,
 	.sizeFunc = GetDefaultBytes,
+        .findSubResFunc = DefaultFindSubRes,
 	.errorValue = BadCursor,
     },
     [RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = FreeColormap,
 	.sizeFunc = GetDefaultBytes,
+        .findSubResFunc = DefaultFindSubRes,
 	.errorValue = BadColor,
     },
     [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = FreeClientPixels,
 	.sizeFunc = GetDefaultBytes,
+        .findSubResFunc = DefaultFindSubRes,
 	.errorValue = BadColor,
     },
     [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = OtherClientGone,
 	.sizeFunc = GetDefaultBytes,
+        .findSubResFunc = DefaultFindSubRes,
 	.errorValue = BadValue,
     },
     [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = DeletePassiveGrab,
 	.sizeFunc = GetDefaultBytes,
+        .findSubResFunc = DefaultFindSubRes,
 	.errorValue = BadValue,
     }
 };
@@ -422,6 +516,7 @@ CreateNewResourceType(DeleteType deleteFunc, char *name)
     resourceTypes = types;
     resourceTypes[next].deleteFunc = deleteFunc;
     resourceTypes[next].sizeFunc = GetDefaultBytes;
+    resourceTypes[next].findSubResFunc = DefaultFindSubRes;
     resourceTypes[next].errorValue = BadValue;
 
     /* Called even if name is NULL, to remove any previous entry */
@@ -463,6 +558,24 @@ SetResourceTypeSizeFunc(RESTYPE type, SizeType sizeFunc)
     resourceTypes[type & TypeMask].sizeFunc = sizeFunc;
 }
 
+/**
+ * Provide a function for iterating the subresources of a resource.
+ * This allows for example more accurate accounting of the (memory)
+ * resources consumed by a resource.
+ *
+ * @see FindSubResources
+ *
+ * @param[in] type     Resource type used in size calculations.
+ *
+ * @param[in] sizeFunc Function to calculate the size of a single
+ *                     resource.
+ */
+void
+SetResourceTypeFindSubResFunc(RESTYPE type, FindTypeSubResources findFunc)
+{
+    resourceTypes[type & TypeMask].findSubResFunc = findFunc;
+}
+
 void
 SetResourceTypeErrorValue(RESTYPE type, int errorValue)
 {
@@ -906,6 +1019,16 @@ FindClientResourcesByType(
     }
 }
 
+void FindSubResources(
+    pointer    resource,
+    RESTYPE    type,
+    FindAllRes func,
+    pointer    cdata
+){
+    struct ResourceType rtype = resourceTypes[type & TypeMask];
+    rtype.findSubResFunc(resource, func, cdata);
+}
+
 void
 FindAllClientResources(
     ClientPtr client,
diff --git a/include/resource.h b/include/resource.h
index 406d74a..aea617c 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -166,6 +166,11 @@ typedef void (*FindAllRes)(
     RESTYPE /*type*/,
     pointer /*cdata*/);
 
+typedef void (*FindTypeSubResources)(
+    pointer /* value */,
+    FindAllRes /* func */,
+    pointer /* cdata */);
+
 typedef Bool (*FindComplexResType)(
     pointer /*value*/,
     XID /*id*/,
@@ -177,6 +182,9 @@ extern _X_EXPORT RESTYPE CreateNewResourceType(
 extern _X_EXPORT SizeType GetResourceTypeSizeFunc(
     RESTYPE /*type*/);
 
+extern _X_EXPORT void SetResourceTypeFindSubResFunc(
+    RESTYPE /*type*/, FindTypeSubResources /*findFunc*/);
+
 extern _X_EXPORT void SetResourceTypeSizeFunc(
     RESTYPE /*type*/, SizeType /*sizeFunc*/);
 
@@ -221,6 +229,16 @@ extern _X_EXPORT void FindClientResourcesByType(
     FindResType /*func*/,
     pointer /*cdata*/);
 
+/** @brief Iterate through all subresources of a resource.
+
+    @note The XID argument provided to the FindAllRes function
+          may be 0 for subresources that don't have an XID */
+extern _X_EXPORT void FindSubResources(
+    pointer /*resource*/,
+    RESTYPE /*type*/,
+    FindAllRes /*func*/,
+    pointer /*cdata*/);
+
 extern _X_EXPORT void FindAllClientResources(
     ClientPtr /*client*/,
     FindAllRes /*func*/,
-- 
1.7.0.4



More information about the xorg-devel mailing list