aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix/privates.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix/privates.c')
-rw-r--r--xorg-server/dix/privates.c1019
1 files changed, 517 insertions, 502 deletions
diff --git a/xorg-server/dix/privates.c b/xorg-server/dix/privates.c
index 583b9f1f5..15fbf7590 100644
--- a/xorg-server/dix/privates.c
+++ b/xorg-server/dix/privates.c
@@ -1,502 +1,517 @@
-/*
-
-Copyright 1993, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-/*
- * Copyright © 2010, Keith Packard
- * Copyright © 2010, Jamey Sharp
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stddef.h>
-#include "windowstr.h"
-#include "resource.h"
-#include "privates.h"
-#include "gcstruct.h"
-#include "cursorstr.h"
-#include "colormapst.h"
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "extnsionst.h"
-
-static struct {
- DevPrivateKey key;
- unsigned offset;
- int created;
- int allocated;
-} keys[PRIVATE_LAST];
-
-static const Bool xselinux_private[PRIVATE_LAST] = {
- [PRIVATE_SCREEN] = TRUE,
- [PRIVATE_CLIENT] = TRUE,
- [PRIVATE_WINDOW] = TRUE,
- [PRIVATE_PIXMAP] = TRUE,
- [PRIVATE_GC] = TRUE,
- [PRIVATE_CURSOR] = TRUE,
- [PRIVATE_COLORMAP] = TRUE,
- [PRIVATE_DEVICE] = TRUE,
- [PRIVATE_EXTENSION] = TRUE,
- [PRIVATE_SELECTION] = TRUE,
- [PRIVATE_PROPERTY] = TRUE,
- [PRIVATE_PICTURE] = TRUE,
- [PRIVATE_GLYPHSET] = TRUE,
-};
-
-typedef Bool (*FixupFunc)(PrivatePtr *privates, int offset, unsigned bytes);
-
-static Bool
-dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
-{
- void *new_privates;
-
- new_privates = realloc(*privates, old_offset + bytes);
- if (!new_privates)
- return FALSE;
- memset((char *) new_privates + old_offset, '\0', bytes);
- *privates = new_privates;
- return TRUE;
-}
-
-static Bool
-dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
-{
- memmove((char *) *privates + bytes, *privates, new_offset - bytes);
- memset(*privates, '\0', bytes);
- return TRUE;
-}
-
-static Bool
-fixupScreens(FixupFunc fixup, unsigned bytes)
-{
- int s;
- for (s = 0; s < screenInfo.numScreens; s++)
- if (!fixup(&screenInfo.screens[s]->devPrivates, keys[PRIVATE_SCREEN].offset, bytes))
- return FALSE;
- return TRUE;
-}
-
-static Bool
-fixupServerClient(FixupFunc fixup, unsigned bytes)
-{
- if (serverClient)
- return fixup(&serverClient->devPrivates, keys[PRIVATE_CLIENT].offset, bytes);
- return TRUE;
-}
-
-static Bool
-fixupExtensions(FixupFunc fixup, unsigned bytes)
-{
- unsigned char major;
- ExtensionEntry *extension;
- for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); major++)
- if (!fixup(&extension->devPrivates, keys[PRIVATE_EXTENSION].offset, bytes))
- return FALSE;
- return TRUE;
-}
-
-static Bool
-fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
-{
- int s;
- for (s = 0; s < screenInfo.numScreens; s++) {
- ColormapPtr cmap;
- dixLookupResourceByType((pointer *) &cmap, screenInfo.screens[s]->defColormap,
- RT_COLORMAP, serverClient, DixCreateAccess);
- if (cmap && !fixup(&cmap->devPrivates, keys[PRIVATE_COLORMAP].offset, bytes))
- return FALSE;
- }
- return TRUE;
-}
-
-static Bool (* const allocated_early[PRIVATE_LAST])(FixupFunc, unsigned) = {
- [PRIVATE_SCREEN] = fixupScreens,
- [PRIVATE_CLIENT] = fixupServerClient,
- [PRIVATE_EXTENSION] = fixupExtensions,
- [PRIVATE_COLORMAP] = fixupDefaultColormaps,
-};
-
-/*
- * Register a private key. This takes the type of object the key will
- * be used with, which may be PRIVATE_ALL indicating that this key
- * will be used with all of the private objects. If 'size' is
- * non-zero, then the specified amount of space will be allocated in
- * the private storage. Otherwise, space for a single pointer will
- * be allocated which can be set with dixSetPrivate
- */
-Bool
-dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
-{
- DevPrivateType t;
- int offset;
- unsigned bytes;
-
- if (key->initialized) {
- assert (size == key->size);
- return TRUE;
- }
-
- /* Compute required space */
- bytes = size;
- if (size == 0)
- bytes = sizeof (void *);
-
- /* align to void * size */
- bytes = (bytes + sizeof (void *) - 1) & ~(sizeof (void *) - 1);
-
- /* Update offsets for all affected keys */
- if (type == PRIVATE_XSELINUX) {
- DevPrivateKey k;
-
- /* Resize if we can, or make sure nothing's allocated if we can't
- */
- for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
- if (xselinux_private[t]) {
- if (!allocated_early[t])
- assert (!keys[t].created);
- else if (!allocated_early[t](dixReallocPrivates, bytes))
- return FALSE;
- }
-
- /* Move all existing keys up in the privates space to make
- * room for this new global key
- */
- for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
- if (xselinux_private[t]) {
- for (k = keys[t].key; k; k = k->next)
- k->offset += bytes;
- keys[t].offset += bytes;
- if (allocated_early[t])
- allocated_early[t](dixMovePrivates, bytes);
- }
- }
-
- offset = 0;
- } else {
- /* Resize if we can, or make sure nothing's allocated if we can't */
- if (!allocated_early[type])
- assert(!keys[type].created);
- else if (!allocated_early[type](dixReallocPrivates, bytes))
- return FALSE;
- offset = keys[type].offset;
- keys[type].offset += bytes;
- }
-
- /* Setup this key */
- key->offset = offset;
- key->size = size;
- key->initialized = TRUE;
- key->type = type;
- key->allocated = FALSE;
- key->next = keys[type].key;
- keys[type].key = key;
-
- return TRUE;
-}
-
-Bool
-dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen, DevPrivateType type, unsigned size)
-{
- DevPrivateKey key;
-
- if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0))
- return FALSE;
- key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey);
- if (key != NULL) {
- assert(key->size == size);
- assert(key->type == type);
- return TRUE;
- }
- key = calloc(sizeof (DevPrivateKeyRec), 1);
- if (!key)
- return FALSE;
- if (!dixRegisterPrivateKey(key, type, size)) {
- free(key);
- return FALSE;
- }
- key->allocated = TRUE;
- dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key);
- return TRUE;
-}
-
-DevPrivateKey
-_dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen)
-{
- return dixGetPrivate(&pScreen->devPrivates, &key->screenKey);
-}
-
-/*
- * Initialize privates by zeroing them
- */
-void
-_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
-{
- keys[type].created++;
- if (xselinux_private[type])
- keys[PRIVATE_XSELINUX].created++;
- if (keys[type].offset == 0)
- addr = 0;
- *privates = addr;
- memset(addr, '\0', keys[type].offset);
-}
-
-/*
- * Clean up privates
- */
-void
-_dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
-{
- keys[type].created--;
- if (xselinux_private[type])
- keys[PRIVATE_XSELINUX].created--;
-}
-
-/*
- * Allocate new object with privates.
- *
- * This is expected to be invoked from the
- * dixAllocateObjectWithPrivates macro
- */
-void *
-_dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, unsigned offset, DevPrivateType type)
-{
- unsigned totalSize;
- void *object;
- PrivatePtr privates;
- PrivatePtr *devPrivates;
-
- assert (type > PRIVATE_SCREEN && type < PRIVATE_LAST);
-
- /* round up so that void * is aligned */
- baseSize = (baseSize + sizeof (void *) - 1) & ~(sizeof (void *) - 1);
- totalSize = baseSize + keys[type].offset;
- object = malloc(totalSize);
- if (!object)
- return NULL;
-
- memset(object, '\0', clear);
- privates = (PrivatePtr) (((char *) object) + baseSize);
- devPrivates = (PrivatePtr *) ((char *) object + offset);
-
- _dixInitPrivates(devPrivates, privates, type);
-
- return object;
-}
-
-/*
- * Allocate privates separately from containing object.
- * Used for clients and screens.
- */
-Bool
-dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
-{
- unsigned size;
- PrivatePtr p;
-
- assert (type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
-
- size = keys[type].offset;
- if (!size) {
- p = NULL;
- } else {
- if (!(p = malloc(size)))
- return FALSE;
- }
-
- _dixInitPrivates(privates, p, type);
- ++keys[type].allocated;
-
- return TRUE;
-}
-
-/*
- * Free an object that has privates
- *
- * This is expected to be invoked from the
- * dixFreeObjectWithPrivates macro
- */
-void
-_dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type)
-{
- _dixFiniPrivates(privates, type);
- free(object);
-}
-
-/*
- * Called to free screen or client privates
- */
-void
-dixFreePrivates(PrivatePtr privates, DevPrivateType type)
-{
- _dixFiniPrivates(privates, type);
- --keys[type].allocated;
- free(privates);
-}
-
-/*
- * Return size of privates for the specified type
- */
-extern _X_EXPORT int
-dixPrivatesSize(DevPrivateType type)
-{
- assert (type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
-
- return keys[type].offset;
-}
-
-/* Table of devPrivates offsets */
-static const int offsets[] = {
- -1, /* RT_NONE */
- offsetof(WindowRec, devPrivates), /* RT_WINDOW */
- offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */
- offsetof(GC, devPrivates), /* RT_GC */
- -1, /* RT_FONT */
- offsetof(CursorRec, devPrivates), /* RT_CURSOR */
- offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
-};
-
-#define NUM_OFFSETS (sizeof (offsets) / sizeof (offsets[0]))
-
-int
-dixLookupPrivateOffset(RESTYPE type)
-{
- /*
- * Special kludge for DBE which registers a new resource type that
- * points at pixmaps (thanks, DBE)
- */
- if (type & RC_DRAWABLE) {
- if (type == RT_WINDOW)
- return offsets[RT_WINDOW & TypeMask];
- else
- return offsets[RT_PIXMAP & TypeMask];
- }
- type = type & TypeMask;
- if (type < NUM_OFFSETS)
- return offsets[type];
- return -1;
-}
-
-static const char *key_names[PRIVATE_LAST] = {
- /* XSELinux uses the same private keys for numerous objects */
- [PRIVATE_XSELINUX] = "XSELINUX",
-
- /* Otherwise, you get a private in just the requested structure
- */
- /* These can have objects created before all of the keys are registered */
- [PRIVATE_SCREEN] = "SCREEN",
- [PRIVATE_EXTENSION] = "EXTENSION",
- [PRIVATE_COLORMAP] = "COLORMAP",
-
- /* These cannot have any objects before all relevant keys are registered */
- [PRIVATE_DEVICE] = "DEVICE",
- [PRIVATE_CLIENT] = "CLIENT",
- [PRIVATE_PROPERTY] = "PROPERTY",
- [PRIVATE_SELECTION] = "SELECTION",
- [PRIVATE_WINDOW] = "WINDOW",
- [PRIVATE_PIXMAP] = "PIXMAP",
- [PRIVATE_GC] = "GC",
- [PRIVATE_CURSOR] = "CURSOR",
- [PRIVATE_CURSOR_BITS] = "CURSOR_BITS",
-
- /* extension privates */
- [PRIVATE_DBE_WINDOW] = "DBE_WINDOW",
- [PRIVATE_DAMAGE] = "DAMAGE",
- [PRIVATE_GLYPH] = "GLYPH",
- [PRIVATE_GLYPHSET] = "GLYPHSET",
- [PRIVATE_PICTURE] = "PICTURE",
- [PRIVATE_SYNC_FENCE] = "SYNC_FENCE",
-};
-
-void
-dixPrivateUsage(void)
-{
- int objects = 0;
- int bytes = 0;
- int alloc = 0;
- DevPrivateType t;
-
- for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
- if (keys[t].offset) {
- ErrorF("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
- key_names[t], keys[t].created, keys[t].offset, keys[t].created * keys[t].offset,
- keys[t].allocated);
- bytes += keys[t].created * keys[t].offset;
- objects += keys[t].created;
- alloc += keys[t].allocated;
- }
- }
- ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n",
- objects, bytes, alloc);
-}
-
-void
-dixResetPrivates(void)
-{
- DevPrivateType t;
-
- for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
- DevPrivateKey key, next;
-
- for (key = keys[t].key; key; key = next) {
- next = key->next;
- key->offset = 0;
- key->initialized = FALSE;
- key->size = 0;
- key->type = 0;
- if (key->allocated)
- free(key);
- }
- if (keys[t].created) {
- ErrorF("%d %ss still allocated at reset\n",
- keys[t].created, key_names[t]);
- dixPrivateUsage();
- }
- keys[t].key = NULL;
- keys[t].offset = 0;
- keys[t].created = 0;
- keys[t].allocated = 0;
- }
-}
+/*
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/*
+ * Copyright © 2010, Keith Packard
+ * Copyright © 2010, Jamey Sharp
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stddef.h>
+#include "windowstr.h"
+#include "resource.h"
+#include "privates.h"
+#include "gcstruct.h"
+#include "cursorstr.h"
+#include "colormapst.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "extnsionst.h"
+
+static struct {
+ DevPrivateKey key;
+ unsigned offset;
+ int created;
+ int allocated;
+} keys[PRIVATE_LAST];
+
+static const Bool xselinux_private[PRIVATE_LAST] = {
+ [PRIVATE_SCREEN] = TRUE,
+ [PRIVATE_CLIENT] = TRUE,
+ [PRIVATE_WINDOW] = TRUE,
+ [PRIVATE_PIXMAP] = TRUE,
+ [PRIVATE_GC] = TRUE,
+ [PRIVATE_CURSOR] = TRUE,
+ [PRIVATE_COLORMAP] = TRUE,
+ [PRIVATE_DEVICE] = TRUE,
+ [PRIVATE_EXTENSION] = TRUE,
+ [PRIVATE_SELECTION] = TRUE,
+ [PRIVATE_PROPERTY] = TRUE,
+ [PRIVATE_PICTURE] = TRUE,
+ [PRIVATE_GLYPHSET] = TRUE,
+};
+
+typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes);
+
+static Bool
+dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
+{
+ void *new_privates;
+
+ new_privates = realloc(*privates, old_offset + bytes);
+ if (!new_privates)
+ return FALSE;
+ memset((char *) new_privates + old_offset, '\0', bytes);
+ *privates = new_privates;
+ return TRUE;
+}
+
+static Bool
+dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
+{
+ memmove((char *) *privates + bytes, *privates, new_offset - bytes);
+ memset(*privates, '\0', bytes);
+ return TRUE;
+}
+
+static Bool
+fixupScreens(FixupFunc fixup, unsigned bytes)
+{
+ int s;
+
+ for (s = 0; s < screenInfo.numScreens; s++)
+ if (!fixup
+ (&screenInfo.screens[s]->devPrivates, keys[PRIVATE_SCREEN].offset,
+ bytes))
+ return FALSE;
+ return TRUE;
+}
+
+static Bool
+fixupServerClient(FixupFunc fixup, unsigned bytes)
+{
+ if (serverClient)
+ return fixup(&serverClient->devPrivates, keys[PRIVATE_CLIENT].offset,
+ bytes);
+ return TRUE;
+}
+
+static Bool
+fixupExtensions(FixupFunc fixup, unsigned bytes)
+{
+ unsigned char major;
+ ExtensionEntry *extension;
+
+ for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major));
+ major++)
+ if (!fixup
+ (&extension->devPrivates, keys[PRIVATE_EXTENSION].offset, bytes))
+ return FALSE;
+ return TRUE;
+}
+
+static Bool
+fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
+{
+ int s;
+
+ for (s = 0; s < screenInfo.numScreens; s++) {
+ ColormapPtr cmap;
+
+ dixLookupResourceByType((pointer *) &cmap,
+ screenInfo.screens[s]->defColormap, RT_COLORMAP,
+ serverClient, DixCreateAccess);
+ if (cmap &&
+ !fixup(&cmap->devPrivates, keys[PRIVATE_COLORMAP].offset, bytes))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = {
+[PRIVATE_SCREEN] = fixupScreens,
+ [PRIVATE_CLIENT] = fixupServerClient,
+ [PRIVATE_EXTENSION] = fixupExtensions,
+ [PRIVATE_COLORMAP] = fixupDefaultColormaps,};
+
+/*
+ * Register a private key. This takes the type of object the key will
+ * be used with, which may be PRIVATE_ALL indicating that this key
+ * will be used with all of the private objects. If 'size' is
+ * non-zero, then the specified amount of space will be allocated in
+ * the private storage. Otherwise, space for a single pointer will
+ * be allocated which can be set with dixSetPrivate
+ */
+Bool
+dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
+{
+ DevPrivateType t;
+ int offset;
+ unsigned bytes;
+
+ if (key->initialized) {
+ assert(size == key->size);
+ return TRUE;
+ }
+
+ /* Compute required space */
+ bytes = size;
+ if (size == 0)
+ bytes = sizeof(void *);
+
+ /* align to void * size */
+ bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
+
+ /* Update offsets for all affected keys */
+ if (type == PRIVATE_XSELINUX) {
+ DevPrivateKey k;
+
+ /* Resize if we can, or make sure nothing's allocated if we can't
+ */
+ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
+ if (xselinux_private[t]) {
+ if (!allocated_early[t])
+ assert(!keys[t].created);
+ else if (!allocated_early[t] (dixReallocPrivates, bytes))
+ return FALSE;
+ }
+
+ /* Move all existing keys up in the privates space to make
+ * room for this new global key
+ */
+ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
+ if (xselinux_private[t]) {
+ for (k = keys[t].key; k; k = k->next)
+ k->offset += bytes;
+ keys[t].offset += bytes;
+ if (allocated_early[t])
+ allocated_early[t] (dixMovePrivates, bytes);
+ }
+ }
+
+ offset = 0;
+ }
+ else {
+ /* Resize if we can, or make sure nothing's allocated if we can't */
+ if (!allocated_early[type])
+ assert(!keys[type].created);
+ else if (!allocated_early[type] (dixReallocPrivates, bytes))
+ return FALSE;
+ offset = keys[type].offset;
+ keys[type].offset += bytes;
+ }
+
+ /* Setup this key */
+ key->offset = offset;
+ key->size = size;
+ key->initialized = TRUE;
+ key->type = type;
+ key->allocated = FALSE;
+ key->next = keys[type].key;
+ keys[type].key = key;
+
+ return TRUE;
+}
+
+Bool
+dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen,
+ DevPrivateType type, unsigned size)
+{
+ DevPrivateKey key;
+
+ if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0))
+ return FALSE;
+ key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey);
+ if (key != NULL) {
+ assert(key->size == size);
+ assert(key->type == type);
+ return TRUE;
+ }
+ key = calloc(sizeof(DevPrivateKeyRec), 1);
+ if (!key)
+ return FALSE;
+ if (!dixRegisterPrivateKey(key, type, size)) {
+ free(key);
+ return FALSE;
+ }
+ key->allocated = TRUE;
+ dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key);
+ return TRUE;
+}
+
+DevPrivateKey
+_dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen)
+{
+ return dixGetPrivate(&pScreen->devPrivates, &key->screenKey);
+}
+
+/*
+ * Initialize privates by zeroing them
+ */
+void
+_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
+{
+ keys[type].created++;
+ if (xselinux_private[type])
+ keys[PRIVATE_XSELINUX].created++;
+ if (keys[type].offset == 0)
+ addr = 0;
+ *privates = addr;
+ memset(addr, '\0', keys[type].offset);
+}
+
+/*
+ * Clean up privates
+ */
+void
+_dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
+{
+ keys[type].created--;
+ if (xselinux_private[type])
+ keys[PRIVATE_XSELINUX].created--;
+}
+
+/*
+ * Allocate new object with privates.
+ *
+ * This is expected to be invoked from the
+ * dixAllocateObjectWithPrivates macro
+ */
+void *
+_dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear,
+ unsigned offset, DevPrivateType type)
+{
+ unsigned totalSize;
+ void *object;
+ PrivatePtr privates;
+ PrivatePtr *devPrivates;
+
+ assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
+
+ /* round up so that void * is aligned */
+ baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
+ totalSize = baseSize + keys[type].offset;
+ object = malloc(totalSize);
+ if (!object)
+ return NULL;
+
+ memset(object, '\0', clear);
+ privates = (PrivatePtr) (((char *) object) + baseSize);
+ devPrivates = (PrivatePtr *) ((char *) object + offset);
+
+ _dixInitPrivates(devPrivates, privates, type);
+
+ return object;
+}
+
+/*
+ * Allocate privates separately from containing object.
+ * Used for clients and screens.
+ */
+Bool
+dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
+{
+ unsigned size;
+ PrivatePtr p;
+
+ assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
+
+ size = keys[type].offset;
+ if (!size) {
+ p = NULL;
+ }
+ else {
+ if (!(p = malloc(size)))
+ return FALSE;
+ }
+
+ _dixInitPrivates(privates, p, type);
+ ++keys[type].allocated;
+
+ return TRUE;
+}
+
+/*
+ * Free an object that has privates
+ *
+ * This is expected to be invoked from the
+ * dixFreeObjectWithPrivates macro
+ */
+void
+_dixFreeObjectWithPrivates(void *object, PrivatePtr privates,
+ DevPrivateType type)
+{
+ _dixFiniPrivates(privates, type);
+ free(object);
+}
+
+/*
+ * Called to free screen or client privates
+ */
+void
+dixFreePrivates(PrivatePtr privates, DevPrivateType type)
+{
+ _dixFiniPrivates(privates, type);
+ --keys[type].allocated;
+ free(privates);
+}
+
+/*
+ * Return size of privates for the specified type
+ */
+extern _X_EXPORT int
+dixPrivatesSize(DevPrivateType type)
+{
+ assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
+
+ return keys[type].offset;
+}
+
+/* Table of devPrivates offsets */
+static const int offsets[] = {
+ -1, /* RT_NONE */
+ offsetof(WindowRec, devPrivates), /* RT_WINDOW */
+ offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */
+ offsetof(GC, devPrivates), /* RT_GC */
+ -1, /* RT_FONT */
+ offsetof(CursorRec, devPrivates), /* RT_CURSOR */
+ offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
+};
+
+#define NUM_OFFSETS (sizeof (offsets) / sizeof (offsets[0]))
+
+int
+dixLookupPrivateOffset(RESTYPE type)
+{
+ /*
+ * Special kludge for DBE which registers a new resource type that
+ * points at pixmaps (thanks, DBE)
+ */
+ if (type & RC_DRAWABLE) {
+ if (type == RT_WINDOW)
+ return offsets[RT_WINDOW & TypeMask];
+ else
+ return offsets[RT_PIXMAP & TypeMask];
+ }
+ type = type & TypeMask;
+ if (type < NUM_OFFSETS)
+ return offsets[type];
+ return -1;
+}
+
+static const char *key_names[PRIVATE_LAST] = {
+ /* XSELinux uses the same private keys for numerous objects */
+ [PRIVATE_XSELINUX] = "XSELINUX",
+
+ /* Otherwise, you get a private in just the requested structure
+ */
+ /* These can have objects created before all of the keys are registered */
+ [PRIVATE_SCREEN] = "SCREEN",
+ [PRIVATE_EXTENSION] = "EXTENSION",
+ [PRIVATE_COLORMAP] = "COLORMAP",
+
+ /* These cannot have any objects before all relevant keys are registered */
+ [PRIVATE_DEVICE] = "DEVICE",
+ [PRIVATE_CLIENT] = "CLIENT",
+ [PRIVATE_PROPERTY] = "PROPERTY",
+ [PRIVATE_SELECTION] = "SELECTION",
+ [PRIVATE_WINDOW] = "WINDOW",
+ [PRIVATE_PIXMAP] = "PIXMAP",
+ [PRIVATE_GC] = "GC",
+ [PRIVATE_CURSOR] = "CURSOR",
+ [PRIVATE_CURSOR_BITS] = "CURSOR_BITS",
+
+ /* extension privates */
+ [PRIVATE_DBE_WINDOW] = "DBE_WINDOW",
+ [PRIVATE_DAMAGE] = "DAMAGE",
+ [PRIVATE_GLYPH] = "GLYPH",
+ [PRIVATE_GLYPHSET] = "GLYPHSET",
+ [PRIVATE_PICTURE] = "PICTURE",
+ [PRIVATE_SYNC_FENCE] = "SYNC_FENCE",
+};
+
+void
+dixPrivateUsage(void)
+{
+ int objects = 0;
+ int bytes = 0;
+ int alloc = 0;
+ DevPrivateType t;
+
+ for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
+ if (keys[t].offset) {
+ ErrorF
+ ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
+ key_names[t], keys[t].created, keys[t].offset,
+ keys[t].created * keys[t].offset, keys[t].allocated);
+ bytes += keys[t].created * keys[t].offset;
+ objects += keys[t].created;
+ alloc += keys[t].allocated;
+ }
+ }
+ ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc);
+}
+
+void
+dixResetPrivates(void)
+{
+ DevPrivateType t;
+
+ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
+ DevPrivateKey key, next;
+
+ for (key = keys[t].key; key; key = next) {
+ next = key->next;
+ key->offset = 0;
+ key->initialized = FALSE;
+ key->size = 0;
+ key->type = 0;
+ if (key->allocated)
+ free(key);
+ }
+ if (keys[t].created) {
+ ErrorF("%d %ss still allocated at reset\n",
+ keys[t].created, key_names[t]);
+ dixPrivateUsage();
+ }
+ keys[t].key = NULL;
+ keys[t].offset = 0;
+ keys[t].created = 0;
+ keys[t].allocated = 0;
+ }
+}