xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

privates.c (23009B)


      1 /*
      2 
      3 Copyright 1993, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included
     12 in all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall
     23 not be used in advertising or otherwise to promote the sale, use or
     24 other dealings in this Software without prior written authorization
     25 from 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 
     67 static DevPrivateSetRec global_keys[PRIVATE_LAST];
     68 
     69 static 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 
     85 static 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 
    114 static 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 
    130 typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes);
    131 
    132 typedef enum { FixupMove, FixupRealloc } FixupType;
    133 
    134 static Bool
    135 dixReallocPrivates(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 
    147 static Bool
    148 dixMovePrivates(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 
    155 static Bool
    156 fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
    157 {
    158     uintptr_t       old;
    159     char            *new;
    160     DevPrivateKey   *keyp, key;
    161     DevPrivateType  type;
    162     int             size;
    163 
    164     old = (uintptr_t) pScreen->devPrivates;
    165     size = global_keys[PRIVATE_SCREEN].offset;
    166     if (!fixup (&pScreen->devPrivates, size, bytes))
    167         return FALSE;
    168 
    169     /* Screen privates can contain screen-specific private keys
    170      * for other types. When they move, the linked list we use to
    171      * track them gets scrambled. Fix that by computing the change
    172      * in the location of each private adjusting our linked list
    173      * pointers to match
    174      */
    175 
    176     new = (char *) pScreen->devPrivates;
    177 
    178     /* Moving means everyone shifts up in the privates by 'bytes' amount,
    179      * realloc means the base pointer moves
    180      */
    181     if (fixup == dixMovePrivates)
    182         new += bytes;
    183 
    184     if ((uintptr_t) new != old) {
    185         for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
    186 
    187             /* Walk the privates list, being careful as the
    188              * pointers are scrambled before we patch them.
    189              */
    190             for (keyp = &pScreen->screenSpecificPrivates[type].key;
    191                  (key = *keyp) != NULL;
    192                  keyp = &key->next)
    193             {
    194 
    195                 /* Only mangle things if the private structure
    196                  * is contained within the allocation. Privates
    197                  * stored elsewhere will be left alone
    198                  */
    199                 if (old <= (uintptr_t) key && (uintptr_t) key < old + size)
    200                 {
    201                     /* Compute new location of key (deriving from the new
    202                      * allocation to avoid UB) */
    203                     key = (DevPrivateKey) (new + ((uintptr_t) key - old));
    204 
    205                     /* Patch the list */
    206                     *keyp = key;
    207                 }
    208             }
    209     }
    210     return TRUE;
    211 }
    212 
    213 static Bool
    214 fixupScreens(FixupFunc fixup, unsigned bytes)
    215 {
    216     int s;
    217 
    218     for (s = 0; s < screenInfo.numScreens; s++)
    219         if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes))
    220             return FALSE;
    221 
    222     for (s = 0; s < screenInfo.numGPUScreens; s++)
    223         if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes))
    224             return FALSE;
    225     return TRUE;
    226 }
    227 
    228 static Bool
    229 fixupServerClient(FixupFunc fixup, unsigned bytes)
    230 {
    231     if (serverClient)
    232         return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset,
    233                      bytes);
    234     return TRUE;
    235 }
    236 
    237 static Bool
    238 fixupExtensions(FixupFunc fixup, unsigned bytes)
    239 {
    240     unsigned char major;
    241     ExtensionEntry *extension;
    242 
    243     for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major));
    244          major++)
    245         if (!fixup
    246             (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes))
    247             return FALSE;
    248     return TRUE;
    249 }
    250 
    251 static Bool
    252 fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
    253 {
    254     int s;
    255 
    256     for (s = 0; s < screenInfo.numScreens; s++) {
    257         ColormapPtr cmap;
    258 
    259         dixLookupResourceByType((void **) &cmap,
    260                                 screenInfo.screens[s]->defColormap, RT_COLORMAP,
    261                                 serverClient, DixCreateAccess);
    262         if (cmap &&
    263             !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes))
    264             return FALSE;
    265     }
    266     return TRUE;
    267 }
    268 
    269 static Bool
    270 fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes)
    271 {
    272     while (device) {
    273         if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes))
    274             return FALSE;
    275         device = device->next;
    276     }
    277     return TRUE;
    278 }
    279 
    280 static Bool
    281 fixupDevices(FixupFunc fixup, unsigned bytes)
    282 {
    283     return (fixupDeviceList(inputInfo.devices, fixup, bytes) &&
    284             fixupDeviceList(inputInfo.off_devices, fixup, bytes));
    285 }
    286 
    287 static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = {
    288     [PRIVATE_SCREEN] = fixupScreens,
    289     [PRIVATE_CLIENT] = fixupServerClient,
    290     [PRIVATE_EXTENSION] = fixupExtensions,
    291     [PRIVATE_COLORMAP] = fixupDefaultColormaps,
    292     [PRIVATE_DEVICE] = fixupDevices,
    293 };
    294 
    295 static void
    296 grow_private_set(DevPrivateSetPtr set, unsigned bytes)
    297 {
    298     DevPrivateKey       k;
    299 
    300     for (k = set->key; k; k = k->next)
    301         k->offset += bytes;
    302     set->offset += bytes;
    303 }
    304 
    305 static void
    306 grow_screen_specific_set(DevPrivateType type, unsigned bytes)
    307 {
    308     int s;
    309 
    310     /* Update offsets for all screen-specific keys */
    311     for (s = 0; s < screenInfo.numScreens; s++) {
    312         ScreenPtr       pScreen = screenInfo.screens[s];
    313 
    314         grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
    315     }
    316     for (s = 0; s < screenInfo.numGPUScreens; s++) {
    317         ScreenPtr       pScreen = screenInfo.gpuscreens[s];
    318 
    319         grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
    320     }
    321 }
    322 
    323 /*
    324  * Register a private key. This takes the type of object the key will
    325  * be used with, which may be PRIVATE_ALL indicating that this key
    326  * will be used with all of the private objects. If 'size' is
    327  * non-zero, then the specified amount of space will be allocated in
    328  * the private storage. Otherwise, space for a single pointer will
    329  * be allocated which can be set with dixSetPrivate
    330  */
    331 Bool
    332 dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
    333 {
    334     DevPrivateType t;
    335     int offset;
    336     unsigned bytes;
    337 
    338     if (key->initialized) {
    339         assert(size == key->size);
    340         return TRUE;
    341     }
    342 
    343     /* Compute required space */
    344     bytes = size;
    345     if (size == 0)
    346         bytes = sizeof(void *);
    347 
    348     /* align to pointer size */
    349     bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
    350 
    351     /* Update offsets for all affected keys */
    352     if (type == PRIVATE_XSELINUX) {
    353 
    354         /* Resize if we can, or make sure nothing's allocated if we can't
    355          */
    356         for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
    357             if (xselinux_private[t]) {
    358                 if (!allocated_early[t])
    359                     assert(!global_keys[t].created);
    360                 else if (!allocated_early[t] (dixReallocPrivates, bytes))
    361                     return FALSE;
    362             }
    363 
    364         /* Move all existing keys up in the privates space to make
    365          * room for this new global key
    366          */
    367         for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
    368             if (xselinux_private[t]) {
    369                 grow_private_set(&global_keys[t], bytes);
    370                 grow_screen_specific_set(t, bytes);
    371                 if (allocated_early[t])
    372                     allocated_early[t] (dixMovePrivates, bytes);
    373             }
    374 
    375         }
    376 
    377         offset = 0;
    378     }
    379     else {
    380         /* Resize if we can, or make sure nothing's allocated if we can't */
    381         if (!allocated_early[type])
    382             assert(!global_keys[type].created);
    383         else if (!allocated_early[type] (dixReallocPrivates, bytes))
    384             return FALSE;
    385         offset = global_keys[type].offset;
    386         global_keys[type].offset += bytes;
    387         grow_screen_specific_set(type, bytes);
    388     }
    389 
    390     /* Setup this key */
    391     key->offset = offset;
    392     key->size = size;
    393     key->initialized = TRUE;
    394     key->type = type;
    395     key->allocated = FALSE;
    396     key->next = global_keys[type].key;
    397     global_keys[type].key = key;
    398 
    399     return TRUE;
    400 }
    401 
    402 Bool
    403 dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen,
    404                             DevPrivateType type, unsigned size)
    405 {
    406     DevPrivateKey key;
    407 
    408     if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0))
    409         return FALSE;
    410     key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey);
    411     if (key != NULL) {
    412         assert(key->size == size);
    413         assert(key->type == type);
    414         return TRUE;
    415     }
    416     key = calloc(sizeof(DevPrivateKeyRec), 1);
    417     if (!key)
    418         return FALSE;
    419     if (!dixRegisterPrivateKey(key, type, size)) {
    420         free(key);
    421         return FALSE;
    422     }
    423     key->allocated = TRUE;
    424     dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key);
    425     return TRUE;
    426 }
    427 
    428 DevPrivateKey
    429 _dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen)
    430 {
    431     return dixGetPrivate(&pScreen->devPrivates, &key->screenKey);
    432 }
    433 
    434 /*
    435  * Initialize privates by zeroing them
    436  */
    437 void
    438 _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
    439 {
    440     assert (!screen_specific_private[type]);
    441 
    442     global_keys[type].created++;
    443     if (xselinux_private[type])
    444         global_keys[PRIVATE_XSELINUX].created++;
    445     if (global_keys[type].offset == 0)
    446         addr = 0;
    447     *privates = addr;
    448     if (addr)
    449         memset(addr, '\0', global_keys[type].offset);
    450 }
    451 
    452 /*
    453  * Clean up privates
    454  */
    455 void
    456 _dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
    457 {
    458     global_keys[type].created--;
    459     if (xselinux_private[type])
    460         global_keys[PRIVATE_XSELINUX].created--;
    461 }
    462 
    463 /*
    464  * Allocate new object with privates.
    465  *
    466  * This is expected to be invoked from the
    467  * dixAllocateObjectWithPrivates macro
    468  */
    469 void *
    470 _dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear,
    471                                unsigned offset, DevPrivateType type)
    472 {
    473     unsigned totalSize;
    474     void *object;
    475     PrivatePtr privates;
    476     PrivatePtr *devPrivates;
    477 
    478     assert(type > PRIVATE_SCREEN);
    479     assert(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  */
    502 Bool
    503 dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
    504 {
    505     unsigned size;
    506     PrivatePtr p;
    507 
    508     assert(type > PRIVATE_XSELINUX);
    509     assert(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  */
    533 void
    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  */
    544 void
    545 dixFreePrivates(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  */
    555 extern _X_EXPORT int
    556 dixPrivatesSize(DevPrivateType type)
    557 {
    558     assert(type >= PRIVATE_SCREEN);
    559     assert(type < PRIVATE_LAST);
    560     assert (!screen_specific_private[type]);
    561 
    562     return global_keys[type].offset;
    563 }
    564 
    565 /* Table of devPrivates offsets */
    566 static const int offsets[] = {
    567     -1,                         /* RT_NONE */
    568     offsetof(WindowRec, devPrivates),   /* RT_WINDOW */
    569     offsetof(PixmapRec, devPrivates),   /* RT_PIXMAP */
    570     offsetof(GC, devPrivates),  /* RT_GC */
    571     -1,                         /* RT_FONT */
    572     offsetof(CursorRec, devPrivates),   /* RT_CURSOR */
    573     offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
    574 };
    575 
    576 int
    577 dixLookupPrivateOffset(RESTYPE type)
    578 {
    579     /*
    580      * Special kludge for DBE which registers a new resource type that
    581      * points at pixmaps (thanks, DBE)
    582      */
    583     if (type & RC_DRAWABLE) {
    584         if (type == RT_WINDOW)
    585             return offsets[RT_WINDOW & TypeMask];
    586         else
    587             return offsets[RT_PIXMAP & TypeMask];
    588     }
    589     type = type & TypeMask;
    590     if (type < ARRAY_SIZE(offsets))
    591         return offsets[type];
    592     return -1;
    593 }
    594 
    595 /*
    596  * Screen-specific privates
    597  */
    598 
    599 extern _X_EXPORT Bool
    600 dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key,
    601                                     DevPrivateType type, unsigned size)
    602 {
    603     int offset;
    604     unsigned bytes;
    605 
    606     if (!screen_specific_private[type])
    607         FatalError("Attempt to allocate screen-specific private storage for type %s\n",
    608                    key_names[type]);
    609 
    610     if (key->initialized) {
    611         assert(size == key->size);
    612         return TRUE;
    613     }
    614 
    615     /* Compute required space */
    616     bytes = size;
    617     if (size == 0)
    618         bytes = sizeof(void *);
    619 
    620     /* align to void * size */
    621     bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
    622 
    623     assert (!allocated_early[type]);
    624     assert (!pScreen->screenSpecificPrivates[type].created);
    625     offset = pScreen->screenSpecificPrivates[type].offset;
    626     pScreen->screenSpecificPrivates[type].offset += bytes;
    627 
    628     /* Setup this key */
    629     key->offset = offset;
    630     key->size = size;
    631     key->initialized = TRUE;
    632     key->type = type;
    633     key->allocated = FALSE;
    634     key->next = pScreen->screenSpecificPrivates[type].key;
    635     pScreen->screenSpecificPrivates[type].key = key;
    636 
    637     return TRUE;
    638 }
    639 
    640 /* Clean up screen-specific privates before CloseScreen */
    641 void
    642 dixFreeScreenSpecificPrivates(ScreenPtr pScreen)
    643 {
    644     DevPrivateType t;
    645 
    646     for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
    647         DevPrivateKey key;
    648 
    649         for (key = pScreen->screenSpecificPrivates[t].key; key; key = key->next) {
    650             key->initialized = FALSE;
    651         }
    652     }
    653 }
    654 
    655 /* Initialize screen-specific privates in AddScreen */
    656 void
    657 dixInitScreenSpecificPrivates(ScreenPtr pScreen)
    658 {
    659     DevPrivateType      t;
    660 
    661     for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
    662         pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset;
    663 }
    664 
    665 /* Initialize screen-specific privates in AddScreen */
    666 void
    667 _dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type)
    668 {
    669     int privates_size;
    670     assert (screen_specific_private[type]);
    671 
    672     if (pScreen) {
    673         privates_size = pScreen->screenSpecificPrivates[type].offset;
    674         pScreen->screenSpecificPrivates[type].created++;
    675     }
    676     else
    677         privates_size = global_keys[type].offset;
    678 
    679     global_keys[type].created++;
    680     if (xselinux_private[type])
    681         global_keys[PRIVATE_XSELINUX].created++;
    682     if (privates_size == 0)
    683         addr = 0;
    684     *privates = addr;
    685     if (addr)
    686         memset(addr, '\0', privates_size);
    687 }
    688 
    689 void *
    690 _dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen,
    691                                      unsigned baseSize,
    692                                      unsigned clear,
    693                                      unsigned offset,
    694                                      DevPrivateType type)
    695 {
    696     unsigned totalSize;
    697     void *object;
    698     PrivatePtr privates;
    699     PrivatePtr *devPrivates;
    700     int privates_size;
    701 
    702     assert(type > PRIVATE_SCREEN);
    703     assert(type < PRIVATE_LAST);
    704     assert (screen_specific_private[type]);
    705 
    706     if (pScreen)
    707         privates_size = pScreen->screenSpecificPrivates[type].offset;
    708     else
    709         privates_size = global_keys[type].offset;
    710     /* round up so that pointer is aligned */
    711     baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
    712     totalSize = baseSize + privates_size;
    713     object = malloc(totalSize);
    714     if (!object)
    715         return NULL;
    716 
    717     memset(object, '\0', clear);
    718     privates = (PrivatePtr) (((char *) object) + baseSize);
    719     devPrivates = (PrivatePtr *) ((char *) object + offset);
    720 
    721     _dixInitScreenPrivates(pScreen, devPrivates, privates, type);
    722 
    723     return object;
    724 }
    725 
    726 int
    727 dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type)
    728 {
    729     assert(type >= PRIVATE_SCREEN);
    730     assert(type < PRIVATE_LAST);
    731 
    732     if (screen_specific_private[type])
    733         return pScreen->screenSpecificPrivates[type].offset;
    734     else
    735         return global_keys[type].offset;
    736 }
    737 
    738 void
    739 dixPrivateUsage(void)
    740 {
    741     int objects = 0;
    742     int bytes = 0;
    743     int alloc = 0;
    744     DevPrivateType t;
    745 
    746     for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
    747         if (global_keys[t].offset) {
    748             ErrorF
    749                 ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
    750                  key_names[t], global_keys[t].created, global_keys[t].offset,
    751                  global_keys[t].created * global_keys[t].offset, global_keys[t].allocated);
    752             bytes += global_keys[t].created * global_keys[t].offset;
    753             objects += global_keys[t].created;
    754             alloc += global_keys[t].allocated;
    755         }
    756     }
    757     ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc);
    758 }
    759 
    760 void
    761 dixResetPrivates(void)
    762 {
    763     DevPrivateType t;
    764 
    765     for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
    766         DevPrivateKey key, next;
    767 
    768         for (key = global_keys[t].key; key; key = next) {
    769             next = key->next;
    770             key->offset = 0;
    771             key->initialized = FALSE;
    772             key->size = 0;
    773             key->type = 0;
    774             if (key->allocated)
    775                 free(key);
    776         }
    777         if (global_keys[t].created) {
    778             ErrorF("%d %ss still allocated at reset\n",
    779                    global_keys[t].created, key_names[t]);
    780             dixPrivateUsage();
    781         }
    782         global_keys[t].key = NULL;
    783         global_keys[t].offset = 0;
    784         global_keys[t].created = 0;
    785         global_keys[t].allocated = 0;
    786     }
    787 }
    788 
    789 Bool
    790 dixPrivatesCreated(DevPrivateType type)
    791 {
    792     if (global_keys[type].created)
    793         return TRUE;
    794     else
    795         return FALSE;
    796 }