summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xext/xres.c27
-rw-r--r--dix/resource.c197
-rw-r--r--include/resource.h25
-rw-r--r--render/picture.c22
4 files changed, 271 insertions, 0 deletions
diff --git a/Xext/xres.c b/Xext/xres.c
index 4989d3e44..a0734098c 100644
--- a/Xext/xres.c
+++ b/Xext/xres.c
@@ -27,6 +27,7 @@
#include "list.h"
#include "misc.h"
#include <string.h>
+#include "picturestr.h"
/** @brief Holds fragments of responses for ConstructClientIds.
*
@@ -288,6 +289,17 @@ ResGetApproxPixmapBytes(PixmapPtr pix)
}
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)
{
unsigned long *bytes = (unsigned long *) cdata;
@@ -322,6 +334,14 @@ ResFindGCPixmaps(pointer value, XID id, pointer cdata)
*bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
}
+static void
+ResFindPicturePixmaps(pointer value, XID id, pointer cdata)
+{
+#ifdef RENDER
+ ResFindResourcePixmaps(value, id, PictureType, cdata);
+#endif
+}
+
static int
ProcXResQueryClientPixmapBytes(ClientPtr client)
{
@@ -356,6 +376,13 @@ ProcXResQueryClientPixmapBytes(ClientPtr client)
FindClientResourcesByType(clients[clientID], RT_GC,
ResFindGCPixmaps, (pointer) (&bytes));
+#ifdef RENDER
+ /* Render extension picture pixmaps. */
+ FindClientResourcesByType(clients[clientID], PictureType,
+ ResFindPicturePixmaps,
+ (pointer)(&bytes));
+#endif
+
#ifdef COMPOSITE
/* FIXME: include composite pixmaps too */
#endif
diff --git a/dix/resource.c b/dix/resource.c
index 89d077642..89dfb5bb6 100644
--- a/dix/resource.c
+++ b/dix/resource.c
@@ -141,6 +141,7 @@ Equipment Corporation.
#include "xace.h"
#include <assert.h>
#include "registry.h"
+#include "gcstruct.h"
#ifdef XSERVER_DTRACE
#include <sys/types.h>
@@ -182,50 +183,212 @@ 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,
},
};
@@ -256,6 +419,7 @@ CreateNewResourceType(DeleteType deleteFunc, const 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 */
@@ -264,6 +428,39 @@ CreateNewResourceType(DeleteType deleteFunc, const 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 068057013..8e58952aa 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -152,12 +152,37 @@ typedef Bool (*FindComplexResType) (pointer /*value */ ,
XID /*id */ ,
pointer /*cdata */ );
+/* 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 void (*SizeType)(pointer /*value*/,
+ XID /*id*/,
+ ResourceSizePtr /*size*/);
+
extern _X_EXPORT RESTYPE CreateNewResourceType(DeleteType /*deleteFunc */ ,
const char * /*name */ );
extern _X_EXPORT void SetResourceTypeErrorValue(RESTYPE /*type */ ,
int /*errorValue */ );
+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*/);
+
extern _X_EXPORT RESTYPE CreateNewResourceClass(void);
extern _X_EXPORT Bool InitClientResources(ClientPtr /*client */ );
diff --git a/render/picture.c b/render/picture.c
index 2fd13fc37..24b6ba0b6 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -591,6 +591,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)
{
@@ -602,6 +623,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;