[RFC] [PATCH v2 3/12] [xserver] render: Report pixmap usage of pictures to resource extension.

Erkki Seppälä erkki.seppala at vincit.fi
Fri Dec 31 05:32:41 PST 2010


From: Rami Ylimäki <rami.ylimaki at vincit.fi>

Signed-off-by: Rami Ylimäki <rami.ylimaki at vincit.fi>
Reviewed-by: Mikhail Gusarov <dottedmag at dottedmag.net>
Reviewed-by: Tiago Vignatti <tiago.vignatti at nokia.com>
---
 Xext/xres.c        |   25 +++++++
 dix/resource.c     |  199 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 include/resource.h |   23 ++++++
 render/picture.c   |   22 ++++++
 4 files changed, 268 insertions(+), 1 deletions(-)

diff --git a/Xext/xres.c b/Xext/xres.c
index ff7cf94..7244677 100644
--- a/Xext/xres.c
+++ b/Xext/xres.c
@@ -294,6 +294,17 @@ ResGetApproxPixmapBytes (PixmapPtr pix)
    return ( nPixels * bytesPerPixel ) / pix->refcnt;
 }
 
+static void
+ResFindResourcePixmaps (pointer value, XID id, RESTYPE type, pointer cdata)
+{
+    SizeType sizeFunc = GetResourceTypeSizeFunc(type);
+    ResourceSizeRec size = { 0, 0 };
+    unsigned long *bytes = cdata;
+ 
+    sizeFunc(value, id, &size);
+    *bytes += size.pixmapRefSize;
+}
+
 static void 
 ResFindPixmaps (pointer value, XID id, pointer cdata)
 {
@@ -329,6 +340,13 @@ ResFindGCPixmaps (pointer value, XID id, pointer cdata)
      *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
 }
 
+static RESTYPE RT_PICTURE = RT_NONE;
+static void
+ResFindPicturePixmaps (pointer value, XID id, pointer cdata)
+{
+    ResFindResourcePixmaps(value, id, RT_PICTURE, cdata);
+}
+
 static int
 ProcXResQueryClientPixmapBytes (ClientPtr client)
 {
@@ -365,6 +383,13 @@ ProcXResQueryClientPixmapBytes (ClientPtr client)
 			      ResFindGCPixmaps, 
                               (pointer)(&bytes));
 
+    /* Render extension picture pixmaps. */
+    RT_PICTURE = LookupResourceType("PICTURE");
+    if (RT_PICTURE != RT_NONE)
+        FindClientResourcesByType(clients[clientID], RT_PICTURE,
+                                  ResFindPicturePixmaps,
+                                  (pointer)(&bytes));
+
 #ifdef COMPOSITE
     /* FIXME: include composite pixmaps too */
 #endif
diff --git a/dix/resource.c b/dix/resource.c
index 6bd2403..7c8a31e 100644
--- a/dix/resource.c
+++ b/dix/resource.c
@@ -142,6 +142,7 @@ Equipment Corporation.
 #include "xace.h"
 #include <assert.h>
 #include "registry.h"
+#include "gcstruct.h"
 
 #ifdef XSERVER_DTRACE
 #include <sys/types.h>
@@ -185,51 +186,213 @@ RESTYPE TypeMask;
 
 struct ResourceType {
     DeleteType deleteFunc;
+    SizeType sizeFunc;
     int errorValue;
 };
 
