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