Imported Upstream version 1.15.1
[deb_xorg-server.git] / dix / privates.c
CommitLineData
a09e091a
JB
1/*
2
3Copyright 1993, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28/*
29 * Copyright © 2010, Keith Packard
30 * Copyright © 2010, Jamey Sharp
31 *
32 * Permission to use, copy, modify, distribute, and sell this software and its
33 * documentation for any purpose is hereby granted without fee, provided that
34 * the above copyright notice appear in all copies and that both that copyright
35 * notice and this permission notice appear in supporting documentation, and
36 * that the name of the copyright holders not be used in advertising or
37 * publicity pertaining to distribution of the software without specific,
38 * written prior permission. The copyright holders make no representations
39 * about the suitability of this software for any purpose. It is provided "as
40 * is" without express or implied warranty.
41 *
42 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
44 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
45 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
46 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
47 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
48 * OF THIS SOFTWARE.
49 */
50
51#ifdef HAVE_DIX_CONFIG_H
52#include <dix-config.h>
53#endif
54
55#include <stddef.h>
56#include "windowstr.h"
57#include "resource.h"
58#include "privates.h"
59#include "gcstruct.h"
60#include "cursorstr.h"
61#include "colormapst.h"
62#include "inputstr.h"
63#include "scrnintstr.h"
64#include "extnsionst.h"
65#include "inputstr.h"
66
67static DevPrivateSetRec global_keys[PRIVATE_LAST];
68
69static const Bool xselinux_private[PRIVATE_LAST] = {
70 [PRIVATE_SCREEN] = TRUE,
71 [PRIVATE_CLIENT] = TRUE,
72 [PRIVATE_WINDOW] = TRUE,
73 [PRIVATE_PIXMAP] = TRUE,
74 [PRIVATE_GC] = TRUE,
75 [PRIVATE_CURSOR] = TRUE,
76 [PRIVATE_COLORMAP] = TRUE,
77 [PRIVATE_DEVICE] = TRUE,
78 [PRIVATE_EXTENSION] = TRUE,
79 [PRIVATE_SELECTION] = TRUE,
80 [PRIVATE_PROPERTY] = TRUE,
81 [PRIVATE_PICTURE] = TRUE,
82 [PRIVATE_GLYPHSET] = TRUE,
83};
84
85static const char *key_names[PRIVATE_LAST] = {
86 /* XSELinux uses the same private keys for numerous objects */
87 [PRIVATE_XSELINUX] = "XSELINUX",
88
89 /* Otherwise, you get a private in just the requested structure
90 */
91 /* These can have objects created before all of the keys are registered */
92 [PRIVATE_SCREEN] = "SCREEN",
93 [PRIVATE_EXTENSION] = "EXTENSION",
94 [PRIVATE_COLORMAP] = "COLORMAP",
95 [PRIVATE_DEVICE] = "DEVICE",
96
97 /* These cannot have any objects before all relevant keys are registered */
98 [PRIVATE_CLIENT] = "CLIENT",
99 [PRIVATE_PROPERTY] = "PROPERTY",
100 [PRIVATE_SELECTION] = "SELECTION",
101 [PRIVATE_WINDOW] = "WINDOW",
102 [PRIVATE_PIXMAP] = "PIXMAP",
103 [PRIVATE_GC] = "GC",
104 [PRIVATE_CURSOR] = "CURSOR",
105 [PRIVATE_CURSOR_BITS] = "CURSOR_BITS",
106
107 /* extension privates */
108 [PRIVATE_DAMAGE] = "DAMAGE",
109 [PRIVATE_GLYPH] = "GLYPH",
110 [PRIVATE_GLYPHSET] = "GLYPHSET",
111 [PRIVATE_PICTURE] = "PICTURE",
112 [PRIVATE_SYNC_FENCE] = "SYNC_FENCE",
113};
114
115static const Bool screen_specific_private[PRIVATE_LAST] = {
116 [PRIVATE_SCREEN] = FALSE,
117 [PRIVATE_CLIENT] = FALSE,
118 [PRIVATE_WINDOW] = TRUE,
119 [PRIVATE_PIXMAP] = TRUE,
120 [PRIVATE_GC] = TRUE,
121 [PRIVATE_CURSOR] = FALSE,
122 [PRIVATE_COLORMAP] = FALSE,
123 [PRIVATE_DEVICE] = FALSE,
124 [PRIVATE_EXTENSION] = FALSE,
125 [PRIVATE_SELECTION] = FALSE,
126 [PRIVATE_PROPERTY] = FALSE,
127 [PRIVATE_PICTURE] = TRUE,
128 [PRIVATE_GLYPHSET] = FALSE,
129};
130
131typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes);
132
133typedef enum { FixupMove, FixupRealloc } FixupType;
134
135static Bool
136dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
137{
138 void *new_privates;
139
140 new_privates = realloc(*privates, old_offset + bytes);
141 if (!new_privates)
142 return FALSE;
143 memset((char *) new_privates + old_offset, '\0', bytes);
144 *privates = new_privates;
145 return TRUE;
146}
147
148static Bool
149dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
150{
151 memmove((char *) *privates + bytes, *privates, new_offset - bytes);
152 memset(*privates, '\0', bytes);
153 return TRUE;
154}
155
156static Bool
157fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
158{
159 intptr_t dist;
160 char *old;
161 char *new;
162 DevPrivateKey *keyp, key;
163 DevPrivateType type;
164 int size;
165
166 old = (char *) pScreen->devPrivates;
167 size = global_keys[PRIVATE_SCREEN].offset;
168 if (!fixup (&pScreen->devPrivates, size, bytes))
169 return FALSE;
170
171 /* Screen privates can contain screen-specific private keys
172 * for other types. When they move, the linked list we use to
173 * track them gets scrambled. Fix that by computing the change
174 * in the location of each private adjusting our linked list
175 * pointers to match
176 */
177
178 new = (char *) pScreen->devPrivates;
179
180 /* Moving means everyone shifts up in the privates by 'bytes' amount,
181 * realloc means the base pointer moves
182 */
183 if (fixup == dixMovePrivates)
184 new += bytes;
185
186 dist = new - old;
187
188 if (dist) {
189 for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
190
191 /* Walk the privates list, being careful as the
192 * pointers are scrambled before we patch them.
193 */
194 for (keyp = &pScreen->screenSpecificPrivates[type].key;
195 (key = *keyp) != NULL;
196 keyp = &key->next)
197 {
198
199 /* Only mangle things if the private structure
200 * is contained within the allocation. Privates
201 * stored elsewhere will be left alone
202 */
203 if (old <= (char *) key && (char *) key < old + size)
204 {
205 /* Compute new location of key */
206 key = (DevPrivateKey) ((char *) key + dist);
207
208 /* Patch the list */
209 *keyp = key;
210 }
211 }
212 }
213 return TRUE;
214}
215
216static Bool
217fixupScreens(FixupFunc fixup, unsigned bytes)
218{
219 int s;
220
221 for (s = 0; s < screenInfo.numScreens; s++)
222 if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes))
223 return FALSE;
224
225 for (s = 0; s < screenInfo.numGPUScreens; s++)
226 if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes))
227 return FALSE;
228 return TRUE;
229}
230
231static Bool
232fixupServerClient(FixupFunc fixup, unsigned bytes)
233{
234 if (serverClient)
235 return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset,
236 bytes);
237 return TRUE;
238}
239
240static Bool
241fixupExtensions(FixupFunc fixup, unsigned bytes)
242{
243 unsigned char major;
244 ExtensionEntry *extension;
245
246 for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major));
247 major++)
248 if (!fixup
249 (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes))
250 return FALSE;
251 return TRUE;
252}
253
254static Bool
255fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
256{
257 int s;
258
259 for (s = 0; s < screenInfo.numScreens; s++) {
260 ColormapPtr cmap;
261
262 dixLookupResourceByType((pointer *) &cmap,
263 screenInfo.screens[s]->defColormap, RT_COLORMAP,
264 serverClient, DixCreateAccess);
265 if (cmap &&
266 !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes))
267 return FALSE;
268 }
269 return TRUE;
270}
271
272static Bool
273fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes)
274{
275 while (device) {
276 if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes))
277 return FALSE;
278 device = device->next;
279 }
280 return TRUE;
281}
282
283static Bool
284fixupDevices(FixupFunc fixup, unsigned bytes)
285{
286 return (fixupDeviceList(inputInfo.devices, fixup, bytes) &&
287 fixupDeviceList(inputInfo.off_devices, fixup, bytes));
288}
289
290static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = {
291 [PRIVATE_SCREEN] = fixupScreens,
292 [PRIVATE_CLIENT] = fixupServerClient,
293 [PRIVATE_EXTENSION] = fixupExtensions,
294 [PRIVATE_COLORMAP] = fixupDefaultColormaps,
295 [PRIVATE_DEVICE] = fixupDevices,
296};
297
298static void
299grow_private_set(DevPrivateSetPtr set, unsigned bytes)
300{
301 DevPrivateKey k;
302
303 for (k = set->key; k; k = k->next)
304 k->offset += bytes;
305 set->offset += bytes;
306}
307
308static void
309grow_screen_specific_set(DevPrivateType type, unsigned bytes)
310{
311 int s;
312
313 /* Update offsets for all screen-specific keys */
314 for (s = 0; s < screenInfo.numScreens; s++) {
315 ScreenPtr pScreen = screenInfo.screens[s];
316
317 grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
318 }
319 for (s = 0; s < screenInfo.numGPUScreens; s++) {
320 ScreenPtr pScreen = screenInfo.gpuscreens[s];
321
322 grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
323 }
324}
325
326/*
327 * Register a private key. This takes the type of object the key will
328 * be used with, which may be PRIVATE_ALL indicating that this key
329 * will be used with all of the private objects. If 'size' is
330 * non-zero, then the specified amount of space will be allocated in
331 * the private storage. Otherwise, space for a single pointer will
332 * be allocated which can be set with dixSetPrivate
333 */
334Bool
335dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
336{
337 DevPrivateType t;
338 int offset;
339 unsigned bytes;
340
341 if (key->initialized) {
342 assert(size == key->size);
343 return TRUE;
344 }
345
346 /* Compute required space */
347 bytes = size;
348 if (size == 0)
349 bytes = sizeof(void *);
350
351 /* align to void * size */
352 bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
353
354 /* Update offsets for all affected keys */
355 if (type == PRIVATE_XSELINUX) {
356
357 /* Resize if we can, or make sure nothing's allocated if we can't
358 */
359 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
360 if (xselinux_private[t]) {
361 if (!allocated_early[t])
362 assert(!global_keys[t].created);
363 else if (!allocated_early[t] (dixReallocPrivates, bytes))
364 return FALSE;
365 }
366
367 /* Move all existing keys up in the privates space to make
368 * room for this new global key
369 */
370 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
371 if (xselinux_private[t]) {
372 grow_private_set(&global_keys[t], bytes);
373 grow_screen_specific_set(t, bytes);
374 if (allocated_early[t])
375 allocated_early[t] (dixMovePrivates, bytes);
376 }
377
378 }
379
380 offset = 0;
381 }
382 else {
383 /* Resize if we can, or make sure nothing's allocated if we can't */
384 if (!allocated_early[type])
385 assert(!global_keys[type].created);
386 else if (!allocated_early[type] (dixReallocPrivates, bytes))
387 return FALSE;
388 offset = global_keys[type].offset;
389 global_keys[type].offset += bytes;
390 grow_screen_specific_set(type, bytes);
391 }
392
393 /* Setup this key */
394 key->offset = offset;
395 key->size = size;
396 key->initialized = TRUE;
397 key->type = type;
398 key->allocated = FALSE;
399 key->next = global_keys[type].key;
400 global_keys[type].key = key;
401
402 return TRUE;
403}
404
405Bool
406dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen,
407 DevPrivateType type, unsigned size)
408{
409 DevPrivateKey key;
410
411 if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0))
412 return FALSE;
413 key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey);
414 if (key != NULL) {
415 assert(key->size == size);
416 assert(key->type == type);
417 return TRUE;
418 }
419 key = calloc(sizeof(DevPrivateKeyRec), 1);
420 if (!key)
421 return FALSE;
422 if (!dixRegisterPrivateKey(key, type, size)) {
423 free(key);
424 return FALSE;
425 }
426 key->allocated = TRUE;
427 dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key);
428 return TRUE;
429}
430
431DevPrivateKey
432_dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen)
433{
434 return dixGetPrivate(&pScreen->devPrivates, &key->screenKey);
435}
436
437/*
438 * Initialize privates by zeroing them
439 */
440void
441_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
442{
443 assert (!screen_specific_private[type]);
444
445 global_keys[type].created++;
446 if (xselinux_private[type])
447 global_keys[PRIVATE_XSELINUX].created++;
448 if (global_keys[type].offset == 0)
449 addr = 0;
450 *privates = addr;
451 memset(addr, '\0', global_keys[type].offset);
452}
453
454/*
455 * Clean up privates
456 */
457void
458_dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
459{
460 global_keys[type].created--;
461 if (xselinux_private[type])
462 global_keys[PRIVATE_XSELINUX].created--;
463}
464
465/*
466 * Allocate new object with privates.
467 *
468 * This is expected to be invoked from the
469 * dixAllocateObjectWithPrivates macro
470 */
471void *
472_dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear,
473 unsigned offset, DevPrivateType type)
474{
475 unsigned totalSize;
476 void *object;
477 PrivatePtr privates;
478 PrivatePtr *devPrivates;
479
480 assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
481 assert(!screen_specific_private[type]);
482
483 /* round up so that void * is aligned */
484 baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
485 totalSize = baseSize + global_keys[type].offset;
486 object = malloc(totalSize);
487 if (!object)
488 return NULL;
489
490 memset(object, '\0', clear);
491 privates = (PrivatePtr) (((char *) object) + baseSize);
492 devPrivates = (PrivatePtr *) ((char *) object + offset);
493
494 _dixInitPrivates(devPrivates, privates, type);
495
496 return object;
497}
498
499/*
500 * Allocate privates separately from containing object.
501 * Used for clients and screens.
502 */
503Bool
504dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
505{
506 unsigned size;
507 PrivatePtr p;
508
509 assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
510 assert(!screen_specific_private[type]);
511
512 size = global_keys[type].offset;
513 if (!size) {
514 p = NULL;
515 }
516 else {
517 if (!(p = malloc(size)))
518 return FALSE;
519 }
520
521 _dixInitPrivates(privates, p, type);
522 ++global_keys[type].allocated;
523
524 return TRUE;
525}
526
527/*
528 * Free an object that has privates
529 *
530 * This is expected to be invoked from the
531 * dixFreeObjectWithPrivates macro
532 */
533void
534_dixFreeObjectWithPrivates(void *object, PrivatePtr privates,
535 DevPrivateType type)
536{
537 _dixFiniPrivates(privates, type);
538 free(object);
539}
540
541/*
542 * Called to free screen or client privates
543 */
544void
545dixFreePrivates(PrivatePtr privates, DevPrivateType type)
546{
547 _dixFiniPrivates(privates, type);
548 --global_keys[type].allocated;
549 free(privates);
550}
551
552/*
553 * Return size of privates for the specified type
554 */
555extern _X_EXPORT int
556dixPrivatesSize(DevPrivateType type)
557{
558 assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
559 assert (!screen_specific_private[type]);
560
561 return global_keys[type].offset;
562}
563
564/* Table of devPrivates offsets */
565static const int offsets[] = {
566 -1, /* RT_NONE */
567 offsetof(WindowRec, devPrivates), /* RT_WINDOW */
568 offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */
569 offsetof(GC, devPrivates), /* RT_GC */
570 -1, /* RT_FONT */
571 offsetof(CursorRec, devPrivates), /* RT_CURSOR */
572 offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
573};
574
575#define NUM_OFFSETS (sizeof (offsets) / sizeof (offsets[0]))
576
577int
578dixLookupPrivateOffset(RESTYPE type)
579{
580 /*
581 * Special kludge for DBE which registers a new resource type that
582 * points at pixmaps (thanks, DBE)
583 */
584 if (type & RC_DRAWABLE) {
585 if (type == RT_WINDOW)
586 return offsets[RT_WINDOW & TypeMask];
587 else
588 return offsets[RT_PIXMAP & TypeMask];
589 }
590 type = type & TypeMask;
591 if (type < NUM_OFFSETS)
592 return offsets[type];
593 return -1;
594}
595
596/*
597 * Screen-specific privates
598 */
599
600extern _X_EXPORT Bool
601dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key,
602 DevPrivateType type, unsigned size)
603{
604 int offset;
605 unsigned bytes;
606
607 if (!screen_specific_private[type])
608 FatalError("Attempt to allocate screen-specific private storage for type %s\n",
609 key_names[type]);
610
611 if (key->initialized) {
612 assert(size == key->size);
613 return TRUE;
614 }
615
616 /* Compute required space */
617 bytes = size;
618 if (size == 0)
619 bytes = sizeof(void *);
620
621 /* align to void * size */
622 bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
623
624 assert (!allocated_early[type]);
625 assert (!pScreen->screenSpecificPrivates[type].created);
626 offset = pScreen->screenSpecificPrivates[type].offset;
627 pScreen->screenSpecificPrivates[type].offset += bytes;
628
629 /* Setup this key */
630 key->offset = offset;
631 key->size = size;
632 key->initialized = TRUE;
633 key->type = type;
634 key->allocated = FALSE;
635 key->next = pScreen->screenSpecificPrivates[type].key;
636 pScreen->screenSpecificPrivates[type].key = key;
637
638 return TRUE;
639}
640
641/* Clean up screen-specific privates before CloseScreen */
642void
643dixFreeScreenSpecificPrivates(ScreenPtr pScreen)
644{
645}
646
647/* Initialize screen-specific privates in AddScreen */
648void
649dixInitScreenSpecificPrivates(ScreenPtr pScreen)
650{
651 DevPrivateType t;
652
653 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
654 pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset;
655}
656
657/* Initialize screen-specific privates in AddScreen */
658void
659_dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type)
660{
661 int privates_size;
662 assert (screen_specific_private[type]);
663
664 if (pScreen) {
665 privates_size = pScreen->screenSpecificPrivates[type].offset;
666 pScreen->screenSpecificPrivates[type].created++;
667 }
668 else
669 privates_size = global_keys[type].offset;
670
671 global_keys[type].created++;
672 if (xselinux_private[type])
673 global_keys[PRIVATE_XSELINUX].created++;
674 if (privates_size == 0)
675 addr = 0;
676 *privates = addr;
677 memset(addr, '\0', privates_size);
678}
679
680void *
681_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen,
682 unsigned baseSize,
683 unsigned clear,
684 unsigned offset,
685 DevPrivateType type)
686{
687 unsigned totalSize;
688 void *object;
689 PrivatePtr privates;
690 PrivatePtr *devPrivates;
691 int privates_size;
692
693 assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
694 assert (screen_specific_private[type]);
695
696 if (pScreen)
697 privates_size = pScreen->screenSpecificPrivates[type].offset;
698 else
699 privates_size = global_keys[type].offset;
700 /* round up so that void * is aligned */
701 baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
702 totalSize = baseSize + privates_size;
703 object = malloc(totalSize);
704 if (!object)
705 return NULL;
706
707 memset(object, '\0', clear);
708 privates = (PrivatePtr) (((char *) object) + baseSize);
709 devPrivates = (PrivatePtr *) ((char *) object + offset);
710
711 _dixInitScreenPrivates(pScreen, devPrivates, privates, type);
712
713 return object;
714}
715
716int
717dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type)
718{
719 assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
720
721 if (screen_specific_private[type])
722 return pScreen->screenSpecificPrivates[type].offset;
723 else
724 return global_keys[type].offset;
725}
726
727void
728dixPrivateUsage(void)
729{
730 int objects = 0;
731 int bytes = 0;
732 int alloc = 0;
733 DevPrivateType t;
734
735 for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
736 if (global_keys[t].offset) {
737 ErrorF
738 ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
739 key_names[t], global_keys[t].created, global_keys[t].offset,
740 global_keys[t].created * global_keys[t].offset, global_keys[t].allocated);
741 bytes += global_keys[t].created * global_keys[t].offset;
742 objects += global_keys[t].created;
743 alloc += global_keys[t].allocated;
744 }
745 }
746 ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc);
747}
748
749void
750dixResetPrivates(void)
751{
752 DevPrivateType t;
753
754 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
755 DevPrivateKey key, next;
756
757 for (key = global_keys[t].key; key; key = next) {
758 next = key->next;
759 key->offset = 0;
760 key->initialized = FALSE;
761 key->size = 0;
762 key->type = 0;
763 if (key->allocated)
764 free(key);
765 }
766 if (global_keys[t].created) {
767 ErrorF("%d %ss still allocated at reset\n",
768 global_keys[t].created, key_names[t]);
769 dixPrivateUsage();
770 }
771 global_keys[t].key = NULL;
772 global_keys[t].offset = 0;
773 global_keys[t].created = 0;
774 global_keys[t].allocated = 0;
775 }
776}