+/**
+ * Used by all resources that don't specify a function to calculate
+ * resource size. Currently this is used for all resources with
+ * insignificant memory usage.
+ *
+ * @see GetResourceTypeSizeFunc, SetResourceTypeSizeFunc
+ *
+ * @param[in] value Pointer to resource object.
+ *
+ * @param[in] id Resource ID for the object.
+ *
+ * @param[out] size Fill all fields to zero to indicate that size of
+ *                  resource can't be determined.
+ */
+static void
+GetDefaultBytes(pointer value, XID id, ResourceSizePtr size)
+{
+    size->resourceSize = 0;
+    size->pixmapRefSize = 0;
+}
+
+/**
+ * Calculate drawable size in bytes. Reference counting is not taken
+ * into account.
+ *
+ * @param[in] drawable Pointer to a drawable.
+ *
+ * @return Estimate of total memory usage for the drawable.
+ */
+static unsigned long
+GetDrawableBytes(DrawablePtr drawable)
+{
+    int bytes = 0;
+
+    if (drawable)
+    {
+        int bytesPerPixel = drawable->bitsPerPixel >> 3;
+        int numberOfPixels = drawable->width * drawable->height;
+        bytes = numberOfPixels * bytesPerPixel;
+    }
+
+    return bytes;
+}
+
+/**
+ * Calculate pixmap size in bytes. Reference counting is taken into
+ * account. Any extra data attached by extensions and drivers is not
+ * taken into account. The purpose of this function is to estimate
+ * memory usage that can be attributed to single reference of the
+ * pixmap.
+ *
+ * @param[in] value Pointer to a pixmap.
+ *
+ * @param[in] id Resource ID of pixmap. If the pixmap hasn't been
+ *               added as resource, just pass value->drawable.id.
+ *
+ * @param[out] size Estimate of memory usage attributed to a single
+ *                  pixmap reference.
+ */
+static void
+GetPixmapBytes(pointer value, XID id, ResourceSizePtr size)
+{
+    PixmapPtr pixmap = value;
+
+    size->resourceSize = 0;
+    size->pixmapRefSize = 0;
+
+    if (pixmap && pixmap->refcnt)
+    {
+        DrawablePtr drawable = &pixmap->drawable;
+        size->resourceSize = GetDrawableBytes(drawable);
+        size->pixmapRefSize = size->resourceSize / pixmap->refcnt;
+    }
+}
+
+/**
+ * Calculate window size in bytes. The purpose of this function is to
+ * estimate memory usage that can be attributed to all pixmap
+ * references of the window.
+ *
+ * @param[in] value Pointer to a window.
+ *
+ * @param[in] id Resource ID of window.
+ *
+ * @param[out] size Estimate of memory usage attributed to a all
+ *                  pixmap references of a window.
+ */
+static void
+GetWindowBytes(pointer value, XID id, ResourceSizePtr size)
+{
+    SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
+    ResourceSizeRec pixmapSize = { 0, 0 };
+    WindowPtr window = value;
+
+    /* Currently only pixmap bytes are reported to clients. */
+    size->resourceSize = 0;
+
+    /* Calculate pixmap reference sizes. */
+    size->pixmapRefSize = 0;
+    if (window->backgroundState == BackgroundPixmap)
+    {
+        PixmapPtr pixmap = window->background.pixmap;
+        pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+        size->pixmapRefSize += pixmapSize.pixmapRefSize;
+    }
+    if (window->border.pixmap && !window->borderIsPixel)
+    {
+        PixmapPtr pixmap = window->border.pixmap;
+        pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+        size->pixmapRefSize += pixmapSize.pixmapRefSize;
+    }
+}
+
+/**
+ * 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[out] size Estimate of memory usage attributed to a all
+ *                  pixmap references of a graphics context.
+ */
+static void
+GetGcBytes(pointer value, XID id, ResourceSizePtr size)
+{
+    SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
+    ResourceSizeRec pixmapSize = { 0, 0 };
+    GCPtr gc = value;
+
+    /* Currently only pixmap bytes are reported to clients. */
+    size->resourceSize = 0;
+
+    /* Calculate pixmap reference sizes. */
+    size->pixmapRefSize = 0;
+    if (gc->stipple)
+    {
+        PixmapPtr pixmap = gc->stipple;
+        pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+        size->pixmapRefSize += pixmapSize.pixmapRefSize;
+    }
+    if (gc->tile.pixmap && !gc->tileIsPixel)
+    {
+        PixmapPtr pixmap = gc->tile.pixmap;
+        pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+        size->pixmapRefSize += pixmapSize.pixmapRefSize;
+    }
+}
+
 static struct ResourceType *resourceTypes;
 static const struct ResourceType predefTypes[] = {
     [RT_NONE & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = (DeleteType)NoopDDA,
+	.sizeFunc = GetDefaultBytes,
 	.errorValue = BadValue,
     },
     [RT_WINDOW & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = DeleteWindow,
+	.sizeFunc = GetWindowBytes,
 	.errorValue = BadWindow,
     },
     [RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = dixDestroyPixmap,
+	.sizeFunc = GetPixmapBytes,
 	.errorValue = BadPixmap,
     },
     [RT_GC & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = FreeGC,
+	.sizeFunc = GetGcBytes,
 	.errorValue = BadGC,
     },
     [RT_FONT & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = CloseFont,
+	.sizeFunc = GetDefaultBytes,
 	.errorValue = BadFont,
     },
     [RT_CURSOR & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = FreeCursor,
+	.sizeFunc = GetDefaultBytes,
 	.errorValue = BadCursor,
     },
     [RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = FreeColormap,
+	.sizeFunc = GetDefaultBytes,
 	.errorValue = BadColor,
     },
     [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = FreeClientPixels,
+	.sizeFunc = GetDefaultBytes,
 	.errorValue = BadColor,
     },
     [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = OtherClientGone,
+	.sizeFunc = GetDefaultBytes,
 	.errorValue = BadValue,
     },
     [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
 	.deleteFunc = DeletePassiveGrab,
+	.sizeFunc = GetDefaultBytes,
 	.errorValue = BadValue,
-    },
+    }
 };
 
 CallbackListPtr ResourceStateCallback;
