/*
Copyright (c) 2002 XFree86 Inc
*/
#define NEED_EVENTS
#define NEED_REPLIES
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <X11/X.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "os.h"
#include "dixstruct.h"
#include "extnsionst.h"
#include "swaprep.h"
#include <X11/extensions/XResproto.h>
#include "pixmapstr.h"
#include "windowstr.h"
#include "gcstruct.h"
#include "modinit.h"
static int
ProcXResQueryVersion (ClientPtr client)
{
REQUEST(xXResQueryVersionReq);
xXResQueryVersionReply rep;
CARD16 client_major, client_minor; /* not used */
REQUEST_SIZE_MATCH (xXResQueryVersionReq);
client_major = stuff->client_major;
client_minor = stuff->client_minor;
(void) client_major;
(void) client_minor;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.server_major = XRES_MAJOR_VERSION;
rep.server_minor = XRES_MINOR_VERSION;
if (client->swapped) {
int n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swaps(&rep.server_major, n);
swaps(&rep.server_minor, n);
}
WriteToClient(client, sizeof (xXResQueryVersionReply), (char *)&rep);
return (client->noClientException);
}
static int
ProcXResQueryClients (ClientPtr client)
{
/* REQUEST(xXResQueryClientsReq); */
xXResQueryClientsReply rep;
int *current_clients;
int i, num_clients;
REQUEST_SIZE_MATCH(xXResQueryClientsReq);
current_clients = ALLOCATE_LOCAL((currentMaxClients - 1) * sizeof(int));
num_clients = 0;
for(i = 1; i < currentMaxClients; i++) {
if(clients[i]) {
current_clients[num_clients] = i;
num_clients++;
}
}
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.num_clients = num_clients;
rep.length = rep.num_clients * sz_xXResClient >> 2;
if (client->swapped) {
int n;
swaps (&rep.sequenceNumber, n);
swapl (&rep.length, n);
swapl (&rep.num_clients, n);
}
WriteToClient (client, sizeof (xXResQueryClientsReply), (char *) &rep);
if(num_clients) {
xXResClient scratch;
for(i = 0; i < num_clients; i++) {
scratch.resource_base = clients[current_clients[i]]->clientAsMask;
scratch.resource_mask = RESOURCE_ID_MASK;
if(client->swapped) {
register int n;
swapl (&scratch.resource_base, n);
swapl (&scratch.resource_mask, n);
}
WriteToClient (client, sz_xXResClient, (char *) &scratch);
}
}
DEALLOCATE_LOCAL(current_clients);
return (client->noClientException);
}
static void
ResFindAllRes (pointer value, XID id, RESTYPE type, pointer cdata)
{
int *counts = (int *)cdata;
counts[(type & TypeMask) - 1]++;
}
static int
ProcXResQueryClientResources (ClientPtr client)
{
REQUEST(xXResQueryClientResourcesReq);
xXResQueryClientResourcesReply rep;
int i, clientID, num_types;
int *counts;
REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq);
clientID = CLIENT_ID(stuff->xid);
/* we could remove the (clientID == 0) check if we wanted to allow
probing the X-server's resource usage */
if(!clientID || (clientID >= currentMaxClients) || !clients[clientID]) {
client->errorValue = stuff->xid;
return BadValue;
}
counts = ALLOCATE_LOCAL((lastResourceType + 1) * sizeof(int));
memset(counts, 0, (lastResourceType + 1) * sizeof(int));
FindAllClientResources(clients[clientID], ResFindAllRes, counts);
num_types = 0;
for(i = 0; i <= lastResourceType; i++) {
if(counts[i]) num_types++;
}
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.num_types = num_types;
rep.length = rep.num_types * sz_xXResType >> 2;
if (client->swapped) {
int n;
swaps (&rep.sequenceNumber, n);
swapl (&rep.length, n);
swapl (&rep.num_types, n);
}
WriteToClient (client,sizeof(xXResQueryClientResourcesReply),(char*)&rep);
if(num_types) {
xXResType scratch;
for(i = 0; i < lastResourceType; i++) {
if(!counts[i]) continue;
if(!ResourceNames[i + 1]) {
char buf[40];
snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1);
RegisterResourceName(i + 1, buf);
}
scratch.resource_type = ResourceNames[i + 1];
scratch.count = counts[i];
if(client->swapped) {
register int n;
swapl (&scratch.resource_type, n);
swapl (&scratch.count, n);
}
WriteToClient (client, sz_xXResType, (char *) &scratch);
}
}
DEALLOCATE_LOCAL(counts);
return (client->noClientException);
}
static unsigned long
ResGetApproxPixmapBytes (PixmapPtr pix)
{
unsigned long nPixels;
int bytesPerPixel;
bytesPerPixel = pix->drawable.bitsPerPixel>>3;
nPixels = pix->drawable.width * pix->drawable.height;
/* Divide by refcnt as pixmap could be shared between clients,
* so total pixmap mem is shared between these.
*/
return ( nPixels * bytesPerPixel ) / pix->refcnt;
}
static void
ResFindPixmaps (pointer value, XID id, pointer cdata)
{
unsigned long *bytes = (unsigned long *)cdata;
PixmapPtr pix = (PixmapPtr)value;
*bytes += ResGetApproxPixmapBytes(pix);
}
static void
ResFindWindowPixmaps (pointer value, XID id, pointer cdata)
{
unsigned long *bytes = (unsigned long *)cdata;
WindowPtr pWin = (WindowPtr)value;
if (pWin->backgroundState == BackgroundPixmap)
*bytes += ResGetApproxPixmapBytes(pWin->background.pixmap);
if (pWin->border.pixmap != NULL && !pWin->borderIsPixel)
*bytes += ResGetApproxPixmapBytes(pWin->border.pixmap);
}
static void
ResFindGCPixmaps (pointer value, XID id, pointer cdata)
{
unsigned long *bytes = (unsigned long *)cdata;
GCPtr pGC = (GCPtr)value;
if (pGC->stipple != NULL)
*bytes += ResGetApproxPixmapBytes(pGC->stipple);
if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel)
*bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
}
static int
ProcXResQueryClientPixmapBytes (ClientPtr client)
{
REQUEST(xXResQueryClientPixmapBytesReq);
xXResQueryClientPixmapBytesReply rep;
int clientID;
unsigned long bytes;
REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq);
clientID = CLIENT_ID(stuff->xid);
/* we could remove the (clientID == 0) check if we wanted to allow
probing the X-server's resource usage */
if(!clientID || (clientID >= currentMaxClients) || !clients[clientID]) {
client->errorValue = stuff->xid;
return BadValue;
}
bytes = 0;
FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps,
(pointer)(&bytes));
/*
* Make sure win background pixmaps also held to account.
*/
FindClientResourcesByType(clients[clientID], RT_WINDOW,
ResFindWindowPixmaps,
(pointer)(&bytes));
/*
* GC Tile & Stipple pixmaps too.
*/
FindClientResourcesByType(clients[clientID], RT_GC,
ResFindGCPixmaps,
(pointer)(&bytes));
#ifdef COMPOSITE
/* FIXME: include composite pixmaps too */
#endif
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.bytes = bytes;
#ifdef _XSERVER64
rep.bytes_overflow = bytes >> 32;
#else
rep.bytes_overflow = 0;
#endif
if (client->swapped) {
int n;
swaps (&rep.sequenceNumber, n);
swapl (&rep.length, n);
swapl (&rep.bytes, n);
swapl (&rep.bytes_overflow, n);
}
WriteToClient (client,sizeof(xXResQueryClientPixmapBytesReply),(char*)&rep);
return (client->noClientException);
}
static void
ResResetProc (ExtensionEntry *extEntry) { }
static int
ProcResDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data) {
case X_XResQueryVersion:
return ProcXResQueryVersion(client);
case X_XResQueryClients:
return ProcXResQueryClients(client);
case X_XResQueryClientResources:
return ProcXResQueryClientResources(client);
case X_XResQueryClientPixmapBytes:
return ProcXResQueryClientPixmapBytes(client);
default: break;
}
return BadRequest;
}
static int
SProcXResQueryVersion (ClientPtr client)
{
REQUEST(xXResQueryVersionReq);
int n;
REQUEST_SIZE_MATCH (xXResQueryVersionReq);
swaps(&stuff->client_major,n);
swaps(&stuff->client_minor,n);
return ProcXResQueryVersion(client);
}
static int
SProcXResQueryClientResources (ClientPtr client)
{
REQUEST(xXResQueryClientResourcesReq);
int n;
REQUEST_SIZE_MATCH (xXResQueryClientResourcesReq);
swaps(&stuff->xid,n);
return ProcXResQueryClientResources(client);
}
static int
SProcXResQueryClientPixmapBytes (ClientPtr client)
{
REQUEST(xXResQueryClientPixmapBytesReq);
int n;
REQUEST_SIZE_MATCH (xXResQueryClientPixmapBytesReq);
swaps(&stuff->xid,n);
return ProcXResQueryClientPixmapBytes(client);
}
static int
SProcResDispatch (ClientPtr client)
{
REQUEST(xReq);
int n;
swaps(&stuff->length,n);
switch (stuff->data) {
case X_XResQueryVersion:
return SProcXResQueryVersion(client);
case X_XResQueryClients: /* nothing to swap */
return ProcXResQueryClients(client);
case X_XResQueryClientResources:
return SProcXResQueryClientResources(client);
case X_XResQueryClientPixmapBytes:
return SProcXResQueryClientPixmapBytes(client);
default: break;
}
return BadRequest;
}
void
ResExtensionInit(INITARGS)
{
(void) AddExtension(XRES_NAME, 0, 0,
ProcResDispatch, SProcResDispatch,
ResResetProc, StandardMinorOpcode);
RegisterResourceName(RT_NONE, "NONE");
RegisterResourceName(RT_WINDOW, "WINDOW");
RegisterResourceName(RT_PIXMAP, "PIXMAP");
RegisterResourceName(RT_GC, "GC");
RegisterResourceName(RT_FONT, "FONT");
RegisterResourceName(RT_CURSOR, "CURSOR");
RegisterResourceName(RT_COLORMAP, "COLORMAP");
RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY");
RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT");
RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB");
}
|