privates.c revision 1b5d61b8
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_GLYPH] = "GLYPH",
109    [PRIVATE_GLYPHSET] = "GLYPHSET",
110    [PRIVATE_PICTURE] = "PICTURE",
111    [PRIVATE_SYNC_FENCE] = "SYNC_FENCE",
112};
113
114static const Bool screen_specific_private[PRIVATE_LAST] = {
115    [PRIVATE_SCREEN] = FALSE,
116    [PRIVATE_CLIENT] = FALSE,
117    [PRIVATE_WINDOW] = TRUE,
118    [PRIVATE_PIXMAP] = TRUE,
119    [PRIVATE_GC] = TRUE,
120    [PRIVATE_CURSOR] = FALSE,
121    [PRIVATE_COLORMAP] = FALSE,
122    [PRIVATE_DEVICE] = FALSE,
123    [PRIVATE_EXTENSION] = FALSE,
124    [PRIVATE_SELECTION] = FALSE,
125    [PRIVATE_PROPERTY] = FALSE,
126    [PRIVATE_PICTURE] = TRUE,
127    [PRIVATE_GLYPHSET] = FALSE,
128};
129
130typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes);
131
132typedef enum { FixupMove, FixupRealloc } FixupType;
133
134static Bool
135dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
136{
137    void *new_privates;
138
139    new_privates = realloc(*privates, old_offset + bytes);
140    if (!new_privates)
141        return FALSE;
142    memset((char *) new_privates + old_offset, '\0', bytes);
143    *privates = new_privates;
144    return TRUE;
145}
146
147static Bool
148dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
149{
150    memmove((char *) *privates + bytes, *privates, new_offset - bytes);
151    memset(*privates, '\0', bytes);
152    return TRUE;
153}
154
155static Bool
156fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
157{
158    intptr_t        dist;
159    char            *old;
160    char            *new;
161    DevPrivateKey   *keyp, key;
162    DevPrivateType  type;
163    int             size;
164
165    old = (char *) pScreen->devPrivates;
166    size = global_keys[PRIVATE_SCREEN].offset;
167    if (!fixup (&pScreen->devPrivates, size, bytes))
168        return FALSE;
169
170    /* Screen privates can contain screen-specific private keys
171     * for other types. When they move, the linked list we use to
172     * track them gets scrambled. Fix that by computing the change
173     * in the location of each private adjusting our linked list
174     * pointers to match
175     */
176
177    new = (char *) pScreen->devPrivates;
178
179    /* Moving means everyone shifts up in the privates by 'bytes' amount,
180     * realloc means the base pointer moves
181     */
182    if (fixup == dixMovePrivates)
183        new += bytes;
184
185    dist = new - old;
186
187    if (dist) {
188        for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
189
190            /* Walk the privates list, being careful as the
191             * pointers are scrambled before we patch them.
192             */
193            for (keyp = &pScreen->screenSpecificPrivates[type].key;
194                 (key = *keyp) != NULL;
195                 keyp = &key->next)
196            {
197
198                /* Only mangle things if the private structure
199                 * is contained within the allocation. Privates
200                 * stored elsewhere will be left alone
201                 */
202                if (old <= (char *) key && (char *) key < old + size)
203                {
204                    /* Compute new location of key */
205                    key = (DevPrivateKey) ((char *) key + dist);
206
207                    /* Patch the list */
208                    *keyp = key;
209                }
210            }
211    }
212    return TRUE;
213}
214
215static Bool
216fixupScreens(FixupFunc fixup, unsigned bytes)
217{
218    int s;
219
220    for (s = 0; s < screenInfo.numScreens; s++)
221        if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes))
222            return FALSE;
223
224    for (s = 0; s < screenInfo.numGPUScreens; s++)
225        if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes))
226            return FALSE;
227    return TRUE;
228}
229
230static Bool
231fixupServerClient(FixupFunc fixup, unsigned bytes)
232{
233    if (serverClient)
234        return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset,
235                     bytes);
236    return TRUE;
237}
238
239static Bool
240fixupExtensions(FixupFunc fixup, unsigned bytes)
241{
242    unsigned char major;
243    ExtensionEntry *extension;
244
245    for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major));
246         major++)
247        if (!fixup
248            (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes))
249            return FALSE;
250    return TRUE;
251}
252
253static Bool
254fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
255{
256    int s;
257
258    for (s = 0; s < screenInfo.numScreens; s++) {
259        ColormapPtr cmap;
260
261        dixLookupResourceByType((void **) &cmap,
262                                screenInfo.screens[s]->defColormap, RT_COLORMAP,
263                                serverClient, DixCreateAccess);
264        if (cmap &&
265            !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes))
266            return FALSE;
267    }
268    return TRUE;
269}
270
271static Bool
272fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes)
273{
274    while (device) {
275        if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes))
276            return FALSE;
277        device = device->next;
278    }
279    return TRUE;
280}
281
282static Bool
283fixupDevices(FixupFunc fixup, unsigned bytes)
284{
285    return (fixupDeviceList(inputInfo.devices, fixup, bytes) &&
286            fixupDeviceList(inputInfo.off_devices, fixup, bytes));
287}
288
289static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = {
290    [PRIVATE_SCREEN] = fixupScreens,
291    [PRIVATE_CLIENT] = fixupServerClient,
292    [PRIVATE_EXTENSION] = fixupExtensions,
293    [PRIVATE_COLORMAP] = fixupDefaultColormaps,
294    [PRIVATE_DEVICE] = fixupDevices,
295};
296
297static void
298grow_private_set(DevPrivateSetPtr set, unsigned bytes)
299{
300    DevPrivateKey       k;
301
302    for (k = set->key; k; k = k->next)
303        k->offset += bytes;
304    set->offset += bytes;
305}
306
307static void
308grow_screen_specific_set(DevPrivateType type, unsigned bytes)
309{
310    int s;
311
312    /* Update offsets for all screen-specific keys */
313    for (s = 0; s < screenInfo.numScreens; s++) {
314        ScreenPtr       pScreen = screenInfo.screens[s];
315
316        grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
317    }
318    for (s = 0; s < screenInfo.numGPUScreens; s++) {
319        ScreenPtr       pScreen = screenInfo.gpuscreens[s];
320
321        grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
322    }
323}
324
325/*
326 * Register a private key. This takes the type of object the key will
327 * be used with, which may be PRIVATE_ALL indicating that this key
328 * will be used with all of the private objects. If 'size' is
329 * non-zero, then the specified amount of space will be allocated in
330 * the private storage. Otherwise, space for a single pointer will
331 * be allocated which can be set with dixSetPrivate
332 */
333Bool
334dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
335{
336    DevPrivateType t;
337    int offset;
338    unsigned bytes;
339
340    if (key->initialized) {
341        assert(size == key->size);
342        return TRUE;
343    }
344
345    /* Compute required space */
346    bytes = size;
347    if (size == 0)
348        bytes = sizeof(void *);
349
350    /* align to pointer size */
351    bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
352
353    /* Update offsets for all affected keys */
354    if (type == PRIVATE_XSELINUX) {
355
356        /* Resize if we can, or make sure nothing's allocated if we can't
357         */
358        for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
359            if (xselinux_private[t]) {
360                if (!allocated_early[t])
361                    assert(!global_keys[t].created);
362                else if (!allocated_early[t] (dixReallocPrivates, bytes))
363                    return FALSE;
364            }
365
366        /* Move all existing keys up in the privates space to make
367         * room for this new global key
368         */
369        for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
370            if (xselinux_private[t]) {
371                grow_private_set(&global_keys[t], bytes);
372                grow_screen_specific_set(t, bytes);
373                if (allocated_early[t])
374                    allocated_early[t] (dixMovePrivates, bytes);
375            }
376
377        }
378
379        offset = 0;
380    }
381    else {
382        /* Resize if we can, or make sure nothing's allocated if we can't */
383        if (!allocated_early[type])
384            assert(!global_keys[type].created);
385        else if (!allocated_early[type] (dixReallocPrivates, bytes))
386            return FALSE;
387        offset = global_keys[type].offset;
388        global_keys[type].offset += bytes;
389        grow_screen_specific_set(type, bytes);
390    }
391
392    /* Setup this key */
393    key->offset = offset;
394    key->size = size;
395    key->initialized = TRUE;
396    key->type = type;
397    key->allocated = FALSE;
398    key->next = global_keys[type].key;
399    global_keys[type].key = key;
400
401    return TRUE;
402}
403
404Bool
405dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen,
406                            DevPrivateType type, unsigned size)
407{
408    DevPrivateKey key;
409
410    if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0))
411        return FALSE;
412    key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey);
413    if (key != NULL) {
414        assert(key->size == size);
415        assert(key->type == type);
416        return TRUE;
417    }
418    key = calloc(sizeof(DevPrivateKeyRec), 1);
419    if (!key)
420        return FALSE;
421    if (!dixRegisterPrivateKey(key, type, size)) {
422        free(key);
423        return FALSE;
424    }
425    key->allocated = TRUE;
426    dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key);
427    return TRUE;
428}
429
430DevPrivateKey
431_dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen)
432{
433    return dixGetPrivate(&pScreen->devPrivates, &key->screenKey);
434}
435
436/*
437 * Initialize privates by zeroing them
438 */
439void
440_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
441{
442    assert (!screen_specific_private[type]);
443
444    global_keys[type].created++;
445    if (xselinux_private[type])
446        global_keys[PRIVATE_XSELINUX].created++;
447    if (global_keys[type].offset == 0)
448        addr = 0;
449    *privates = addr;
450    memset(addr, '\0', global_keys[type].offset);
451}
452
453/*
454 * Clean up privates
455 */
456void
457_dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
458{
459    global_keys[type].created--;
460    if (xselinux_private[type])
461        global_keys[PRIVATE_XSELINUX].created--;
462}
463
464/*
465 * Allocate new object with privates.
466 *
467 * This is expected to be invoked from the
468 * dixAllocateObjectWithPrivates macro
469 */
470void *
471_dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear,
472                               unsigned offset, DevPrivateType type)
473{
474    unsigned totalSize;
475    void *object;
476    PrivatePtr privates;
477    PrivatePtr *devPrivates;
478
479    assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
480    assert(!screen_specific_private[type]);
481
482    /* round up so that void * is aligned */
483    baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
484    totalSize = baseSize + global_keys[type].offset;
485    object = malloc(totalSize);
486    if (!object)
487        return NULL;
488
489    memset(object, '\0', clear);
490    privates = (PrivatePtr) (((char *) object) + baseSize);
491    devPrivates = (PrivatePtr *) ((char *) object + offset);
492
493    _dixInitPrivates(devPrivates, privates, type);
494
495    return object;
496}
497
498/*
499 * Allocate privates separately from containing object.
500 * Used for clients and screens.
501 */
502Bool
503dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
504{
505    unsigned size;
506    PrivatePtr p;
507
508    assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
509    assert(!screen_specific_private[type]);
510
511    size = global_keys[type].offset;
512    if (!size) {
513        p = NULL;
514    }
515    else {
516        if (!(p = malloc(size)))
517            return FALSE;
518    }
519
520    _dixInitPrivates(privates, p, type);
521    ++global_keys[type].allocated;
522
523    return TRUE;
524}
525
526/*
527 * Free an object that has privates
528 *
529 * This is expected to be invoked from the
530 * dixFreeObjectWithPrivates macro
531 */
532void
533_dixFreeObjectWithPrivates(void *object, PrivatePtr privates,
534                           DevPrivateType type)
535{
536    _dixFiniPrivates(privates, type);
537    free(object);
538}
539
540/*
541 * Called to free screen or client privates
542 */
543void
544dixFreePrivates(PrivatePtr privates, DevPrivateType type)
545{
546    _dixFiniPrivates(privates, type);
547    --global_keys[type].allocated;
548    free(privates);
549}
550
551/*
552 * Return size of privates for the specified type
553 */
554extern _X_EXPORT int
555dixPrivatesSize(DevPrivateType type)
556{
557    assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
558    assert (!screen_specific_private[type]);
559
560    return global_keys[type].offset;
561}
562
563/* Table of devPrivates offsets */
564static const int offsets[] = {
565    -1,                         /* RT_NONE */
566    offsetof(WindowRec, devPrivates),   /* RT_WINDOW */
567    offsetof(PixmapRec, devPrivates),   /* RT_PIXMAP */
568    offsetof(GC, devPrivates),  /* RT_GC */
569    -1,                         /* RT_FONT */
570    offsetof(CursorRec, devPrivates),   /* RT_CURSOR */
571    offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
572};
573
574int
575dixLookupPrivateOffset(RESTYPE type)
576{
577    /*
578     * Special kludge for DBE which registers a new resource type that
579     * points at pixmaps (thanks, DBE)
580     */
581    if (type & RC_DRAWABLE) {
582        if (type == RT_WINDOW)
583            return offsets[RT_WINDOW & TypeMask];
584        else
585            return offsets[RT_PIXMAP & TypeMask];
586    }
587    type = type & TypeMask;
588    if (type < ARRAY_SIZE(offsets))
589        return offsets[type];
590    return -1;
591}
592
593/*
594 * Screen-specific privates
595 */
596
597extern _X_EXPORT Bool
598dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key,
599                                    DevPrivateType type, unsigned size)
600{
601    int offset;
602    unsigned bytes;
603
604    if (!screen_specific_private[type])
605        FatalError("Attempt to allocate screen-specific private storage for type %s\n",
606                   key_names[type]);
607
608    if (key->initialized) {
609        assert(size == key->size);
610        return TRUE;
611    }
612
613    /* Compute required space */
614    bytes = size;
615    if (size == 0)
616        bytes = sizeof(void *);
617
618    /* align to void * size */
619    bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
620
621    assert (!allocated_early[type]);
622    assert (!pScreen->screenSpecificPrivates[type].created);
623    offset = pScreen->screenSpecificPrivates[type].offset;
624    pScreen->screenSpecificPrivates[type].offset += bytes;
625
626    /* Setup this key */
627    key->offset = offset;
628    key->size = size;
629    key->initialized = TRUE;
630    key->type = type;
631    key->allocated = FALSE;
632    key->next = pScreen->screenSpecificPrivates[type].key;
633    pScreen->screenSpecificPrivates[type].key = key;
634
635    return TRUE;
636}
637
638/* Clean up screen-specific privates before CloseScreen */
639void
640dixFreeScreenSpecificPrivates(ScreenPtr pScreen)
641{
642    DevPrivateType t;
643
644    for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
645        DevPrivateKey key;
646
647        for (key = pScreen->screenSpecificPrivates[t].key; key; key = key->next) {
648            key->initialized = FALSE;
649        }
650    }
651}
652
653/* Initialize screen-specific privates in AddScreen */
654void
655dixInitScreenSpecificPrivates(ScreenPtr pScreen)
656{
657    DevPrivateType      t;
658
659    for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
660        pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset;
661}
662
663/* Initialize screen-specific privates in AddScreen */
664void
665_dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type)
666{
667    int privates_size;
668    assert (screen_specific_private[type]);
669
670    if (pScreen) {
671        privates_size = pScreen->screenSpecificPrivates[type].offset;
672        pScreen->screenSpecificPrivates[type].created++;
673    }
674    else
675        privates_size = global_keys[type].offset;
676
677    global_keys[type].created++;
678    if (xselinux_private[type])
679        global_keys[PRIVATE_XSELINUX].created++;
680    if (privates_size == 0)
681        addr = 0;
682    *privates = addr;
683    memset(addr, '\0', privates_size);
684}
685
686void *
687_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen,
688                                     unsigned baseSize,
689                                     unsigned clear,
690                                     unsigned offset,
691                                     DevPrivateType type)
692{
693    unsigned totalSize;
694    void *object;
695    PrivatePtr privates;
696    PrivatePtr *devPrivates;
697    int privates_size;
698
699    assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
700    assert (screen_specific_private[type]);
701
702    if (pScreen)
703        privates_size = pScreen->screenSpecificPrivates[type].offset;
704    else
705        privates_size = global_keys[type].offset;
706    /* round up so that pointer is aligned */
707    baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
708    totalSize = baseSize + privates_size;
709    object = malloc(totalSize);
710    if (!object)
711        return NULL;
712
713    memset(object, '\0', clear);
714    privates = (PrivatePtr) (((char *) object) + baseSize);
715    devPrivates = (PrivatePtr *) ((char *) object + offset);
716
717    _dixInitScreenPrivates(pScreen, devPrivates, privates, type);
718
719    return object;
720}
721
722int
723dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type)
724{
725    assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
726
727    if (screen_specific_private[type])
728        return pScreen->screenSpecificPrivates[type].offset;
729    else
730        return global_keys[type].offset;
731}
732
733void
734dixPrivateUsage(void)
735{
736    int objects = 0;
737    int bytes = 0;
738    int alloc = 0;
739    DevPrivateType t;
740
741    for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
742        if (global_keys[t].offset) {
743            ErrorF
744                ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
745                 key_names[t], global_keys[t].created, global_keys[t].offset,
746                 global_keys[t].created * global_keys[t].offset, global_keys[t].allocated);
747            bytes += global_keys[t].created * global_keys[t].offset;
748            objects += global_keys[t].created;
749            alloc += global_keys[t].allocated;
750        }
751    }
752    ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc);
753}
754
755void
756dixResetPrivates(void)
757{
758    DevPrivateType t;
759
760    for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
761        DevPrivateKey key, next;
762
763        for (key = global_keys[t].key; key; key = next) {
764            next = key->next;
765            key->offset = 0;
766            key->initialized = FALSE;
767            key->size = 0;
768            key->type = 0;
769            if (key->allocated)
770                free(key);
771        }
772        if (global_keys[t].created) {
773            ErrorF("%d %ss still allocated at reset\n",
774                   global_keys[t].created, key_names[t]);
775            dixPrivateUsage();
776        }
777        global_keys[t].key = NULL;
778        global_keys[t].offset = 0;
779        global_keys[t].created = 0;
780        global_keys[t].allocated = 0;
781    }
782}
783
784Bool
785dixPrivatesCreated(DevPrivateType type)
786{
787    if (global_keys[type].created)
788        return TRUE;
789    else
790        return FALSE;
791}
792