@@ -258,6 +421,7 @@ CreateNewResourceType(DeleteType deleteFunc, char *name)
     lastResourceType = next;
     resourceTypes = types;
     resourceTypes[next].deleteFunc = deleteFunc;
+    resourceTypes[next].sizeFunc = GetDefaultBytes;
     resourceTypes[next].errorValue = BadValue;
 
     /* Called even if name is NULL, to remove any previous entry */
@@ -266,6 +430,39 @@ CreateNewResourceType(DeleteType deleteFunc, char *name)
     return next;
 }
 
+/**
+ * Get the function used to calculate resource size. Extensions and
+ * drivers need to be able to determine the current size calculation
+ * function if they want to wrap or override it.
+ *
+ * @param[in] type     Resource type used in size calculations.
+ *
+ * @return Function to calculate the size of a single
+ *                     resource.
+ */
+SizeType
+GetResourceTypeSizeFunc(RESTYPE type)
+{
+    return resourceTypes[type & TypeMask].sizeFunc;
+}
+
+/**
+ * Override the default function that calculates resource size. For
+ * example, video driver knows better how to calculate pixmap memory
+ * usage and can therefore wrap or override size calculation for
+ * RT_PIXMAP.
+ *
+ * @param[in] type     Resource type used in size calculations.
+ *
+ * @param[in] sizeFunc Function to calculate the size of a single
+ *                     resource.
+ */
+void
+SetResourceTypeSizeFunc(RESTYPE type, SizeType sizeFunc)
+{
+    resourceTypes[type & TypeMask].sizeFunc = sizeFunc;
+}
+
 void
 SetResourceTypeErrorValue(RESTYPE type, int errorValue)
 {
diff --git a/include/resource.h b/include/resource.h
index 0c5a59d..406d74a 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -134,10 +134,27 @@ typedef struct {
     pointer value;
 } ResourceStateInfoRec;
 
+/* Structure for estimating resource memory usage. Memory usage
+ * consists of space allocated for the resource itself and of
+ * references to other resources. Currently the most important use for
+ * this structure is to estimate pixmap usage of different resources
+ * more accurately. */
+typedef struct {
+    /* Size of resource itself. Zero if not implemented. */
+    unsigned long resourceSize;
+    /* Size attributed to pixmap references from the resource. */
+    unsigned long pixmapRefSize;
+} ResourceSizeRec, *ResourceSizePtr;
+
 typedef int (*DeleteType)(
     pointer /*value*/,
     XID /*id*/);
 
+typedef void (*SizeType)(
+    pointer /*value*/,
+    XID /*id*/,
+    ResourceSizePtr /*size*/);
+
 typedef void (*FindResType)(
     pointer /*value*/,
     XID /*id*/,
@@ -157,6 +174,12 @@ typedef Bool (*FindComplexResType)(
 extern _X_EXPORT RESTYPE CreateNewResourceType(
     DeleteType /*deleteFunc*/, char * /*name*/);
 
+extern _X_EXPORT SizeType GetResourceTypeSizeFunc(
+    RESTYPE /*type*/);
+
+extern _X_EXPORT void SetResourceTypeSizeFunc(
+    RESTYPE /*type*/, SizeType /*sizeFunc*/);
+
 extern _X_EXPORT void SetResourceTypeErrorValue(
     RESTYPE /*type*/, int /*errorValue*/);
 
diff --git a/render/picture.c b/render/picture.c
index 0028cc7..018946c 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -606,6 +606,27 @@ PictureParseCmapPolicy (const char *name)
 	return PictureCmapPolicyInvalid;
 }
 
+/** @see GetDefaultBytes */
+static void
+GetPictureBytes(pointer value, XID id, ResourceSizePtr size)
+{
+    PicturePtr picture = value;
+
+    /* Currently only pixmap bytes are reported to clients. */
+    size->resourceSize = 0;
+
+    /* Calculate pixmap reference sizes. */
+    size->pixmapRefSize = 0;
+    if (picture->pDrawable && (picture->pDrawable->type == DRAWABLE_PIXMAP))
+    {
+        SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
+        ResourceSizeRec pixmapSize = { 0, 0 };
+        PixmapPtr pixmap = (PixmapPtr)picture->pDrawable;
+        pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
+        size->pixmapRefSize += pixmapSize.pixmapRefSize;
+    }
+}
+
 Bool
 PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
 {
@@ -618,6 +639,7 @@ PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
 	PictureType = CreateNewResourceType (FreePicture, "PICTURE");
 	if (!PictureType)
 	    return FALSE;
+	SetResourceTypeSizeFunc(PictureType, GetPictureBytes);
 	PictFormatType = CreateNewResourceType (FreePictFormat, "PICTFORMAT");
 	if (!PictFormatType)
 	    return FALSE;
-- 
1.7.0.4



More information about the xorg-devel mailing list