xres.c revision 6747b715
105b261ecSmrg/*
205b261ecSmrg   Copyright (c) 2002  XFree86 Inc
305b261ecSmrg*/
405b261ecSmrg
505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
605b261ecSmrg#include <dix-config.h>
705b261ecSmrg#endif
805b261ecSmrg
905b261ecSmrg#include <stdio.h>
1005b261ecSmrg#include <string.h>
1105b261ecSmrg#include <X11/X.h>
1205b261ecSmrg#include <X11/Xproto.h>
1305b261ecSmrg#include "misc.h"
1405b261ecSmrg#include "os.h"
1505b261ecSmrg#include "dixstruct.h"
1605b261ecSmrg#include "extnsionst.h"
1705b261ecSmrg#include "swaprep.h"
184642e01fSmrg#include "registry.h"
1905b261ecSmrg#include <X11/extensions/XResproto.h>
2005b261ecSmrg#include "pixmapstr.h"
2105b261ecSmrg#include "windowstr.h"
2205b261ecSmrg#include "gcstruct.h"
2305b261ecSmrg#include "modinit.h"
246747b715Smrg#include "protocol-versions.h"
2505b261ecSmrg
2605b261ecSmrgstatic int
2705b261ecSmrgProcXResQueryVersion (ClientPtr client)
2805b261ecSmrg{
2905b261ecSmrg    REQUEST(xXResQueryVersionReq);
3005b261ecSmrg    xXResQueryVersionReply rep;
3105b261ecSmrg    CARD16 client_major, client_minor;  /* not used */
3205b261ecSmrg
3305b261ecSmrg    REQUEST_SIZE_MATCH (xXResQueryVersionReq);
3405b261ecSmrg
3505b261ecSmrg    client_major = stuff->client_major;
3605b261ecSmrg    client_minor = stuff->client_minor;
3705b261ecSmrg    (void) client_major;
3805b261ecSmrg    (void) client_minor;
3905b261ecSmrg
4005b261ecSmrg    rep.type = X_Reply;
4105b261ecSmrg    rep.length = 0;
4205b261ecSmrg    rep.sequenceNumber = client->sequence;
436747b715Smrg    rep.server_major = SERVER_XRES_MAJOR_VERSION;
446747b715Smrg    rep.server_minor = SERVER_XRES_MINOR_VERSION;
4505b261ecSmrg    if (client->swapped) {
4605b261ecSmrg        int n;
4705b261ecSmrg        swaps(&rep.sequenceNumber, n);
4805b261ecSmrg        swapl(&rep.length, n);
4905b261ecSmrg        swaps(&rep.server_major, n);
5005b261ecSmrg        swaps(&rep.server_minor, n);
5105b261ecSmrg    }
5205b261ecSmrg    WriteToClient(client, sizeof (xXResQueryVersionReply), (char *)&rep);
536747b715Smrg    return Success;
5405b261ecSmrg}
5505b261ecSmrg
5605b261ecSmrgstatic int
5705b261ecSmrgProcXResQueryClients (ClientPtr client)
5805b261ecSmrg{
5905b261ecSmrg    /* REQUEST(xXResQueryClientsReq); */
6005b261ecSmrg    xXResQueryClientsReply rep;
6105b261ecSmrg    int *current_clients;
6205b261ecSmrg    int i, num_clients;
6305b261ecSmrg
6405b261ecSmrg    REQUEST_SIZE_MATCH(xXResQueryClientsReq);
6505b261ecSmrg
666747b715Smrg    current_clients = malloc(currentMaxClients * sizeof(int));
6705b261ecSmrg
6805b261ecSmrg    num_clients = 0;
694642e01fSmrg    for(i = 0; i < currentMaxClients; i++) {
7005b261ecSmrg       if(clients[i]) {
7105b261ecSmrg           current_clients[num_clients] = i;
7205b261ecSmrg           num_clients++;
7305b261ecSmrg       }
7405b261ecSmrg    }
7505b261ecSmrg
7605b261ecSmrg    rep.type = X_Reply;
7705b261ecSmrg    rep.sequenceNumber = client->sequence;
7805b261ecSmrg    rep.num_clients = num_clients;
796747b715Smrg    rep.length = bytes_to_int32(rep.num_clients * sz_xXResClient);
8005b261ecSmrg    if (client->swapped) {
8105b261ecSmrg        int n;
8205b261ecSmrg        swaps (&rep.sequenceNumber, n);
8305b261ecSmrg        swapl (&rep.length, n);
8405b261ecSmrg        swapl (&rep.num_clients, n);
8505b261ecSmrg    }
8605b261ecSmrg    WriteToClient (client, sizeof (xXResQueryClientsReply), (char *) &rep);
8705b261ecSmrg
8805b261ecSmrg    if(num_clients) {
8905b261ecSmrg        xXResClient scratch;
9005b261ecSmrg
9105b261ecSmrg        for(i = 0; i < num_clients; i++) {
9205b261ecSmrg            scratch.resource_base = clients[current_clients[i]]->clientAsMask;
9305b261ecSmrg            scratch.resource_mask = RESOURCE_ID_MASK;
9405b261ecSmrg
9505b261ecSmrg            if(client->swapped) {
964642e01fSmrg                int n;
9705b261ecSmrg                swapl (&scratch.resource_base, n);
9805b261ecSmrg                swapl (&scratch.resource_mask, n);
9905b261ecSmrg            }
10005b261ecSmrg            WriteToClient (client, sz_xXResClient, (char *) &scratch);
10105b261ecSmrg        }
10205b261ecSmrg    }
10305b261ecSmrg
1046747b715Smrg    free(current_clients);
10505b261ecSmrg
1066747b715Smrg    return Success;
10705b261ecSmrg}
10805b261ecSmrg
10905b261ecSmrg
11005b261ecSmrgstatic void
11105b261ecSmrgResFindAllRes (pointer value, XID id, RESTYPE type, pointer cdata)
11205b261ecSmrg{
11305b261ecSmrg    int *counts = (int *)cdata;
11405b261ecSmrg
11505b261ecSmrg    counts[(type & TypeMask) - 1]++;
11605b261ecSmrg}
11705b261ecSmrg
11805b261ecSmrgstatic int
11905b261ecSmrgProcXResQueryClientResources (ClientPtr client)
12005b261ecSmrg{
12105b261ecSmrg    REQUEST(xXResQueryClientResourcesReq);
12205b261ecSmrg    xXResQueryClientResourcesReply rep;
12305b261ecSmrg    int i, clientID, num_types;
12405b261ecSmrg    int *counts;
12505b261ecSmrg
12605b261ecSmrg    REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq);
12705b261ecSmrg
12805b261ecSmrg    clientID = CLIENT_ID(stuff->xid);
12905b261ecSmrg
1304642e01fSmrg    if((clientID >= currentMaxClients) || !clients[clientID]) {
13105b261ecSmrg        client->errorValue = stuff->xid;
13205b261ecSmrg        return BadValue;
13305b261ecSmrg    }
13405b261ecSmrg
1356747b715Smrg    counts = calloc(lastResourceType + 1, sizeof(int));
13605b261ecSmrg
13705b261ecSmrg    FindAllClientResources(clients[clientID], ResFindAllRes, counts);
13805b261ecSmrg
13905b261ecSmrg    num_types = 0;
14005b261ecSmrg
14105b261ecSmrg    for(i = 0; i <= lastResourceType; i++) {
14205b261ecSmrg       if(counts[i]) num_types++;
14305b261ecSmrg    }
14405b261ecSmrg
14505b261ecSmrg    rep.type = X_Reply;
14605b261ecSmrg    rep.sequenceNumber = client->sequence;
14705b261ecSmrg    rep.num_types = num_types;
1486747b715Smrg    rep.length = bytes_to_int32(rep.num_types * sz_xXResType);
14905b261ecSmrg    if (client->swapped) {
15005b261ecSmrg        int n;
15105b261ecSmrg        swaps (&rep.sequenceNumber, n);
15205b261ecSmrg        swapl (&rep.length, n);
15305b261ecSmrg        swapl (&rep.num_types, n);
15405b261ecSmrg    }
15505b261ecSmrg
15605b261ecSmrg    WriteToClient (client,sizeof(xXResQueryClientResourcesReply),(char*)&rep);
15705b261ecSmrg
15805b261ecSmrg    if(num_types) {
15905b261ecSmrg        xXResType scratch;
1604642e01fSmrg	char *name;
16105b261ecSmrg
16205b261ecSmrg        for(i = 0; i < lastResourceType; i++) {
16305b261ecSmrg            if(!counts[i]) continue;
16405b261ecSmrg
1654642e01fSmrg	    name = (char *)LookupResourceName(i + 1);
1664642e01fSmrg            if (strcmp(name, XREGISTRY_UNKNOWN))
1674642e01fSmrg		scratch.resource_type = MakeAtom(name, strlen(name), TRUE);
1684642e01fSmrg	    else {
16905b261ecSmrg                char buf[40];
17005b261ecSmrg                snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1);
1714642e01fSmrg		scratch.resource_type = MakeAtom(buf, strlen(buf), TRUE);
17205b261ecSmrg            }
17305b261ecSmrg
17405b261ecSmrg            scratch.count = counts[i];
17505b261ecSmrg
17605b261ecSmrg            if(client->swapped) {
1774642e01fSmrg                int n;
17805b261ecSmrg                swapl (&scratch.resource_type, n);
17905b261ecSmrg                swapl (&scratch.count, n);
18005b261ecSmrg            }
18105b261ecSmrg            WriteToClient (client, sz_xXResType, (char *) &scratch);
18205b261ecSmrg        }
18305b261ecSmrg    }
18405b261ecSmrg
1856747b715Smrg    free(counts);
18605b261ecSmrg
1876747b715Smrg    return Success;
18805b261ecSmrg}
18905b261ecSmrg
19005b261ecSmrgstatic unsigned long
19105b261ecSmrgResGetApproxPixmapBytes (PixmapPtr pix)
19205b261ecSmrg{
19305b261ecSmrg   unsigned long nPixels;
19405b261ecSmrg   int           bytesPerPixel;
19505b261ecSmrg
19605b261ecSmrg   bytesPerPixel = pix->drawable.bitsPerPixel>>3;
19705b261ecSmrg   nPixels       = pix->drawable.width * pix->drawable.height;
19805b261ecSmrg
19905b261ecSmrg   /* Divide by refcnt as pixmap could be shared between clients,
20005b261ecSmrg    * so total pixmap mem is shared between these.
20105b261ecSmrg   */
20205b261ecSmrg   return ( nPixels * bytesPerPixel ) / pix->refcnt;
20305b261ecSmrg}
20405b261ecSmrg
20505b261ecSmrgstatic void
20605b261ecSmrgResFindPixmaps (pointer value, XID id, pointer cdata)
20705b261ecSmrg{
20805b261ecSmrg   unsigned long *bytes = (unsigned long *)cdata;
20905b261ecSmrg   PixmapPtr pix = (PixmapPtr)value;
21005b261ecSmrg
21105b261ecSmrg   *bytes += ResGetApproxPixmapBytes(pix);
21205b261ecSmrg}
21305b261ecSmrg
21405b261ecSmrgstatic void
21505b261ecSmrgResFindWindowPixmaps (pointer value, XID id, pointer cdata)
21605b261ecSmrg{
21705b261ecSmrg   unsigned long *bytes = (unsigned long *)cdata;
21805b261ecSmrg   WindowPtr pWin = (WindowPtr)value;
21905b261ecSmrg
22005b261ecSmrg   if (pWin->backgroundState == BackgroundPixmap)
22105b261ecSmrg     *bytes += ResGetApproxPixmapBytes(pWin->background.pixmap);
22205b261ecSmrg
22305b261ecSmrg   if (pWin->border.pixmap != NULL && !pWin->borderIsPixel)
22405b261ecSmrg     *bytes += ResGetApproxPixmapBytes(pWin->border.pixmap);
22505b261ecSmrg}
22605b261ecSmrg
22705b261ecSmrgstatic void
22805b261ecSmrgResFindGCPixmaps (pointer value, XID id, pointer cdata)
22905b261ecSmrg{
23005b261ecSmrg   unsigned long *bytes = (unsigned long *)cdata;
23105b261ecSmrg   GCPtr pGC = (GCPtr)value;
23205b261ecSmrg
23305b261ecSmrg   if (pGC->stipple != NULL)
23405b261ecSmrg     *bytes += ResGetApproxPixmapBytes(pGC->stipple);
23505b261ecSmrg
23605b261ecSmrg   if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel)
23705b261ecSmrg     *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
23805b261ecSmrg}
23905b261ecSmrg
24005b261ecSmrgstatic int
24105b261ecSmrgProcXResQueryClientPixmapBytes (ClientPtr client)
24205b261ecSmrg{
24305b261ecSmrg    REQUEST(xXResQueryClientPixmapBytesReq);
24405b261ecSmrg    xXResQueryClientPixmapBytesReply rep;
24505b261ecSmrg    int clientID;
24605b261ecSmrg    unsigned long bytes;
24705b261ecSmrg
24805b261ecSmrg    REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq);
24905b261ecSmrg
25005b261ecSmrg    clientID = CLIENT_ID(stuff->xid);
25105b261ecSmrg
2524642e01fSmrg    if((clientID >= currentMaxClients) || !clients[clientID]) {
25305b261ecSmrg        client->errorValue = stuff->xid;
25405b261ecSmrg        return BadValue;
25505b261ecSmrg    }
25605b261ecSmrg
25705b261ecSmrg    bytes = 0;
25805b261ecSmrg
25905b261ecSmrg    FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps,
26005b261ecSmrg                              (pointer)(&bytes));
26105b261ecSmrg
26205b261ecSmrg    /*
26305b261ecSmrg     * Make sure win background pixmaps also held to account.
26405b261ecSmrg     */
26505b261ecSmrg    FindClientResourcesByType(clients[clientID], RT_WINDOW,
26605b261ecSmrg			      ResFindWindowPixmaps,
26705b261ecSmrg                              (pointer)(&bytes));
26805b261ecSmrg
26905b261ecSmrg    /*
27005b261ecSmrg     * GC Tile & Stipple pixmaps too.
27105b261ecSmrg    */
27205b261ecSmrg    FindClientResourcesByType(clients[clientID], RT_GC,
27305b261ecSmrg			      ResFindGCPixmaps,
27405b261ecSmrg                              (pointer)(&bytes));
27505b261ecSmrg
27605b261ecSmrg#ifdef COMPOSITE
27705b261ecSmrg    /* FIXME: include composite pixmaps too */
27805b261ecSmrg#endif
27905b261ecSmrg
28005b261ecSmrg    rep.type = X_Reply;
28105b261ecSmrg    rep.sequenceNumber = client->sequence;
28205b261ecSmrg    rep.length = 0;
28305b261ecSmrg    rep.bytes = bytes;
28405b261ecSmrg#ifdef _XSERVER64
28505b261ecSmrg    rep.bytes_overflow = bytes >> 32;
28605b261ecSmrg#else
28705b261ecSmrg    rep.bytes_overflow = 0;
28805b261ecSmrg#endif
28905b261ecSmrg    if (client->swapped) {
29005b261ecSmrg        int n;
29105b261ecSmrg        swaps (&rep.sequenceNumber, n);
29205b261ecSmrg        swapl (&rep.length, n);
29305b261ecSmrg        swapl (&rep.bytes, n);
29405b261ecSmrg        swapl (&rep.bytes_overflow, n);
29505b261ecSmrg    }
29605b261ecSmrg    WriteToClient (client,sizeof(xXResQueryClientPixmapBytesReply),(char*)&rep);
29705b261ecSmrg
2986747b715Smrg    return Success;
29905b261ecSmrg}
30005b261ecSmrg
30105b261ecSmrgstatic int
30205b261ecSmrgProcResDispatch (ClientPtr client)
30305b261ecSmrg{
30405b261ecSmrg    REQUEST(xReq);
30505b261ecSmrg    switch (stuff->data) {
30605b261ecSmrg    case X_XResQueryVersion:
30705b261ecSmrg        return ProcXResQueryVersion(client);
30805b261ecSmrg    case X_XResQueryClients:
30905b261ecSmrg        return ProcXResQueryClients(client);
31005b261ecSmrg    case X_XResQueryClientResources:
31105b261ecSmrg        return ProcXResQueryClientResources(client);
31205b261ecSmrg    case X_XResQueryClientPixmapBytes:
31305b261ecSmrg        return ProcXResQueryClientPixmapBytes(client);
31405b261ecSmrg    default: break;
31505b261ecSmrg    }
31605b261ecSmrg
31705b261ecSmrg    return BadRequest;
31805b261ecSmrg}
31905b261ecSmrg
32005b261ecSmrgstatic int
32105b261ecSmrgSProcXResQueryVersion (ClientPtr client)
32205b261ecSmrg{
32305b261ecSmrg    REQUEST(xXResQueryVersionReq);
32405b261ecSmrg    int n;
32505b261ecSmrg
32605b261ecSmrg    REQUEST_SIZE_MATCH (xXResQueryVersionReq);
32705b261ecSmrg    swaps(&stuff->client_major,n);
32805b261ecSmrg    swaps(&stuff->client_minor,n);
32905b261ecSmrg    return ProcXResQueryVersion(client);
33005b261ecSmrg}
33105b261ecSmrg
33205b261ecSmrgstatic int
33305b261ecSmrgSProcXResQueryClientResources (ClientPtr client)
33405b261ecSmrg{
33505b261ecSmrg    REQUEST(xXResQueryClientResourcesReq);
33605b261ecSmrg    int n;
33705b261ecSmrg
33805b261ecSmrg    REQUEST_SIZE_MATCH (xXResQueryClientResourcesReq);
33905b261ecSmrg    swaps(&stuff->xid,n);
34005b261ecSmrg    return ProcXResQueryClientResources(client);
34105b261ecSmrg}
34205b261ecSmrg
34305b261ecSmrgstatic int
34405b261ecSmrgSProcXResQueryClientPixmapBytes (ClientPtr client)
34505b261ecSmrg{
34605b261ecSmrg    REQUEST(xXResQueryClientPixmapBytesReq);
34705b261ecSmrg    int n;
34805b261ecSmrg
34905b261ecSmrg    REQUEST_SIZE_MATCH (xXResQueryClientPixmapBytesReq);
35005b261ecSmrg    swaps(&stuff->xid,n);
35105b261ecSmrg    return ProcXResQueryClientPixmapBytes(client);
35205b261ecSmrg}
35305b261ecSmrg
35405b261ecSmrgstatic int
35505b261ecSmrgSProcResDispatch (ClientPtr client)
35605b261ecSmrg{
35705b261ecSmrg    REQUEST(xReq);
35805b261ecSmrg    int n;
35905b261ecSmrg
36005b261ecSmrg    swaps(&stuff->length,n);
36105b261ecSmrg
36205b261ecSmrg    switch (stuff->data) {
36305b261ecSmrg    case X_XResQueryVersion:
36405b261ecSmrg        return SProcXResQueryVersion(client);
36505b261ecSmrg    case X_XResQueryClients:  /* nothing to swap */
36605b261ecSmrg        return ProcXResQueryClients(client);
36705b261ecSmrg    case X_XResQueryClientResources:
36805b261ecSmrg        return SProcXResQueryClientResources(client);
36905b261ecSmrg    case X_XResQueryClientPixmapBytes:
37005b261ecSmrg        return SProcXResQueryClientPixmapBytes(client);
37105b261ecSmrg    default: break;
37205b261ecSmrg    }
37305b261ecSmrg
37405b261ecSmrg    return BadRequest;
37505b261ecSmrg}
37605b261ecSmrg
37705b261ecSmrgvoid
37805b261ecSmrgResExtensionInit(INITARGS)
37905b261ecSmrg{
38005b261ecSmrg    (void) AddExtension(XRES_NAME, 0, 0,
38105b261ecSmrg                            ProcResDispatch, SProcResDispatch,
3824642e01fSmrg                            NULL, StandardMinorOpcode);
38305b261ecSmrg}
384