diff options
author | Rami Ylimäki <rami.ylimaki@vincit.fi> | 2010-10-27 16:59:06 +0300 |
---|---|---|
committer | Erkki Seppälä <erkki.seppala@vincit.fi> | 2012-04-18 12:31:24 +0300 |
commit | e83388cc70e21e7f377ed2e417d04469e23eb706 (patch) | |
tree | dfbd34d2f494110e91ae6700a37417e336691577 | |
parent | 96864bfa951ea8bf4ab697753fc62c6a97598bc0 (diff) |
render: Report pixmap usage of pictures to resource extension.
Signed-off-by: Erkki Seppälä <erkki.seppala@vincit.fi>
Signed-off-by: Rami Ylimäki <rami.ylimaki@vincit.fi>
Reviewed-by: Mikhail Gusarov <dottedmag@dottedmag.net>
Reviewed-by: Tiago Vignatti <tiago.vignatti@nokia.com>
-rw-r--r-- | Xext/xres.c | 27 | ||||
-rw-r--r-- | dix/resource.c | 197 | ||||
-rw-r--r-- | include/resource.h | 25 | ||||
-rw-r--r-- | render/picture.c | 22 |
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; |