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