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