dix: add a mechanism for iterating through all subresources
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@vincit.fi> Signed-off-by: Erkki Seppälä <erkki.seppala@vincit.fi>
This commit is contained in:
parent
b8d0d19a6d
commit
3ba0decb4b
122
dix/resource.c
122
dix/resource.c
|
@ -184,6 +184,7 @@ RESTYPE TypeMask;
|
||||||
struct ResourceType {
|
struct ResourceType {
|
||||||
DeleteType deleteFunc;
|
DeleteType deleteFunc;
|
||||||
SizeType sizeFunc;
|
SizeType sizeFunc;
|
||||||
|
FindTypeSubResources findSubResFunc;
|
||||||
int errorValue;
|
int errorValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -208,6 +209,25 @@ GetDefaultBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
size->pixmapRefSize = 0;
|
size->pixmapRefSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Calculate drawable size in bytes. Reference counting is not taken
|
||||||
* into account.
|
* into account.
|
||||||
|
@ -300,6 +320,38 @@ 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
|
* Calculate graphics context size in bytes. The purpose of this
|
||||||
* function is to estimate memory usage that can be attributed to all
|
* function is to estimate memory usage that can be attributed to all
|
||||||
|
@ -338,57 +390,99 @@ 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 struct ResourceType *resourceTypes;
|
||||||
|
|
||||||
static const struct ResourceType predefTypes[] = {
|
static const struct ResourceType predefTypes[] = {
|
||||||
[RT_NONE & (RC_LASTPREDEF - 1)] = {
|
[RT_NONE & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = (DeleteType) NoopDDA,
|
.deleteFunc = (DeleteType) NoopDDA,
|
||||||
.sizeFunc = GetDefaultBytes,
|
.sizeFunc = GetDefaultBytes,
|
||||||
|
.findSubResFunc = DefaultFindSubRes,
|
||||||
.errorValue = BadValue,
|
.errorValue = BadValue,
|
||||||
},
|
},
|
||||||
[RT_WINDOW & (RC_LASTPREDEF - 1)] = {
|
[RT_WINDOW & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = DeleteWindow,
|
.deleteFunc = DeleteWindow,
|
||||||
.sizeFunc = GetWindowBytes,
|
.sizeFunc = GetWindowBytes,
|
||||||
|
.findSubResFunc = FindWindowSubRes,
|
||||||
.errorValue = BadWindow,
|
.errorValue = BadWindow,
|
||||||
},
|
},
|
||||||
[RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
|
[RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = dixDestroyPixmap,
|
.deleteFunc = dixDestroyPixmap,
|
||||||
.sizeFunc = GetPixmapBytes,
|
.sizeFunc = GetPixmapBytes,
|
||||||
|
.findSubResFunc = DefaultFindSubRes,
|
||||||
.errorValue = BadPixmap,
|
.errorValue = BadPixmap,
|
||||||
},
|
},
|
||||||
[RT_GC & (RC_LASTPREDEF - 1)] = {
|
[RT_GC & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = FreeGC,
|
.deleteFunc = FreeGC,
|
||||||
.sizeFunc = GetGcBytes,
|
.sizeFunc = GetGcBytes,
|
||||||
|
.findSubResFunc = FindGCSubRes,
|
||||||
.errorValue = BadGC,
|
.errorValue = BadGC,
|
||||||
},
|
},
|
||||||
[RT_FONT & (RC_LASTPREDEF - 1)] = {
|
[RT_FONT & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = CloseFont,
|
.deleteFunc = CloseFont,
|
||||||
.sizeFunc = GetDefaultBytes,
|
.sizeFunc = GetDefaultBytes,
|
||||||
|
.findSubResFunc = DefaultFindSubRes,
|
||||||
.errorValue = BadFont,
|
.errorValue = BadFont,
|
||||||
},
|
},
|
||||||
[RT_CURSOR & (RC_LASTPREDEF - 1)] = {
|
[RT_CURSOR & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = FreeCursor,
|
.deleteFunc = FreeCursor,
|
||||||
.sizeFunc = GetDefaultBytes,
|
.sizeFunc = GetDefaultBytes,
|
||||||
|
.findSubResFunc = DefaultFindSubRes,
|
||||||
.errorValue = BadCursor,
|
.errorValue = BadCursor,
|
||||||
},
|
},
|
||||||
[RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
|
[RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = FreeColormap,
|
.deleteFunc = FreeColormap,
|
||||||
.sizeFunc = GetDefaultBytes,
|
.sizeFunc = GetDefaultBytes,
|
||||||
|
.findSubResFunc = DefaultFindSubRes,
|
||||||
.errorValue = BadColor,
|
.errorValue = BadColor,
|
||||||
},
|
},
|
||||||
[RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
|
[RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = FreeClientPixels,
|
.deleteFunc = FreeClientPixels,
|
||||||
.sizeFunc = GetDefaultBytes,
|
.sizeFunc = GetDefaultBytes,
|
||||||
|
.findSubResFunc = DefaultFindSubRes,
|
||||||
.errorValue = BadColor,
|
.errorValue = BadColor,
|
||||||
},
|
},
|
||||||
[RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
|
[RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = OtherClientGone,
|
.deleteFunc = OtherClientGone,
|
||||||
.sizeFunc = GetDefaultBytes,
|
.sizeFunc = GetDefaultBytes,
|
||||||
|
.findSubResFunc = DefaultFindSubRes,
|
||||||
.errorValue = BadValue,
|
.errorValue = BadValue,
|
||||||
},
|
},
|
||||||
[RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
|
[RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
|
||||||
.deleteFunc = DeletePassiveGrab,
|
.deleteFunc = DeletePassiveGrab,
|
||||||
.sizeFunc = GetDefaultBytes,
|
.sizeFunc = GetDefaultBytes,
|
||||||
|
.findSubResFunc = DefaultFindSubRes,
|
||||||
.errorValue = BadValue,
|
.errorValue = BadValue,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -420,6 +514,7 @@ CreateNewResourceType(DeleteType deleteFunc, const char *name)
|
||||||
resourceTypes = types;
|
resourceTypes = types;
|
||||||
resourceTypes[next].deleteFunc = deleteFunc;
|
resourceTypes[next].deleteFunc = deleteFunc;
|
||||||
resourceTypes[next].sizeFunc = GetDefaultBytes;
|
resourceTypes[next].sizeFunc = GetDefaultBytes;
|
||||||
|
resourceTypes[next].findSubResFunc = DefaultFindSubRes;
|
||||||
resourceTypes[next].errorValue = BadValue;
|
resourceTypes[next].errorValue = BadValue;
|
||||||
|
|
||||||
/* Called even if name is NULL, to remove any previous entry */
|
/* Called even if name is NULL, to remove any previous entry */
|
||||||
|
@ -461,6 +556,24 @@ SetResourceTypeSizeFunc(RESTYPE type, SizeType sizeFunc)
|
||||||
resourceTypes[type & TypeMask].sizeFunc = 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
|
void
|
||||||
SetResourceTypeErrorValue(RESTYPE type, int errorValue)
|
SetResourceTypeErrorValue(RESTYPE type, int errorValue)
|
||||||
{
|
{
|
||||||
|
@ -871,6 +984,15 @@ FindClientResourcesByType(ClientPtr client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FindSubResources(pointer resource,
|
||||||
|
RESTYPE type,
|
||||||
|
FindAllRes func,
|
||||||
|
pointer cdata)
|
||||||
|
{
|
||||||
|
struct ResourceType rtype = resourceTypes[type & TypeMask];
|
||||||
|
rtype.findSubResFunc(resource, func, cdata);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FindAllClientResources(ClientPtr client, FindAllRes func, pointer cdata)
|
FindAllClientResources(ClientPtr client, FindAllRes func, pointer cdata)
|
||||||
{
|
{
|
||||||
|
|
|
@ -171,12 +171,19 @@ typedef void (*SizeType)(pointer /*value*/,
|
||||||
extern _X_EXPORT RESTYPE CreateNewResourceType(DeleteType /*deleteFunc */ ,
|
extern _X_EXPORT RESTYPE CreateNewResourceType(DeleteType /*deleteFunc */ ,
|
||||||
const char * /*name */ );
|
const char * /*name */ );
|
||||||
|
|
||||||
|
typedef void (*FindTypeSubResources)(pointer /* value */,
|
||||||
|
FindAllRes /* func */,
|
||||||
|
pointer /* cdata */);
|
||||||
|
|
||||||
extern _X_EXPORT void SetResourceTypeErrorValue(RESTYPE /*type */ ,
|
extern _X_EXPORT void SetResourceTypeErrorValue(RESTYPE /*type */ ,
|
||||||
int /*errorValue */ );
|
int /*errorValue */ );
|
||||||
|
|
||||||
extern _X_EXPORT SizeType GetResourceTypeSizeFunc(
|
extern _X_EXPORT SizeType GetResourceTypeSizeFunc(
|
||||||
RESTYPE /*type*/);
|
RESTYPE /*type*/);
|
||||||
|
|
||||||
|
extern _X_EXPORT void SetResourceTypeFindSubResFunc(
|
||||||
|
RESTYPE /*type*/, FindTypeSubResources /*findFunc*/);
|
||||||
|
|
||||||
extern _X_EXPORT void SetResourceTypeSizeFunc(
|
extern _X_EXPORT void SetResourceTypeSizeFunc(
|
||||||
RESTYPE /*type*/, SizeType /*sizeFunc*/);
|
RESTYPE /*type*/, SizeType /*sizeFunc*/);
|
||||||
|
|
||||||
|
@ -218,6 +225,15 @@ extern _X_EXPORT void FindAllClientResources(ClientPtr /*client */ ,
|
||||||
FindAllRes /*func */ ,
|
FindAllRes /*func */ ,
|
||||||
pointer /*cdata */ );
|
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 FreeClientNeverRetainResources(ClientPtr /*client */ );
|
extern _X_EXPORT void FreeClientNeverRetainResources(ClientPtr /*client */ );
|
||||||
|
|
||||||
extern _X_EXPORT void FreeClientResources(ClientPtr /*client */ );
|
extern _X_EXPORT void FreeClientResources(ClientPtr /*client */ );
|
||||||
|
|
Loading…
Reference in New Issue