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