3 Copyright 1993, 1998 The Open Group
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
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
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.
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
29 * Copyright © 2010, Keith Packard
30 * Copyright © 2010, Jamey Sharp
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.
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
51 #ifdef HAVE_DIX_CONFIG_H
52 #include <dix-config.h>
56 #include "windowstr.h"
60 #include "cursorstr.h"
61 #include "colormapst.h"
63 #include "scrnintstr.h"
64 #include "extnsionst.h"
73 static const Bool xselinux_private[PRIVATE_LAST] = {
74 [PRIVATE_SCREEN] = TRUE,
75 [PRIVATE_CLIENT] = TRUE,
76 [PRIVATE_WINDOW] = TRUE,
77 [PRIVATE_PIXMAP] = TRUE,
79 [PRIVATE_CURSOR] = TRUE,
80 [PRIVATE_COLORMAP] = TRUE,
81 [PRIVATE_DEVICE] = TRUE,
82 [PRIVATE_EXTENSION] = TRUE,
83 [PRIVATE_SELECTION] = TRUE,
84 [PRIVATE_PROPERTY] = TRUE,
85 [PRIVATE_PICTURE] = TRUE,
86 [PRIVATE_GLYPHSET] = TRUE,
89 typedef Bool (*FixupFunc)(PrivatePtr *privates, int offset, unsigned bytes);
92 dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
96 new_privates = realloc(*privates, old_offset + bytes);
99 memset((char *) new_privates + old_offset, '\0', bytes);
100 *privates = new_privates;
105 dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
107 memmove((char *) *privates + bytes, *privates, new_offset - bytes);
108 memset(*privates, '\0', bytes);
113 fixupScreens(FixupFunc fixup, unsigned bytes)
116 for (s = 0; s < screenInfo.numScreens; s++)
117 if (!fixup(&screenInfo.screens[s]->devPrivates, keys[PRIVATE_SCREEN].offset, bytes))
123 fixupServerClient(FixupFunc fixup, unsigned bytes)
126 return fixup(&serverClient->devPrivates, keys[PRIVATE_CLIENT].offset, bytes);
131 fixupExtensions(FixupFunc fixup, unsigned bytes)
134 ExtensionEntry *extension;
135 for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); major++)
136 if (!fixup(&extension->devPrivates, keys[PRIVATE_EXTENSION].offset, bytes))
142 fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
145 for (s = 0; s < screenInfo.numScreens; s++) {
147 dixLookupResourceByType((pointer *) &cmap, screenInfo.screens[s]->defColormap,
148 RT_COLORMAP, serverClient, DixCreateAccess);
149 if (cmap && !fixup(&cmap->devPrivates, keys[PRIVATE_COLORMAP].offset, bytes))
155 static Bool (* const allocated_early[PRIVATE_LAST])(FixupFunc, unsigned) = {
156 [PRIVATE_SCREEN] = fixupScreens,
157 [PRIVATE_CLIENT] = fixupServerClient,
158 [PRIVATE_EXTENSION] = fixupExtensions,
159 [PRIVATE_COLORMAP] = fixupDefaultColormaps,
163 * Register a private key. This takes the type of object the key will
164 * be used with, which may be PRIVATE_ALL indicating that this key
165 * will be used with all of the private objects. If 'size' is
166 * non-zero, then the specified amount of space will be allocated in
167 * the private storage. Otherwise, space for a single pointer will
168 * be allocated which can be set with dixSetPrivate
171 dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
177 if (key->initialized) {
178 assert (size == key->size);
182 /* Compute required space */
185 bytes = sizeof (void *);
187 /* align to void * size */
188 bytes = (bytes + sizeof (void *) - 1) & ~(sizeof (void *) - 1);
190 /* Update offsets for all affected keys */
191 if (type == PRIVATE_XSELINUX) {
194 /* Resize if we can, or make sure nothing's allocated if we can't
196 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
197 if (xselinux_private[t]) {
198 if (!allocated_early[t])
199 assert (!keys[t].created);
200 else if (!allocated_early[t](dixReallocPrivates, bytes))
204 /* Move all existing keys up in the privates space to make
205 * room for this new global key
207 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
208 if (xselinux_private[t]) {
209 for (k = keys[t].key; k; k = k->next)
211 keys[t].offset += bytes;
212 if (allocated_early[t])
213 allocated_early[t](dixMovePrivates, bytes);
219 /* Resize if we can, or make sure nothing's allocated if we can't */
220 if (!allocated_early[type])
221 assert(!keys[type].created);
222 else if (!allocated_early[type](dixReallocPrivates, bytes))
224 offset = keys[type].offset;
225 keys[type].offset += bytes;
229 key->offset = offset;
231 key->initialized = TRUE;
233 key->allocated = FALSE;
234 key->next = keys[type].key;
235 keys[type].key = key;
241 * Allocate a new private key.
243 * This manages the storage of the key object itself, freeing it when the
244 * privates system is restarted at server reset time. All other keys
245 * are expected to be statically allocated as the privates must be
246 * reset after all objects have been freed
249 dixCreatePrivateKey(DevPrivateType type, unsigned size)
253 key = calloc(sizeof (DevPrivateKeyRec), 1);
256 if (!dixRegisterPrivateKey(key, type, size)) {
260 key->allocated = TRUE;
265 * Initialize privates by zeroing them
268 _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
270 keys[type].created++;
271 if (xselinux_private[type])
272 keys[PRIVATE_XSELINUX].created++;
273 if (keys[type].offset == 0)
276 memset(addr, '\0', keys[type].offset);
283 _dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
285 keys[type].created--;
286 if (xselinux_private[type])
287 keys[PRIVATE_XSELINUX].created--;
291 * Allocate new object with privates.
293 * This is expected to be invoked from the
294 * dixAllocateObjectWithPrivates macro
297 _dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, unsigned offset, DevPrivateType type)
302 PrivatePtr *devPrivates;
304 assert (type > PRIVATE_SCREEN && type < PRIVATE_LAST);
306 /* round up so that void * is aligned */
307 baseSize = (baseSize + sizeof (void *) - 1) & ~(sizeof (void *) - 1);
308 totalSize = baseSize + keys[type].offset;
309 object = malloc(totalSize);
313 memset(object, '\0', clear);
314 privates = (PrivatePtr) (((char *) object) + baseSize);
315 devPrivates = (PrivatePtr *) ((char *) object + offset);
317 _dixInitPrivates(devPrivates, privates, type);
323 * Allocate privates separately from containing object.
324 * Used for clients and screens.
327 dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
332 assert (type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
334 size = keys[type].offset;
338 if (!(p = malloc(size)))
342 _dixInitPrivates(privates, p, type);
343 ++keys[type].allocated;
349 * Free an object that has privates
351 * This is expected to be invoked from the
352 * dixFreeObjectWithPrivates macro
355 _dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type)
357 _dixFiniPrivates(privates, type);
362 * Called to free screen or client privates
365 dixFreePrivates(PrivatePtr privates, DevPrivateType type)
367 _dixFiniPrivates(privates, type);
368 --keys[type].allocated;
373 * Return size of privates for the specified type
376 dixPrivatesSize(DevPrivateType type)
378 assert (type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
380 return keys[type].offset;
383 /* Table of devPrivates offsets */
384 static const int offsets[] = {
386 offsetof(WindowRec, devPrivates), /* RT_WINDOW */
387 offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */
388 offsetof(GC, devPrivates), /* RT_GC */
390 offsetof(CursorRec, devPrivates), /* RT_CURSOR */
391 offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
394 #define NUM_OFFSETS (sizeof (offsets) / sizeof (offsets[0]))
397 dixLookupPrivateOffset(RESTYPE type)
400 * Special kludge for DBE which registers a new resource type that
401 * points at pixmaps (thanks, DBE)
403 if (type & RC_DRAWABLE) {
404 if (type == RT_WINDOW)
405 return offsets[RT_WINDOW & TypeMask];
407 return offsets[RT_PIXMAP & TypeMask];
409 type = type & TypeMask;
410 if (type < NUM_OFFSETS)
411 return offsets[type];
415 static const char *key_names[PRIVATE_LAST] = {
416 /* XSELinux uses the same private keys for numerous objects */
417 [PRIVATE_XSELINUX] = "XSELINUX",
419 /* Otherwise, you get a private in just the requested structure
421 /* These can have objects created before all of the keys are registered */
422 [PRIVATE_SCREEN] = "SCREEN",
423 [PRIVATE_EXTENSION] = "EXTENSION",
424 [PRIVATE_COLORMAP] = "COLORMAP",
426 /* These cannot have any objects before all relevant keys are registered */
427 [PRIVATE_DEVICE] = "DEVICE",
428 [PRIVATE_CLIENT] = "CLIENT",
429 [PRIVATE_PROPERTY] = "PROPERTY",
430 [PRIVATE_SELECTION] = "SELECTION",
431 [PRIVATE_WINDOW] = "WINDOW",
432 [PRIVATE_PIXMAP] = "PIXMAP",
434 [PRIVATE_CURSOR] = "CURSOR",
435 [PRIVATE_CURSOR_BITS] = "CURSOR_BITS",
437 /* extension privates */
438 [PRIVATE_DBE_WINDOW] = "DBE_WINDOW",
439 [PRIVATE_DAMAGE] = "DAMAGE",
440 [PRIVATE_GLYPH] = "GLYPH",
441 [PRIVATE_GLYPHSET] = "GLYPHSET",
442 [PRIVATE_PICTURE] = "PICTURE",
443 [PRIVATE_SYNC_FENCE] = "SYNC_FENCE",
447 dixPrivateUsage(void)
454 for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
455 if (keys[t].offset) {
456 ErrorF("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
457 key_names[t], keys[t].created, keys[t].offset, keys[t].created * keys[t].offset,
459 bytes += keys[t].created * keys[t].offset;
460 objects += keys[t].created;
461 alloc += keys[t].allocated;
464 ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n",
465 objects, bytes, alloc);
469 dixResetPrivates(void)
473 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
474 DevPrivateKey key, next;
476 for (key = keys[t].key; key; key = next) {
479 key->initialized = FALSE;
485 if (keys[t].created) {
486 ErrorF("%d %ss still allocated at reset\n",
487 keys[t].created, key_names[t]);
493 keys[t].allocated = 0;