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