1 /*
2 Copyright (c) 2002 XFree86 Inc
3 */
5 #ifdef HAVE_DIX_CONFIG_H
6 #include <dix-config.h>
7 #endif
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"
26 static int
27 ProcXResQueryVersion (ClientPtr client)
28 {
29 REQUEST(xXResQueryVersionReq);
30 xXResQueryVersionReply rep;
31 CARD16 client_major, client_minor; /* not used */
33 REQUEST_SIZE_MATCH (xXResQueryVersionReq);
35 client_major = stuff->client_major;
36 client_minor = stuff->client_minor;
37 (void) client_major;
38 (void) client_minor;
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 }
56 static int
57 ProcXResQueryClients (ClientPtr client)
58 {
59 /* REQUEST(xXResQueryClientsReq); */
60 xXResQueryClientsReply rep;
61 int *current_clients;
62 int i, num_clients;
64 REQUEST_SIZE_MATCH(xXResQueryClientsReq);
66 current_clients = malloc(currentMaxClients * sizeof(int));
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 }
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);
88 if(num_clients) {
89 xXResClient scratch;
91 for(i = 0; i < num_clients; i++) {
92 scratch.resource_base = clients[current_clients[i]]->clientAsMask;
93 scratch.resource_mask = RESOURCE_ID_MASK;
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 }
104 free(current_clients);
106 return Success;
107 }
110 static void
111 ResFindAllRes (pointer value, XID id, RESTYPE type, pointer cdata)
112 {
113 int *counts = (int *)cdata;
115 counts[(type & TypeMask) - 1]++;
116 }
118 static int
119 ProcXResQueryClientResources (ClientPtr client)
120 {
121 REQUEST(xXResQueryClientResourcesReq);
122 xXResQueryClientResourcesReply rep;
123 int i, clientID, num_types;
124 int *counts;
126 REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq);
128 clientID = CLIENT_ID(stuff->xid);
130 if((clientID >= currentMaxClients) || !clients[clientID]) {
131 client->errorValue = stuff->xid;
132 return BadValue;
133 }
135 counts = calloc(lastResourceType + 1, sizeof(int));
137 FindAllClientResources(clients[clientID], ResFindAllRes, counts);
139 num_types = 0;
141 for(i = 0; i <= lastResourceType; i++) {
142 if(counts[i]) num_types++;
143 }
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 }
156 WriteToClient (client,sizeof(xXResQueryClientResourcesReply),(char*)&rep);
158 if(num_types) {
159 xXResType scratch;
160 char *name;
162 for(i = 0; i < lastResourceType; i++) {
163 if(!counts[i]) continue;
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 }
174 scratch.count = counts[i];
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 }
185 free(counts);
187 return Success;
188 }
190 static unsigned long
191 ResGetApproxPixmapBytes (PixmapPtr pix)
192 {
193 unsigned long nPixels;
194 int bytesPerPixel;
196 bytesPerPixel = pix->drawable.bitsPerPixel>>3;
197 nPixels = pix->drawable.width * pix->drawable.height;
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 }
205 static void
206 ResFindPixmaps (pointer value, XID id, pointer cdata)
207 {
208 unsigned long *bytes = (unsigned long *)cdata;
209 PixmapPtr pix = (PixmapPtr)value;
211 *bytes += ResGetApproxPixmapBytes(pix);
212 }
214 static void
215 ResFindWindowPixmaps (pointer value, XID id, pointer cdata)
216 {
217 unsigned long *bytes = (unsigned long *)cdata;
218 WindowPtr pWin = (WindowPtr)value;
220 if (pWin->backgroundState == BackgroundPixmap)
221 *bytes += ResGetApproxPixmapBytes(pWin->background.pixmap);
223 if (pWin->border.pixmap != NULL && !pWin->borderIsPixel)
224 *bytes += ResGetApproxPixmapBytes(pWin->border.pixmap);
225 }
227 static void
228 ResFindGCPixmaps (pointer value, XID id, pointer cdata)
229 {
230 unsigned long *bytes = (unsigned long *)cdata;
231 GCPtr pGC = (GCPtr)value;
233 if (pGC->stipple != NULL)
234 *bytes += ResGetApproxPixmapBytes(pGC->stipple);
236 if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel)
237 *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
238 }
240 static int
241 ProcXResQueryClientPixmapBytes (ClientPtr client)
242 {
243 REQUEST(xXResQueryClientPixmapBytesReq);
244 xXResQueryClientPixmapBytesReply rep;
245 int clientID;
246 unsigned long bytes;
248 REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq);
250 clientID = CLIENT_ID(stuff->xid);
252 if((clientID >= currentMaxClients) || !clients[clientID]) {
253 client->errorValue = stuff->xid;
254 return BadValue;
255 }
257 bytes = 0;
259 FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps,
260 (pointer)(&bytes));
262 /*
263 * Make sure win background pixmaps also held to account.
264 */
265 FindClientResourcesByType(clients[clientID], RT_WINDOW,
266 ResFindWindowPixmaps,
267 (pointer)(&bytes));
269 /*
270 * GC Tile & Stipple pixmaps too.
271 */
272 FindClientResourcesByType(clients[clientID], RT_GC,
273 ResFindGCPixmaps,
274 (pointer)(&bytes));
276 #ifdef COMPOSITE
277 /* FIXME: include composite pixmaps too */
278 #endif
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);
298 return Success;
299 }
301 static int
302 ProcResDispatch (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 }
317 return BadRequest;
318 }
320 static int
321 SProcXResQueryVersion (ClientPtr client)
322 {
323 REQUEST(xXResQueryVersionReq);
324 int n;
326 REQUEST_SIZE_MATCH (xXResQueryVersionReq);
327 swaps(&stuff->client_major,n);
328 swaps(&stuff->client_minor,n);
329 return ProcXResQueryVersion(client);
330 }
332 static int
333 SProcXResQueryClientResources (ClientPtr client)
334 {
335 REQUEST(xXResQueryClientResourcesReq);
336 int n;
338 REQUEST_SIZE_MATCH (xXResQueryClientResourcesReq);
339 swaps(&stuff->xid,n);
340 return ProcXResQueryClientResources(client);
341 }
343 static int
344 SProcXResQueryClientPixmapBytes (ClientPtr client)
345 {
346 REQUEST(xXResQueryClientPixmapBytesReq);
347 int n;
349 REQUEST_SIZE_MATCH (xXResQueryClientPixmapBytesReq);
350 swaps(&stuff->xid,n);
351 return ProcXResQueryClientPixmapBytes(client);
352 }
354 static int
355 SProcResDispatch (ClientPtr client)
356 {
357 REQUEST(xReq);
358 int n;
360 swaps(&stuff->length,n);
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 }
374 return BadRequest;
375 }
377 void
378 ResExtensionInit(INITARGS)
379 {
380 (void) AddExtension(XRES_NAME, 0, 0,
381 ProcResDispatch, SProcResDispatch,
382 NULL, StandardMinorOpcode);
383 }