dix: add reference count of the resource to ResourceSizeRec
The ResourceSizeRec now contains the number of references to the resource. For example a Pixmap knows this value and it can be useful for determining the "weight" of the resource. Typically this value is 1. 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
ccb3e78124
commit
233eab4d05
481
Xext/xres.c
481
Xext/xres.c
|
@ -27,6 +27,7 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "hashtable.h"
|
||||||
#include "picturestr.h"
|
#include "picturestr.h"
|
||||||
#include "compint.h"
|
#include "compint.h"
|
||||||
|
|
||||||
|
@ -39,6 +40,8 @@ typedef struct {
|
||||||
/* data follows */
|
/* data follows */
|
||||||
} FragmentList;
|
} FragmentList;
|
||||||
|
|
||||||
|
#define FRAGMENT_DATA(ptr) ((void*) ((char*) (ptr) + sizeof(FragmentList)))
|
||||||
|
|
||||||
/** @brief Holds structure for the generated response to
|
/** @brief Holds structure for the generated response to
|
||||||
ProcXResQueryClientIds; used by ConstructClientId* -functions */
|
ProcXResQueryClientIds; used by ConstructClientId* -functions */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -48,6 +51,41 @@ typedef struct {
|
||||||
int sentClientMasks[MAXCLIENTS];
|
int sentClientMasks[MAXCLIENTS];
|
||||||
} ConstructClientIdCtx;
|
} ConstructClientIdCtx;
|
||||||
|
|
||||||
|
/** @brief Holds the structure for information required to
|
||||||
|
generate the response to XResQueryResourceBytes. In addition
|
||||||
|
to response it contains information on the query as well,
|
||||||
|
as well as some volatile information required by a few
|
||||||
|
functions that cannot take that information directly
|
||||||
|
via a parameter, as they are called via already-existing
|
||||||
|
higher order functions. */
|
||||||
|
typedef struct {
|
||||||
|
ClientPtr sendClient;
|
||||||
|
int numSizes;
|
||||||
|
int resultBytes;
|
||||||
|
struct xorg_list response;
|
||||||
|
int status;
|
||||||
|
long numSpecs;
|
||||||
|
xXResResourceIdSpec *specs;
|
||||||
|
HashTable visitedResources;
|
||||||
|
|
||||||
|
/* Used by AddSubResourceSizeSpec when AddResourceSizeValue is
|
||||||
|
handling crossreferences */
|
||||||
|
HashTable visitedSubResources;
|
||||||
|
|
||||||
|
/* used when ConstructResourceBytesCtx is passed to
|
||||||
|
AddResourceSizeValue2 via FindClientResourcesByType */
|
||||||
|
RESTYPE resType;
|
||||||
|
|
||||||
|
/* used when ConstructResourceBytesCtx is passed to
|
||||||
|
AddResourceSizeValueByResource from ConstructResourceBytesByResource */
|
||||||
|
xXResResourceIdSpec *curSpec;
|
||||||
|
|
||||||
|
/** Used when iterating through a single resource's subresources
|
||||||
|
|
||||||
|
@see AddSubResourceSizeSpec */
|
||||||
|
xXResResourceSizeValue *sizeValue;
|
||||||
|
} ConstructResourceBytesCtx;
|
||||||
|
|
||||||
/** @brief Allocate and add a sequence of bytes at the end of a fragment list.
|
/** @brief Allocate and add a sequence of bytes at the end of a fragment list.
|
||||||
Call DestroyFragments to release the list.
|
Call DestroyFragments to release the list.
|
||||||
|
|
||||||
|
@ -118,6 +156,37 @@ DestroyConstructClientIdCtx(ConstructClientIdCtx *ctx)
|
||||||
DestroyFragments(&ctx->response);
|
DestroyFragments(&ctx->response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
InitConstructResourceBytesCtx(ConstructResourceBytesCtx *ctx,
|
||||||
|
ClientPtr sendClient,
|
||||||
|
long numSpecs,
|
||||||
|
xXResResourceIdSpec *specs)
|
||||||
|
{
|
||||||
|
ctx->sendClient = sendClient;
|
||||||
|
ctx->numSizes = 0;
|
||||||
|
ctx->resultBytes = 0;
|
||||||
|
xorg_list_init(&ctx->response);
|
||||||
|
ctx->status = Success;
|
||||||
|
ctx->numSpecs = numSpecs;
|
||||||
|
ctx->specs = specs;
|
||||||
|
ctx->visitedResources = ht_create(sizeof(XID), 0,
|
||||||
|
ht_resourceid_hash, ht_resourceid_compare,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!ctx->visitedResources) {
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DestroyConstructResourceBytesCtx(ConstructResourceBytesCtx *ctx)
|
||||||
|
{
|
||||||
|
DestroyFragments(&ctx->response);
|
||||||
|
ht_destroy(ctx->visitedResources);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ProcXResQueryVersion(ClientPtr client)
|
ProcXResQueryVersion(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -293,7 +362,7 @@ static void
|
||||||
ResFindResourcePixmaps(pointer value, XID id, RESTYPE type, pointer cdata)
|
ResFindResourcePixmaps(pointer value, XID id, RESTYPE type, pointer cdata)
|
||||||
{
|
{
|
||||||
SizeType sizeFunc = GetResourceTypeSizeFunc(type);
|
SizeType sizeFunc = GetResourceTypeSizeFunc(type);
|
||||||
ResourceSizeRec size = { 0, 0 };
|
ResourceSizeRec size = { 0, 0, 0 };
|
||||||
unsigned long *bytes = cdata;
|
unsigned long *bytes = cdata;
|
||||||
|
|
||||||
sizeFunc(value, id, &size);
|
sizeFunc(value, id, &size);
|
||||||
|
@ -616,6 +685,388 @@ ProcXResQueryClientIds (ClientPtr client)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Swaps xXResResourceIdSpec endianess */
|
||||||
|
static void
|
||||||
|
SwapXResResourceIdSpec(xXResResourceIdSpec *spec)
|
||||||
|
{
|
||||||
|
swapl(&spec->resource);
|
||||||
|
swapl(&spec->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Swaps xXResResourceSizeSpec endianess */
|
||||||
|
static void
|
||||||
|
SwapXResResourceSizeSpec(xXResResourceSizeSpec *size)
|
||||||
|
{
|
||||||
|
SwapXResResourceIdSpec(&size->spec);
|
||||||
|
swapl(&size->bytes);
|
||||||
|
swapl(&size->refCount);
|
||||||
|
swapl(&size->useCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Swaps xXResResourceSizeValue endianess */
|
||||||
|
static void
|
||||||
|
SwapXResResourceSizeValue(xXResResourceSizeValue *rep)
|
||||||
|
{
|
||||||
|
SwapXResResourceSizeSpec(&rep->size);
|
||||||
|
swapl(&rep->numCrossReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Swaps the response bytes */
|
||||||
|
static void
|
||||||
|
SwapXResQueryResourceBytes(struct xorg_list *response)
|
||||||
|
{
|
||||||
|
struct xorg_list *it = response->next;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while (it != response) {
|
||||||
|
xXResResourceSizeValue *value = FRAGMENT_DATA(it);
|
||||||
|
it = it->next;
|
||||||
|
for (c = 0; c < value->numCrossReferences; ++c) {
|
||||||
|
xXResResourceSizeSpec *spec = FRAGMENT_DATA(it);
|
||||||
|
SwapXResResourceSizeSpec(spec);
|
||||||
|
it = it->next;
|
||||||
|
}
|
||||||
|
SwapXResResourceSizeValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Adds xXResResourceSizeSpec describing a resource's size into
|
||||||
|
the buffer contained in the context. The resource is considered
|
||||||
|
to be a subresource.
|
||||||
|
|
||||||
|
@see AddResourceSizeValue
|
||||||
|
|
||||||
|
@param[in] value The X resource object on which to add information
|
||||||
|
about to the buffer
|
||||||
|
@param[in] id The ID of the X resource
|
||||||
|
@param[in] type The type of the X resource
|
||||||
|
@param[in/out] cdata The context object of type ConstructResourceBytesCtx.
|
||||||
|
Void pointer type is used here to satisfy the type
|
||||||
|
FindRes
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
AddSubResourceSizeSpec(pointer value,
|
||||||
|
XID id,
|
||||||
|
RESTYPE type,
|
||||||
|
pointer cdata)
|
||||||
|
{
|
||||||
|
ConstructResourceBytesCtx *ctx = cdata;
|
||||||
|
|
||||||
|
if (ctx->status == Success) {
|
||||||
|
xXResResourceSizeSpec **prevCrossRef =
|
||||||
|
ht_find(ctx->visitedSubResources, &value);
|
||||||
|
if (!prevCrossRef) {
|
||||||
|
Bool ok = TRUE;
|
||||||
|
xXResResourceSizeSpec *crossRef =
|
||||||
|
AddFragment(&ctx->response, sizeof(xXResResourceSizeSpec));
|
||||||
|
ok = ok && crossRef != NULL;
|
||||||
|
if (ok) {
|
||||||
|
xXResResourceSizeSpec **p;
|
||||||
|
p = ht_add(ctx->visitedSubResources, &value);
|
||||||
|
if (!p) {
|
||||||
|
ok = FALSE;
|
||||||
|
} else {
|
||||||
|
*p = crossRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
ctx->status = BadAlloc;
|
||||||
|
} else {
|
||||||
|
SizeType sizeFunc = GetResourceTypeSizeFunc(type);
|
||||||
|
ResourceSizeRec size = { 0, 0, 0 };
|
||||||
|
sizeFunc(value, id, &size);
|
||||||
|
|
||||||
|
crossRef->spec.resource = id;
|
||||||
|
crossRef->spec.type = type;
|
||||||
|
crossRef->bytes = size.resourceSize;
|
||||||
|
crossRef->refCount = size.refCnt;
|
||||||
|
crossRef->useCount = 1;
|
||||||
|
|
||||||
|
++ctx->sizeValue->numCrossReferences;
|
||||||
|
|
||||||
|
ctx->resultBytes += sizeof(*crossRef);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* if we have visited the subresource earlier (from current parent
|
||||||
|
resource), just increase its use count by one */
|
||||||
|
++(*prevCrossRef)->useCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Adds xXResResourceSizeValue describing a resource's size into
|
||||||
|
the buffer contained in the context. In addition, the
|
||||||
|
subresources are iterated and added as xXResResourceSizeSpec's
|
||||||
|
by using AddSubResourceSizeSpec
|
||||||
|
|
||||||
|
@see AddSubResourceSizeSpec
|
||||||
|
|
||||||
|
@param[in] value The X resource object on which to add information
|
||||||
|
about to the buffer
|
||||||
|
@param[in] id The ID of the X resource
|
||||||
|
@param[in] type The type of the X resource
|
||||||
|
@param[in/out] cdata The context object of type ConstructResourceBytesCtx.
|
||||||
|
Void pointer type is used here to satisfy the type
|
||||||
|
FindRes
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
AddResourceSizeValue(pointer ptr, XID id, RESTYPE type, pointer cdata)
|
||||||
|
{
|
||||||
|
ConstructResourceBytesCtx *ctx = cdata;
|
||||||
|
if (ctx->status == Success &&
|
||||||
|
!ht_find(ctx->visitedResources, &id)) {
|
||||||
|
Bool ok = TRUE;
|
||||||
|
HashTable ht;
|
||||||
|
HtGenericHashSetupRec htSetup = {
|
||||||
|
.keySize = sizeof(void*)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* it doesn't matter that we don't undo the work done here
|
||||||
|
* immediately. All but ht_init will be undone at the end
|
||||||
|
* of the request and there can happen no failure after
|
||||||
|
* ht_init, so we don't need to clean it up here in any
|
||||||
|
* special way */
|
||||||
|
|
||||||
|
xXResResourceSizeValue *value =
|
||||||
|
AddFragment(&ctx->response, sizeof(xXResResourceSizeValue));
|
||||||
|
if (!value) {
|
||||||
|
ok = FALSE;
|
||||||
|
}
|
||||||
|
ok = ok && ht_add(ctx->visitedResources, &id);
|
||||||
|
if (ok) {
|
||||||
|
ht = ht_create(htSetup.keySize,
|
||||||
|
sizeof(xXResResourceSizeSpec*),
|
||||||
|
ht_generic_hash, ht_generic_compare,
|
||||||
|
&htSetup);
|
||||||
|
ok = ok && ht;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
ctx->status = BadAlloc;
|
||||||
|
} else {
|
||||||
|
SizeType sizeFunc = GetResourceTypeSizeFunc(type);
|
||||||
|
ResourceSizeRec size = { 0, 0, 0 };
|
||||||
|
|
||||||
|
sizeFunc(ptr, id, &size);
|
||||||
|
|
||||||
|
value->size.spec.resource = id;
|
||||||
|
value->size.spec.type = type;
|
||||||
|
value->size.bytes = size.resourceSize;
|
||||||
|
value->size.refCount = size.refCnt;
|
||||||
|
value->size.useCount = 1;
|
||||||
|
value->numCrossReferences = 0;
|
||||||
|
|
||||||
|
ctx->sizeValue = value;
|
||||||
|
ctx->visitedSubResources = ht;
|
||||||
|
FindSubResources(ptr, type, AddSubResourceSizeSpec, ctx);
|
||||||
|
ctx->visitedSubResources = NULL;
|
||||||
|
ctx->sizeValue = NULL;
|
||||||
|
|
||||||
|
ctx->resultBytes += sizeof(*value);
|
||||||
|
++ctx->numSizes;
|
||||||
|
|
||||||
|
ht_destroy(ht);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief A variant of AddResourceSizeValue that passes the resource type
|
||||||
|
through the context object to satisfy the type FindResType
|
||||||
|
|
||||||
|
@see AddResourceSizeValue
|
||||||
|
|
||||||
|
@param[in] ptr The resource
|
||||||
|
@param[in] id The resource ID
|
||||||
|
@param[in/out] cdata The context object that contains the resource type
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
AddResourceSizeValueWithResType(pointer ptr, XID id, pointer cdata)
|
||||||
|
{
|
||||||
|
ConstructResourceBytesCtx *ctx = cdata;
|
||||||
|
AddResourceSizeValue(ptr, id, ctx->resType, cdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Adds the information of a resource into the buffer if it matches
|
||||||
|
the match condition.
|
||||||
|
|
||||||
|
@see AddResourceSizeValue
|
||||||
|
|
||||||
|
@param[in] ptr The resource
|
||||||
|
@param[in] id The resource ID
|
||||||
|
@param[in] type The resource type
|
||||||
|
@param[in/out] cdata The context object as a void pointer to satisfy the
|
||||||
|
type FindAllRes
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
AddResourceSizeValueByResource(pointer ptr, XID id, RESTYPE type, pointer cdata)
|
||||||
|
{
|
||||||
|
ConstructResourceBytesCtx *ctx = cdata;
|
||||||
|
xXResResourceIdSpec *spec = ctx->curSpec;
|
||||||
|
|
||||||
|
if ((!spec->type || spec->type == type) &&
|
||||||
|
(!spec->resource || spec->resource == id)) {
|
||||||
|
AddResourceSizeValue(ptr, id, type, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Add all resources of the client into the result buffer
|
||||||
|
disregarding all those specifications that specify the
|
||||||
|
resource by its ID. Those are handled by
|
||||||
|
ConstructResourceBytesByResource
|
||||||
|
|
||||||
|
@see ConstructResourceBytesByResource
|
||||||
|
|
||||||
|
@param[in] aboutClient Which client is being considered
|
||||||
|
@param[in/out] ctx The context that contains the resource id
|
||||||
|
specifications as well as the result buffer
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ConstructClientResourceBytes(ClientPtr aboutClient,
|
||||||
|
ConstructResourceBytesCtx *ctx)
|
||||||
|
{
|
||||||
|
int specIdx;
|
||||||
|
for (specIdx = 0; specIdx < ctx->numSpecs; ++specIdx) {
|
||||||
|
xXResResourceIdSpec* spec = ctx->specs + specIdx;
|
||||||
|
if (spec->resource) {
|
||||||
|
/* these specs are handled elsewhere */
|
||||||
|
} else if (spec->type) {
|
||||||
|
ctx->resType = spec->type;
|
||||||
|
FindClientResourcesByType(aboutClient, spec->type,
|
||||||
|
AddResourceSizeValueWithResType, ctx);
|
||||||
|
} else {
|
||||||
|
FindAllClientResources(aboutClient, AddResourceSizeValue, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Add the sizes of all such resources that can are specified by
|
||||||
|
their ID in the resource id specification. The scan can
|
||||||
|
by limited to a client with the aboutClient parameter
|
||||||
|
|
||||||
|
@see ConstructResourceBytesByResource
|
||||||
|
|
||||||
|
@param[in] aboutClient Which client is being considered. This may be None
|
||||||
|
to mean all clients.
|
||||||
|
@param[in/out] ctx The context that contains the resource id
|
||||||
|
specifications as well as the result buffer. In
|
||||||
|
addition this function uses the curSpec field to
|
||||||
|
keep a pointer to the current resource id
|
||||||
|
specification in it, which can be used by
|
||||||
|
AddResourceSizeValueByResource .
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ConstructResourceBytesByResource(XID aboutClient, ConstructResourceBytesCtx *ctx)
|
||||||
|
{
|
||||||
|
int specIdx;
|
||||||
|
for (specIdx = 0; specIdx < ctx->numSpecs; ++specIdx) {
|
||||||
|
xXResResourceIdSpec *spec = ctx->specs + specIdx;
|
||||||
|
if (spec->resource) {
|
||||||
|
int cid = CLIENT_ID(spec->resource);
|
||||||
|
if (cid < currentMaxClients &&
|
||||||
|
(aboutClient == None || cid == aboutClient)) {
|
||||||
|
ClientPtr client = clients[cid];
|
||||||
|
if (client) {
|
||||||
|
ctx->curSpec = spec;
|
||||||
|
FindAllClientResources(client,
|
||||||
|
AddResourceSizeValueByResource,
|
||||||
|
ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Build the resource size response for the given client
|
||||||
|
(or all if not specified) per the parameters set up
|
||||||
|
in the context object.
|
||||||
|
|
||||||
|
@param[in] aboutClient Which client to consider or None for all clients
|
||||||
|
@param[in/out] ctx The context object that contains the request as well
|
||||||
|
as the response buffer.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ConstructResourceBytes(XID aboutClient,
|
||||||
|
ConstructResourceBytesCtx *ctx)
|
||||||
|
{
|
||||||
|
if (aboutClient) {
|
||||||
|
int clientIdx = CLIENT_ID(aboutClient);
|
||||||
|
ClientPtr client = NullClient;
|
||||||
|
|
||||||
|
if ((clientIdx >= currentMaxClients) || !clients[clientIdx]) {
|
||||||
|
ctx->sendClient->errorValue = aboutClient;
|
||||||
|
return BadValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = clients[clientIdx];
|
||||||
|
|
||||||
|
ConstructClientResourceBytes(client, ctx);
|
||||||
|
ConstructResourceBytesByResource(aboutClient, ctx);
|
||||||
|
} else {
|
||||||
|
int clientIdx;
|
||||||
|
|
||||||
|
ConstructClientResourceBytes(NULL, ctx);
|
||||||
|
|
||||||
|
for (clientIdx = 0; clientIdx < currentMaxClients; ++clientIdx) {
|
||||||
|
ClientPtr client = clients[clientIdx];
|
||||||
|
|
||||||
|
if (client) {
|
||||||
|
ConstructClientResourceBytes(client, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstructResourceBytesByResource(None, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ctx->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Implements the XResQueryResourceBytes of XResProto v1.2 */
|
||||||
|
static int
|
||||||
|
ProcXResQueryResourceBytes (ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xXResQueryResourceBytesReq);
|
||||||
|
|
||||||
|
xXResQueryResourceBytesReply rep;
|
||||||
|
int rc;
|
||||||
|
ConstructResourceBytesCtx ctx;
|
||||||
|
|
||||||
|
REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq);
|
||||||
|
REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq,
|
||||||
|
stuff->numSpecs * sizeof(ctx.specs[0]));
|
||||||
|
|
||||||
|
if (!InitConstructResourceBytesCtx(&ctx, client,
|
||||||
|
stuff->numSpecs,
|
||||||
|
(void*) ((char*) stuff +
|
||||||
|
sz_xXResQueryResourceBytesReq))) {
|
||||||
|
return BadAlloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ConstructResourceBytes(stuff->client, &ctx);
|
||||||
|
|
||||||
|
if (rc == Success) {
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
rep.numSizes = ctx.numSizes;
|
||||||
|
rep.length = bytes_to_int32(ctx.resultBytes);
|
||||||
|
|
||||||
|
if (client->swapped) {
|
||||||
|
swaps (&rep.sequenceNumber);
|
||||||
|
swapl (&rep.length);
|
||||||
|
swapl (&rep.numSizes);
|
||||||
|
|
||||||
|
SwapXResQueryResourceBytes(&ctx.response);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteToClient(client,sizeof(rep),(char*)&rep);
|
||||||
|
WriteFragmentsToClient(client, &ctx.response);
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyConstructResourceBytesCtx(&ctx);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ProcResDispatch(ClientPtr client)
|
ProcResDispatch(ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -632,8 +1083,7 @@ ProcResDispatch(ClientPtr client)
|
||||||
case X_XResQueryClientIds:
|
case X_XResQueryClientIds:
|
||||||
return ProcXResQueryClientIds(client);
|
return ProcXResQueryClientIds(client);
|
||||||
case X_XResQueryResourceBytes:
|
case X_XResQueryResourceBytes:
|
||||||
/* not implemented yet */
|
return ProcXResQueryResourceBytes(client);
|
||||||
return BadRequest;
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,6 +1126,28 @@ SProcXResQueryClientIds (ClientPtr client)
|
||||||
return ProcXResQueryClientIds(client);
|
return ProcXResQueryClientIds(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Implements the XResQueryResourceBytes of XResProto v1.2.
|
||||||
|
This variant byteswaps request contents before issuing the
|
||||||
|
rest of the work to ProcXResQueryResourceBytes */
|
||||||
|
static int
|
||||||
|
SProcXResQueryResourceBytes (ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xXResQueryResourceBytesReq);
|
||||||
|
int c;
|
||||||
|
xXResResourceIdSpec *specs = (void*) ((char*) stuff + sizeof(*stuff));
|
||||||
|
|
||||||
|
swapl(&stuff->numSpecs);
|
||||||
|
REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq);
|
||||||
|
REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq,
|
||||||
|
stuff->numSpecs * sizeof(specs[0]));
|
||||||
|
|
||||||
|
for (c = 0; c < stuff->numSpecs; ++c) {
|
||||||
|
SwapXResResourceIdSpec(specs + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcXResQueryResourceBytes(client);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SProcResDispatch (ClientPtr client)
|
SProcResDispatch (ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -694,8 +1166,7 @@ SProcResDispatch (ClientPtr client)
|
||||||
case X_XResQueryClientIds:
|
case X_XResQueryClientIds:
|
||||||
return SProcXResQueryClientIds(client);
|
return SProcXResQueryClientIds(client);
|
||||||
case X_XResQueryResourceBytes:
|
case X_XResQueryResourceBytes:
|
||||||
/* not implemented yet */
|
return SProcXResQueryResourceBytes(client);
|
||||||
return BadRequest;
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,6 +207,7 @@ GetDefaultBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
{
|
{
|
||||||
size->resourceSize = 0;
|
size->resourceSize = 0;
|
||||||
size->pixmapRefSize = 0;
|
size->pixmapRefSize = 0;
|
||||||
|
size->refCnt = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -273,6 +274,7 @@ GetPixmapBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
|
|
||||||
size->resourceSize = 0;
|
size->resourceSize = 0;
|
||||||
size->pixmapRefSize = 0;
|
size->pixmapRefSize = 0;
|
||||||
|
size->refCnt = pixmap->refcnt;
|
||||||
|
|
||||||
if (pixmap && pixmap->refcnt)
|
if (pixmap && pixmap->refcnt)
|
||||||
{
|
{
|
||||||
|
@ -298,7 +300,7 @@ static void
|
||||||
GetWindowBytes(pointer value, XID id, ResourceSizePtr size)
|
GetWindowBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
{
|
{
|
||||||
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
||||||
ResourceSizeRec pixmapSize = { 0, 0 };
|
ResourceSizeRec pixmapSize = { 0, 0, 0 };
|
||||||
WindowPtr window = value;
|
WindowPtr window = value;
|
||||||
|
|
||||||
/* Currently only pixmap bytes are reported to clients. */
|
/* Currently only pixmap bytes are reported to clients. */
|
||||||
|
@ -306,6 +308,9 @@ GetWindowBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
|
|
||||||
/* Calculate pixmap reference sizes. */
|
/* Calculate pixmap reference sizes. */
|
||||||
size->pixmapRefSize = 0;
|
size->pixmapRefSize = 0;
|
||||||
|
|
||||||
|
size->refCnt = 1;
|
||||||
|
|
||||||
if (window->backgroundState == BackgroundPixmap)
|
if (window->backgroundState == BackgroundPixmap)
|
||||||
{
|
{
|
||||||
PixmapPtr pixmap = window->background.pixmap;
|
PixmapPtr pixmap = window->background.pixmap;
|
||||||
|
@ -368,7 +373,7 @@ static void
|
||||||
GetGcBytes(pointer value, XID id, ResourceSizePtr size)
|
GetGcBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
{
|
{
|
||||||
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
||||||
ResourceSizeRec pixmapSize = { 0, 0 };
|
ResourceSizeRec pixmapSize = { 0, 0, 0 };
|
||||||
GCPtr gc = value;
|
GCPtr gc = value;
|
||||||
|
|
||||||
/* Currently only pixmap bytes are reported to clients. */
|
/* Currently only pixmap bytes are reported to clients. */
|
||||||
|
@ -376,6 +381,8 @@ GetGcBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
|
|
||||||
/* Calculate pixmap reference sizes. */
|
/* Calculate pixmap reference sizes. */
|
||||||
size->pixmapRefSize = 0;
|
size->pixmapRefSize = 0;
|
||||||
|
|
||||||
|
size->refCnt = 1;
|
||||||
if (gc->stipple)
|
if (gc->stipple)
|
||||||
{
|
{
|
||||||
PixmapPtr pixmap = gc->stipple;
|
PixmapPtr pixmap = gc->stipple;
|
||||||
|
|
|
@ -162,6 +162,8 @@ typedef struct {
|
||||||
unsigned long resourceSize;
|
unsigned long resourceSize;
|
||||||
/* Size attributed to pixmap references from the resource. */
|
/* Size attributed to pixmap references from the resource. */
|
||||||
unsigned long pixmapRefSize;
|
unsigned long pixmapRefSize;
|
||||||
|
/* Number of references to this resource; typically 1 */
|
||||||
|
unsigned long refCnt;
|
||||||
} ResourceSizeRec, *ResourceSizePtr;
|
} ResourceSizeRec, *ResourceSizePtr;
|
||||||
|
|
||||||
typedef void (*SizeType)(pointer /*value*/,
|
typedef void (*SizeType)(pointer /*value*/,
|
||||||
|
|
|
@ -600,12 +600,14 @@ GetPictureBytes(pointer value, XID id, ResourceSizePtr size)
|
||||||
/* Currently only pixmap bytes are reported to clients. */
|
/* Currently only pixmap bytes are reported to clients. */
|
||||||
size->resourceSize = 0;
|
size->resourceSize = 0;
|
||||||
|
|
||||||
|
size->refCnt = picture->refcnt;
|
||||||
|
|
||||||
/* Calculate pixmap reference sizes. */
|
/* Calculate pixmap reference sizes. */
|
||||||
size->pixmapRefSize = 0;
|
size->pixmapRefSize = 0;
|
||||||
if (picture->pDrawable && (picture->pDrawable->type == DRAWABLE_PIXMAP))
|
if (picture->pDrawable && (picture->pDrawable->type == DRAWABLE_PIXMAP))
|
||||||
{
|
{
|
||||||
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
|
||||||
ResourceSizeRec pixmapSize = { 0, 0 };
|
ResourceSizeRec pixmapSize = { 0, 0, 0 };
|
||||||
PixmapPtr pixmap = (PixmapPtr)picture->pDrawable;
|
PixmapPtr pixmap = (PixmapPtr)picture->pDrawable;
|
||||||
pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
|
pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
|
||||||
size->pixmapRefSize += pixmapSize.pixmapRefSize;
|
size->pixmapRefSize += pixmapSize.pixmapRefSize;
|
||||||
|
|
Loading…
Reference in New Issue