384 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			384 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
   Copyright (c) 2002  XFree86 Inc
 | 
						|
*/
 | 
						|
 | 
						|
#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 "registry.h"
 | 
						|
#include <X11/extensions/XResproto.h>
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "modinit.h"
 | 
						|
#include "protocol-versions.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 = SERVER_XRES_MAJOR_VERSION;
 | 
						|
    rep.server_minor = SERVER_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 Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ProcXResQueryClients (ClientPtr client)
 | 
						|
{
 | 
						|
    /* REQUEST(xXResQueryClientsReq); */
 | 
						|
    xXResQueryClientsReply rep;
 | 
						|
    int *current_clients;
 | 
						|
    int i, num_clients;
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xXResQueryClientsReq);
 | 
						|
 | 
						|
    current_clients = malloc(currentMaxClients * sizeof(int));
 | 
						|
 | 
						|
    num_clients = 0;
 | 
						|
    for(i = 0; 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 = bytes_to_int32(rep.num_clients * sz_xXResClient);
 | 
						|
    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) {
 | 
						|
                int n;
 | 
						|
                swapl (&scratch.resource_base, n);
 | 
						|
                swapl (&scratch.resource_mask, n);
 | 
						|
            }
 | 
						|
            WriteToClient (client, sz_xXResClient, (char *) &scratch);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    free(current_clients);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
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);
 | 
						|
 | 
						|
    if((clientID >= currentMaxClients) || !clients[clientID]) {
 | 
						|
        client->errorValue = stuff->xid;
 | 
						|
        return BadValue;
 | 
						|
    }
 | 
						|
 | 
						|
    counts = calloc(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 = bytes_to_int32(rep.num_types * sz_xXResType);
 | 
						|
    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;
 | 
						|
	char *name;
 | 
						|
 | 
						|
        for(i = 0; i < lastResourceType; i++) {
 | 
						|
            if(!counts[i]) continue;
 | 
						|
 | 
						|
	    name = (char *)LookupResourceName(i + 1);
 | 
						|
            if (strcmp(name, XREGISTRY_UNKNOWN))
 | 
						|
		scratch.resource_type = MakeAtom(name, strlen(name), TRUE);
 | 
						|
	    else {
 | 
						|
                char buf[40];
 | 
						|
                snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1);
 | 
						|
		scratch.resource_type = MakeAtom(buf, strlen(buf), TRUE);
 | 
						|
            }
 | 
						|
 | 
						|
            scratch.count = counts[i];
 | 
						|
 | 
						|
            if(client->swapped) {
 | 
						|
                int n;
 | 
						|
                swapl (&scratch.resource_type, n);
 | 
						|
                swapl (&scratch.count, n);
 | 
						|
            }
 | 
						|
            WriteToClient (client, sz_xXResType, (char *) &scratch);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    free(counts);
 | 
						|
    
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
 | 
						|
    if((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 Success;
 | 
						|
}
 | 
						|
 | 
						|
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,
 | 
						|
                            NULL, StandardMinorOpcode);
 | 
						|
}
 |