xres.c revision 4642e01f
1/*
2   Copyright (c) 2002  XFree86 Inc
3*/
4
5#define NEED_EVENTS
6#define NEED_REPLIES
7#ifdef HAVE_DIX_CONFIG_H
8#include <dix-config.h>
9#endif
10
11#include <stdio.h>
12#include <string.h>
13#include <X11/X.h>
14#include <X11/Xproto.h>
15#include "misc.h"
16#include "os.h"
17#include "dixstruct.h"
18#include "extnsionst.h"
19#include "swaprep.h"
20#include "registry.h"
21#include <X11/extensions/XResproto.h>
22#include "pixmapstr.h"
23#include "windowstr.h"
24#include "gcstruct.h"
25#include "modinit.h"
26
27static int
28ProcXResQueryVersion (ClientPtr client)
29{
30    REQUEST(xXResQueryVersionReq);
31    xXResQueryVersionReply rep;
32    CARD16 client_major, client_minor;  /* not used */
33
34    REQUEST_SIZE_MATCH (xXResQueryVersionReq);
35
36    client_major = stuff->client_major;
37    client_minor = stuff->client_minor;
38    (void) client_major;
39    (void) client_minor;
40
41    rep.type = X_Reply;
42    rep.length = 0;
43    rep.sequenceNumber = client->sequence;
44    rep.server_major = XRES_MAJOR_VERSION;
45    rep.server_minor = XRES_MINOR_VERSION;
46    if (client->swapped) {
47        int n;
48        swaps(&rep.sequenceNumber, n);
49        swapl(&rep.length, n);
50        swaps(&rep.server_major, n);
51        swaps(&rep.server_minor, n);
52    }
53    WriteToClient(client, sizeof (xXResQueryVersionReply), (char *)&rep);
54    return (client->noClientException);
55}
56
57static int
58ProcXResQueryClients (ClientPtr client)
59{
60    /* REQUEST(xXResQueryClientsReq); */
61    xXResQueryClientsReply rep;
62    int *current_clients;
63    int i, num_clients;
64
65    REQUEST_SIZE_MATCH(xXResQueryClientsReq);
66
67    current_clients = xalloc(currentMaxClients * sizeof(int));
68
69    num_clients = 0;
70    for(i = 0; i < currentMaxClients; i++) {
71       if(clients[i]) {
72           current_clients[num_clients] = i;
73           num_clients++;
74       }
75    }
76
77    rep.type = X_Reply;
78    rep.sequenceNumber = client->sequence;
79    rep.num_clients = num_clients;
80    rep.length = rep.num_clients * sz_xXResClient >> 2;
81    if (client->swapped) {
82        int n;
83        swaps (&rep.sequenceNumber, n);
84        swapl (&rep.length, n);
85        swapl (&rep.num_clients, n);
86    }
87    WriteToClient (client, sizeof (xXResQueryClientsReply), (char *) &rep);
88
89    if(num_clients) {
90        xXResClient scratch;
91
92        for(i = 0; i < num_clients; i++) {
93            scratch.resource_base = clients[current_clients[i]]->clientAsMask;
94            scratch.resource_mask = RESOURCE_ID_MASK;
95
96            if(client->swapped) {
97                int n;
98                swapl (&scratch.resource_base, n);
99                swapl (&scratch.resource_mask, n);
100            }
101            WriteToClient (client, sz_xXResClient, (char *) &scratch);
102        }
103    }
104
105    xfree(current_clients);
106
107    return (client->noClientException);
108}
109
110
111static void
112ResFindAllRes (pointer value, XID id, RESTYPE type, pointer cdata)
113{
114    int *counts = (int *)cdata;
115
116    counts[(type & TypeMask) - 1]++;
117}
118
119static int
120ProcXResQueryClientResources (ClientPtr client)
121{
122    REQUEST(xXResQueryClientResourcesReq);
123    xXResQueryClientResourcesReply rep;
124    int i, clientID, num_types;
125    int *counts;
126
127    REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq);
128
129    clientID = CLIENT_ID(stuff->xid);
130
131    if((clientID >= currentMaxClients) || !clients[clientID]) {
132        client->errorValue = stuff->xid;
133        return BadValue;
134    }
135
136    counts = xcalloc(lastResourceType + 1, sizeof(int));
137
138    FindAllClientResources(clients[clientID], ResFindAllRes, counts);
139
140    num_types = 0;
141
142    for(i = 0; i <= lastResourceType; i++) {
143       if(counts[i]) num_types++;
144    }
145
146    rep.type = X_Reply;
147    rep.sequenceNumber = client->sequence;
148    rep.num_types = num_types;
149    rep.length = rep.num_types * sz_xXResType >> 2;
150    if (client->swapped) {
151        int n;
152        swaps (&rep.sequenceNumber, n);
153        swapl (&rep.length, n);
154        swapl (&rep.num_types, n);
155    }
156
157    WriteToClient (client,sizeof(xXResQueryClientResourcesReply),(char*)&rep);
158
159    if(num_types) {
160        xXResType scratch;
161	char *name;
162
163        for(i = 0; i < lastResourceType; i++) {
164            if(!counts[i]) continue;
165
166	    name = (char *)LookupResourceName(i + 1);
167            if (strcmp(name, XREGISTRY_UNKNOWN))
168		scratch.resource_type = MakeAtom(name, strlen(name), TRUE);
169	    else {
170                char buf[40];
171                snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1);
172		scratch.resource_type = MakeAtom(buf, strlen(buf), TRUE);
173            }
174
175            scratch.count = counts[i];
176
177            if(client->swapped) {
178                int n;
179                swapl (&scratch.resource_type, n);
180                swapl (&scratch.count, n);
181            }
182            WriteToClient (client, sz_xXResType, (char *) &scratch);
183        }
184    }
185
186    xfree(counts);
187
188    return (client->noClientException);
189}
190
191static unsigned long
192ResGetApproxPixmapBytes (PixmapPtr pix)
193{
194   unsigned long nPixels;
195   int           bytesPerPixel;
196
197   bytesPerPixel = pix->drawable.bitsPerPixel>>3;
198   nPixels       = pix->drawable.width * pix->drawable.height;
199
200   /* Divide by refcnt as pixmap could be shared between clients,
201    * so total pixmap mem is shared between these.
202   */
203   return ( nPixels * bytesPerPixel ) / pix->refcnt;
204}
205
206static void
207ResFindPixmaps (pointer value, XID id, pointer cdata)
208{
209   unsigned long *bytes = (unsigned long *)cdata;
210   PixmapPtr pix = (PixmapPtr)value;
211
212   *bytes += ResGetApproxPixmapBytes(pix);
213}
214
215static void
216ResFindWindowPixmaps (pointer value, XID id, pointer cdata)
217{
218   unsigned long *bytes = (unsigned long *)cdata;
219   WindowPtr pWin = (WindowPtr)value;
220
221   if (pWin->backgroundState == BackgroundPixmap)
222     *bytes += ResGetApproxPixmapBytes(pWin->background.pixmap);
223
224   if (pWin->border.pixmap != NULL && !pWin->borderIsPixel)
225     *bytes += ResGetApproxPixmapBytes(pWin->border.pixmap);
226}
227
228static void
229ResFindGCPixmaps (pointer value, XID id, pointer cdata)
230{
231   unsigned long *bytes = (unsigned long *)cdata;
232   GCPtr pGC = (GCPtr)value;
233
234   if (pGC->stipple != NULL)
235     *bytes += ResGetApproxPixmapBytes(pGC->stipple);
236
237   if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel)
238     *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
239}
240
241static int
242ProcXResQueryClientPixmapBytes (ClientPtr client)
243{
244    REQUEST(xXResQueryClientPixmapBytesReq);
245    xXResQueryClientPixmapBytesReply rep;
246    int clientID;
247    unsigned long bytes;
248
249    REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq);
250
251    clientID = CLIENT_ID(stuff->xid);
252
253    if((clientID >= currentMaxClients) || !clients[clientID]) {
254        client->errorValue = stuff->xid;
255        return BadValue;
256    }
257
258    bytes = 0;
259
260    FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps,
261                              (pointer)(&bytes));
262
263    /*
264     * Make sure win background pixmaps also held to account.
265     */
266    FindClientResourcesByType(clients[clientID], RT_WINDOW,
267			      ResFindWindowPixmaps,
268                              (pointer)(&bytes));
269
270    /*
271     * GC Tile & Stipple pixmaps too.
272    */
273    FindClientResourcesByType(clients[clientID], RT_GC,
274			      ResFindGCPixmaps,
275                              (pointer)(&bytes));
276
277#ifdef COMPOSITE
278    /* FIXME: include composite pixmaps too */
279#endif
280
281    rep.type = X_Reply;
282    rep.sequenceNumber = client->sequence;
283    rep.length = 0;
284    rep.bytes = bytes;
285#ifdef _XSERVER64
286    rep.bytes_overflow = bytes >> 32;
287#else
288    rep.bytes_overflow = 0;
289#endif
290    if (client->swapped) {
291        int n;
292        swaps (&rep.sequenceNumber, n);
293        swapl (&rep.length, n);
294        swapl (&rep.bytes, n);
295        swapl (&rep.bytes_overflow, n);
296    }
297    WriteToClient (client,sizeof(xXResQueryClientPixmapBytesReply),(char*)&rep);
298
299    return (client->noClientException);
300}
301
302static int
303ProcResDispatch (ClientPtr client)
304{
305    REQUEST(xReq);
306    switch (stuff->data) {
307    case X_XResQueryVersion:
308        return ProcXResQueryVersion(client);
309    case X_XResQueryClients:
310        return ProcXResQueryClients(client);
311    case X_XResQueryClientResources:
312        return ProcXResQueryClientResources(client);
313    case X_XResQueryClientPixmapBytes:
314        return ProcXResQueryClientPixmapBytes(client);
315    default: break;
316    }
317
318    return BadRequest;
319}
320
321static int
322SProcXResQueryVersion (ClientPtr client)
323{
324    REQUEST(xXResQueryVersionReq);
325    int n;
326
327    REQUEST_SIZE_MATCH (xXResQueryVersionReq);
328    swaps(&stuff->client_major,n);
329    swaps(&stuff->client_minor,n);
330    return ProcXResQueryVersion(client);
331}
332
333static int
334SProcXResQueryClientResources (ClientPtr client)
335{
336    REQUEST(xXResQueryClientResourcesReq);
337    int n;
338
339    REQUEST_SIZE_MATCH (xXResQueryClientResourcesReq);
340    swaps(&stuff->xid,n);
341    return ProcXResQueryClientResources(client);
342}
343
344static int
345SProcXResQueryClientPixmapBytes (ClientPtr client)
346{
347    REQUEST(xXResQueryClientPixmapBytesReq);
348    int n;
349
350    REQUEST_SIZE_MATCH (xXResQueryClientPixmapBytesReq);
351    swaps(&stuff->xid,n);
352    return ProcXResQueryClientPixmapBytes(client);
353}
354
355static int
356SProcResDispatch (ClientPtr client)
357{
358    REQUEST(xReq);
359    int n;
360
361    swaps(&stuff->length,n);
362
363    switch (stuff->data) {
364    case X_XResQueryVersion:
365        return SProcXResQueryVersion(client);
366    case X_XResQueryClients:  /* nothing to swap */
367        return ProcXResQueryClients(client);
368    case X_XResQueryClientResources:
369        return SProcXResQueryClientResources(client);
370    case X_XResQueryClientPixmapBytes:
371        return SProcXResQueryClientPixmapBytes(client);
372    default: break;
373    }
374
375    return BadRequest;
376}
377
378void
379ResExtensionInit(INITARGS)
380{
381    (void) AddExtension(XRES_NAME, 0, 0,
382                            ProcResDispatch, SProcResDispatch,
383                            NULL, StandardMinorOpcode);
384}
385