xres.c revision 05b261ec
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 <X11/extensions/XResproto.h>
21#include "pixmapstr.h"
22#include "windowstr.h"
23#include "gcstruct.h"
24#include "modinit.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 = XRES_MAJOR_VERSION;
44    rep.server_minor = 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 (client->noClientException);
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 = ALLOCATE_LOCAL((currentMaxClients - 1) * sizeof(int));
67
68    num_clients = 0;
69    for(i = 1; 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 = rep.num_clients * sz_xXResClient >> 2;
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                register 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    DEALLOCATE_LOCAL(current_clients);
105
106    return (client->noClientException);
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    /* we could remove the (clientID == 0) check if we wanted to allow
131       probing the X-server's resource usage */
132    if(!clientID || (clientID >= currentMaxClients) || !clients[clientID]) {
133        client->errorValue = stuff->xid;
134        return BadValue;
135    }
136
137    counts = ALLOCATE_LOCAL((lastResourceType + 1) * sizeof(int));
138
139    memset(counts, 0, (lastResourceType + 1) * sizeof(int));
140
141    FindAllClientResources(clients[clientID], ResFindAllRes, counts);
142
143    num_types = 0;
144
145    for(i = 0; i <= lastResourceType; i++) {
146       if(counts[i]) num_types++;
147    }
148
149    rep.type = X_Reply;
150    rep.sequenceNumber = client->sequence;
151    rep.num_types = num_types;
152    rep.length = rep.num_types * sz_xXResType >> 2;
153    if (client->swapped) {
154        int n;
155        swaps (&rep.sequenceNumber, n);
156        swapl (&rep.length, n);
157        swapl (&rep.num_types, n);
158    }
159
160    WriteToClient (client,sizeof(xXResQueryClientResourcesReply),(char*)&rep);
161
162    if(num_types) {
163        xXResType scratch;
164
165        for(i = 0; i < lastResourceType; i++) {
166            if(!counts[i]) continue;
167
168            if(!ResourceNames[i + 1]) {
169                char buf[40];
170                snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1);
171                RegisterResourceName(i + 1, buf);
172            }
173
174            scratch.resource_type = ResourceNames[i + 1];
175            scratch.count = counts[i];
176
177            if(client->swapped) {
178                register 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    DEALLOCATE_LOCAL(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    /* we could remove the (clientID == 0) check if we wanted to allow
254       probing the X-server's resource usage */
255    if(!clientID || (clientID >= currentMaxClients) || !clients[clientID]) {
256        client->errorValue = stuff->xid;
257        return BadValue;
258    }
259
260    bytes = 0;
261
262    FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps,
263                              (pointer)(&bytes));
264
265    /*
266     * Make sure win background pixmaps also held to account.
267     */
268    FindClientResourcesByType(clients[clientID], RT_WINDOW,
269			      ResFindWindowPixmaps,
270                              (pointer)(&bytes));
271
272    /*
273     * GC Tile & Stipple pixmaps too.
274    */
275    FindClientResourcesByType(clients[clientID], RT_GC,
276			      ResFindGCPixmaps,
277                              (pointer)(&bytes));
278
279#ifdef COMPOSITE
280    /* FIXME: include composite pixmaps too */
281#endif
282
283    rep.type = X_Reply;
284    rep.sequenceNumber = client->sequence;
285    rep.length = 0;
286    rep.bytes = bytes;
287#ifdef _XSERVER64
288    rep.bytes_overflow = bytes >> 32;
289#else
290    rep.bytes_overflow = 0;
291#endif
292    if (client->swapped) {
293        int n;
294        swaps (&rep.sequenceNumber, n);
295        swapl (&rep.length, n);
296        swapl (&rep.bytes, n);
297        swapl (&rep.bytes_overflow, n);
298    }
299    WriteToClient (client,sizeof(xXResQueryClientPixmapBytesReply),(char*)&rep);
300
301    return (client->noClientException);
302}
303
304
305static void
306ResResetProc (ExtensionEntry *extEntry) { }
307
308static int
309ProcResDispatch (ClientPtr client)
310{
311    REQUEST(xReq);
312    switch (stuff->data) {
313    case X_XResQueryVersion:
314        return ProcXResQueryVersion(client);
315    case X_XResQueryClients:
316        return ProcXResQueryClients(client);
317    case X_XResQueryClientResources:
318        return ProcXResQueryClientResources(client);
319    case X_XResQueryClientPixmapBytes:
320        return ProcXResQueryClientPixmapBytes(client);
321    default: break;
322    }
323
324    return BadRequest;
325}
326
327static int
328SProcXResQueryVersion (ClientPtr client)
329{
330    REQUEST(xXResQueryVersionReq);
331    int n;
332
333    REQUEST_SIZE_MATCH (xXResQueryVersionReq);
334    swaps(&stuff->client_major,n);
335    swaps(&stuff->client_minor,n);
336    return ProcXResQueryVersion(client);
337}
338
339static int
340SProcXResQueryClientResources (ClientPtr client)
341{
342    REQUEST(xXResQueryClientResourcesReq);
343    int n;
344
345    REQUEST_SIZE_MATCH (xXResQueryClientResourcesReq);
346    swaps(&stuff->xid,n);
347    return ProcXResQueryClientResources(client);
348}
349
350static int
351SProcXResQueryClientPixmapBytes (ClientPtr client)
352{
353    REQUEST(xXResQueryClientPixmapBytesReq);
354    int n;
355
356    REQUEST_SIZE_MATCH (xXResQueryClientPixmapBytesReq);
357    swaps(&stuff->xid,n);
358    return ProcXResQueryClientPixmapBytes(client);
359}
360
361static int
362SProcResDispatch (ClientPtr client)
363{
364    REQUEST(xReq);
365    int n;
366
367    swaps(&stuff->length,n);
368
369    switch (stuff->data) {
370    case X_XResQueryVersion:
371        return SProcXResQueryVersion(client);
372    case X_XResQueryClients:  /* nothing to swap */
373        return ProcXResQueryClients(client);
374    case X_XResQueryClientResources:
375        return SProcXResQueryClientResources(client);
376    case X_XResQueryClientPixmapBytes:
377        return SProcXResQueryClientPixmapBytes(client);
378    default: break;
379    }
380
381    return BadRequest;
382}
383
384void
385ResExtensionInit(INITARGS)
386{
387    (void) AddExtension(XRES_NAME, 0, 0,
388                            ProcResDispatch, SProcResDispatch,
389                            ResResetProc, StandardMinorOpcode);
390
391    RegisterResourceName(RT_NONE, "NONE");
392    RegisterResourceName(RT_WINDOW, "WINDOW");
393    RegisterResourceName(RT_PIXMAP, "PIXMAP");
394    RegisterResourceName(RT_GC, "GC");
395    RegisterResourceName(RT_FONT, "FONT");
396    RegisterResourceName(RT_CURSOR, "CURSOR");
397    RegisterResourceName(RT_COLORMAP, "COLORMAP");
398    RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY");
399    RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT");
400    RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB");
401}
402