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"
67 static DevPrivateSetRec global_keys
[PRIVATE_LAST
];
69 static const Bool xselinux_private
[PRIVATE_LAST
] = {
70 [PRIVATE_SCREEN
] = TRUE
,
71 [PRIVATE_CLIENT
] = TRUE
,
72 [PRIVATE_WINDOW
] = TRUE
,
73 [PRIVATE_PIXMAP
] = 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
,
85 static const char *key_names
[PRIVATE_LAST
] = {
86 /* XSELinux uses the same private keys for numerous objects */
87 [PRIVATE_XSELINUX
] = "XSELINUX",
89 /* Otherwise, you get a private in just the requested structure
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",
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",
104 [PRIVATE_CURSOR
] = "CURSOR",
105 [PRIVATE_CURSOR_BITS
] = "CURSOR_BITS",
107 /* extension privates */
108 [PRIVATE_DAMAGE
] = "DAMAGE",
109 [PRIVATE_GLYPH
] = "GLYPH",
110 [PRIVATE_GLYPHSET
] = "GLYPHSET",
111 [PRIVATE_PICTURE
] = "PICTURE",
112 [PRIVATE_SYNC_FENCE
] = "SYNC_FENCE",
115 static const Bool screen_specific_private
[PRIVATE_LAST
] = {
116 [PRIVATE_SCREEN
] = FALSE
,
117 [PRIVATE_CLIENT
] = FALSE
,
118 [PRIVATE_WINDOW
] = TRUE
,
119 [PRIVATE_PIXMAP
] = TRUE
,
121 [PRIVATE_CURSOR
] = FALSE
,
122 [PRIVATE_COLORMAP
] = FALSE
,
123 [PRIVATE_DEVICE
] = FALSE
,
124 [PRIVATE_EXTENSION
] = FALSE
,
125 [PRIVATE_SELECTION
] = FALSE
,
126 [PRIVATE_PROPERTY
] = FALSE
,
127 [PRIVATE_PICTURE
] = TRUE
,
128 [PRIVATE_GLYPHSET
] = FALSE
,
131 typedef Bool (*FixupFunc
) (PrivatePtr
*privates
, int offset
, unsigned bytes
);
133 typedef enum { FixupMove
, FixupRealloc
} FixupType
;
136 dixReallocPrivates(PrivatePtr
*privates
, int old_offset
, unsigned bytes
)
140 new_privates
= realloc(*privates
, old_offset
+ bytes
);
143 memset((char *) new_privates
+ old_offset
, '\0', bytes
);
144 *privates
= new_privates
;
149 dixMovePrivates(PrivatePtr
*privates
, int new_offset
, unsigned bytes
)
151 memmove((char *) *privates
+ bytes
, *privates
, new_offset
- bytes
);
152 memset(*privates
, '\0', bytes
);
157 fixupOneScreen(ScreenPtr pScreen
, FixupFunc fixup
, unsigned bytes
)
162 DevPrivateKey
*keyp
, key
;
166 old
= (char *) pScreen
->devPrivates
;
167 size
= global_keys
[PRIVATE_SCREEN
].offset
;
168 if (!fixup (&pScreen
->devPrivates
, size
, bytes
))
171 /* Screen privates can contain screen-specific private keys
172 * for other types. When they move, the linked list we use to
173 * track them gets scrambled. Fix that by computing the change
174 * in the location of each private adjusting our linked list
178 new = (char *) pScreen
->devPrivates
;
180 /* Moving means everyone shifts up in the privates by 'bytes' amount,
181 * realloc means the base pointer moves
183 if (fixup
== dixMovePrivates
)
189 for (type
= PRIVATE_XSELINUX
; type
< PRIVATE_LAST
; type
++)
191 /* Walk the privates list, being careful as the
192 * pointers are scrambled before we patch them.
194 for (keyp
= &pScreen
->screenSpecificPrivates
[type
].key
;
195 (key
= *keyp
) != NULL
;
199 /* Only mangle things if the private structure
200 * is contained within the allocation. Privates
201 * stored elsewhere will be left alone
203 if (old
<= (char *) key
&& (char *) key
< old
+ size
)
205 /* Compute new location of key */
206 key
= (DevPrivateKey
) ((char *) key
+ dist
);
217 fixupScreens(FixupFunc fixup
, unsigned bytes
)
221 for (s
= 0; s
< screenInfo
.numScreens
; s
++)
222 if (!fixupOneScreen (screenInfo
.screens
[s
], fixup
, bytes
))
225 for (s
= 0; s
< screenInfo
.numGPUScreens
; s
++)
226 if (!fixupOneScreen (screenInfo
.gpuscreens
[s
], fixup
, bytes
))
232 fixupServerClient(FixupFunc fixup
, unsigned bytes
)
235 return fixup(&serverClient
->devPrivates
, global_keys
[PRIVATE_CLIENT
].offset
,
241 fixupExtensions(FixupFunc fixup
, unsigned bytes
)
244 ExtensionEntry
*extension
;
246 for (major
= EXTENSION_BASE
; (extension
= GetExtensionEntry(major
));
249 (&extension
->devPrivates
, global_keys
[PRIVATE_EXTENSION
].offset
, bytes
))
255 fixupDefaultColormaps(FixupFunc fixup
, unsigned bytes
)
259 for (s
= 0; s
< screenInfo
.numScreens
; s
++) {
262 dixLookupResourceByType((pointer
*) &cmap
,
263 screenInfo
.screens
[s
]->defColormap
, RT_COLORMAP
,
264 serverClient
, DixCreateAccess
);
266 !fixup(&cmap
->devPrivates
, screenInfo
.screens
[s
]->screenSpecificPrivates
[PRIVATE_COLORMAP
].offset
, bytes
))
273 fixupDeviceList(DeviceIntPtr device
, FixupFunc fixup
, unsigned bytes
)
276 if (!fixup(&device
->devPrivates
, global_keys
[PRIVATE_DEVICE
].offset
, bytes
))
278 device
= device
->next
;
284 fixupDevices(FixupFunc fixup
, unsigned bytes
)
286 return (fixupDeviceList(inputInfo
.devices
, fixup
, bytes
) &&
287 fixupDeviceList(inputInfo
.off_devices
, fixup
, bytes
));
290 static Bool (*const allocated_early
[PRIVATE_LAST
]) (FixupFunc
, unsigned) = {
291 [PRIVATE_SCREEN
] = fixupScreens
,
292 [PRIVATE_CLIENT
] = fixupServerClient
,
293 [PRIVATE_EXTENSION
] = fixupExtensions
,
294 [PRIVATE_COLORMAP
] = fixupDefaultColormaps
,
295 [PRIVATE_DEVICE
] = fixupDevices
,
299 grow_private_set(DevPrivateSetPtr set
, unsigned bytes
)
303 for (k
= set
->key
; k
; k
= k
->next
)
305 set
->offset
+= bytes
;
309 grow_screen_specific_set(DevPrivateType type
, unsigned bytes
)
313 /* Update offsets for all screen-specific keys */
314 for (s
= 0; s
< screenInfo
.numScreens
; s
++) {
315 ScreenPtr pScreen
= screenInfo
.screens
[s
];
317 grow_private_set(&pScreen
->screenSpecificPrivates
[type
], bytes
);
319 for (s
= 0; s
< screenInfo
.numGPUScreens
; s
++) {
320 ScreenPtr pScreen
= screenInfo
.gpuscreens
[s
];
322 grow_private_set(&pScreen
->screenSpecificPrivates
[type
], bytes
);
327 * Register a private key. This takes the type of object the key will
328 * be used with, which may be PRIVATE_ALL indicating that this key
329 * will be used with all of the private objects. If 'size' is
330 * non-zero, then the specified amount of space will be allocated in
331 * the private storage. Otherwise, space for a single pointer will
332 * be allocated which can be set with dixSetPrivate
335 dixRegisterPrivateKey(DevPrivateKey key
, DevPrivateType type
, unsigned size
)
341 if (key
->initialized
) {
342 assert(size
== key
->size
);
346 /* Compute required space */
349 bytes
= sizeof(void *);
351 /* align to void * size */
352 bytes
= (bytes
+ sizeof(void *) - 1) & ~(sizeof(void *) - 1);
354 /* Update offsets for all affected keys */
355 if (type
== PRIVATE_XSELINUX
) {
357 /* Resize if we can, or make sure nothing's allocated if we can't
359 for (t
= PRIVATE_XSELINUX
; t
< PRIVATE_LAST
; t
++)
360 if (xselinux_private
[t
]) {
361 if (!allocated_early
[t
])
362 assert(!global_keys
[t
].created
);
363 else if (!allocated_early
[t
] (dixReallocPrivates
, bytes
))
367 /* Move all existing keys up in the privates space to make
368 * room for this new global key
370 for (t
= PRIVATE_XSELINUX
; t
< PRIVATE_LAST
; t
++) {
371 if (xselinux_private
[t
]) {
372 grow_private_set(&global_keys
[t
], bytes
);
373 grow_screen_specific_set(t
, bytes
);
374 if (allocated_early
[t
])
375 allocated_early
[t
] (dixMovePrivates
, bytes
);
383 /* Resize if we can, or make sure nothing's allocated if we can't */
384 if (!allocated_early
[type
])
385 assert(!global_keys
[type
].created
);
386 else if (!allocated_early
[type
] (dixReallocPrivates
, bytes
))
388 offset
= global_keys
[type
].offset
;
389 global_keys
[type
].offset
+= bytes
;
390 grow_screen_specific_set(type
, bytes
);
394 key
->offset
= offset
;
396 key
->initialized
= TRUE
;
398 key
->allocated
= FALSE
;
399 key
->next
= global_keys
[type
].key
;
400 global_keys
[type
].key
= key
;
406 dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey
, ScreenPtr pScreen
,
407 DevPrivateType type
, unsigned size
)
411 if (!dixRegisterPrivateKey(&screenKey
->screenKey
, PRIVATE_SCREEN
, 0))
413 key
= dixGetPrivate(&pScreen
->devPrivates
, &screenKey
->screenKey
);
415 assert(key
->size
== size
);
416 assert(key
->type
== type
);
419 key
= calloc(sizeof(DevPrivateKeyRec
), 1);
422 if (!dixRegisterPrivateKey(key
, type
, size
)) {
426 key
->allocated
= TRUE
;
427 dixSetPrivate(&pScreen
->devPrivates
, &screenKey
->screenKey
, key
);
432 _dixGetScreenPrivateKey(const DevScreenPrivateKey key
, ScreenPtr pScreen
)
434 return dixGetPrivate(&pScreen
->devPrivates
, &key
->screenKey
);
438 * Initialize privates by zeroing them
441 _dixInitPrivates(PrivatePtr
*privates
, void *addr
, DevPrivateType type
)
443 assert (!screen_specific_private
[type
]);
445 global_keys
[type
].created
++;
446 if (xselinux_private
[type
])
447 global_keys
[PRIVATE_XSELINUX
].created
++;
448 if (global_keys
[type
].offset
== 0)
451 memset(addr
, '\0', global_keys
[type
].offset
);
458 _dixFiniPrivates(PrivatePtr privates
, DevPrivateType type
)
460 global_keys
[type
].created
--;
461 if (xselinux_private
[type
])
462 global_keys
[PRIVATE_XSELINUX
].created
--;
466 * Allocate new object with privates.
468 * This is expected to be invoked from the
469 * dixAllocateObjectWithPrivates macro
472 _dixAllocateObjectWithPrivates(unsigned baseSize
, unsigned clear
,
473 unsigned offset
, DevPrivateType type
)
478 PrivatePtr
*devPrivates
;
480 assert(type
> PRIVATE_SCREEN
&& type
< PRIVATE_LAST
);
481 assert(!screen_specific_private
[type
]);
483 /* round up so that void * is aligned */
484 baseSize
= (baseSize
+ sizeof(void *) - 1) & ~(sizeof(void *) - 1);
485 totalSize
= baseSize
+ global_keys
[type
].offset
;
486 object
= malloc(totalSize
);
490 memset(object
, '\0', clear
);
491 privates
= (PrivatePtr
) (((char *) object
) + baseSize
);
492 devPrivates
= (PrivatePtr
*) ((char *) object
+ offset
);
494 _dixInitPrivates(devPrivates
, privates
, type
);
500 * Allocate privates separately from containing object.
501 * Used for clients and screens.
504 dixAllocatePrivates(PrivatePtr
*privates
, DevPrivateType type
)
509 assert(type
> PRIVATE_XSELINUX
&& type
< PRIVATE_LAST
);
510 assert(!screen_specific_private
[type
]);
512 size
= global_keys
[type
].offset
;
517 if (!(p
= malloc(size
)))
521 _dixInitPrivates(privates
, p
, type
);
522 ++global_keys
[type
].allocated
;
528 * Free an object that has privates
530 * This is expected to be invoked from the
531 * dixFreeObjectWithPrivates macro
534 _dixFreeObjectWithPrivates(void *object
, PrivatePtr privates
,
537 _dixFiniPrivates(privates
, type
);
542 * Called to free screen or client privates
545 dixFreePrivates(PrivatePtr privates
, DevPrivateType type
)
547 _dixFiniPrivates(privates
, type
);
548 --global_keys
[type
].allocated
;
553 * Return size of privates for the specified type
556 dixPrivatesSize(DevPrivateType type
)
558 assert(type
>= PRIVATE_SCREEN
&& type
< PRIVATE_LAST
);
559 assert (!screen_specific_private
[type
]);
561 return global_keys
[type
].offset
;
564 /* Table of devPrivates offsets */
565 static const int offsets
[] = {
567 offsetof(WindowRec
, devPrivates
), /* RT_WINDOW */
568 offsetof(PixmapRec
, devPrivates
), /* RT_PIXMAP */
569 offsetof(GC
, devPrivates
), /* RT_GC */
571 offsetof(CursorRec
, devPrivates
), /* RT_CURSOR */
572 offsetof(ColormapRec
, devPrivates
), /* RT_COLORMAP */
575 #define NUM_OFFSETS (sizeof (offsets) / sizeof (offsets[0]))
578 dixLookupPrivateOffset(RESTYPE type
)
581 * Special kludge for DBE which registers a new resource type that
582 * points at pixmaps (thanks, DBE)
584 if (type
& RC_DRAWABLE
) {
585 if (type
== RT_WINDOW
)
586 return offsets
[RT_WINDOW
& TypeMask
];
588 return offsets
[RT_PIXMAP
& TypeMask
];
590 type
= type
& TypeMask
;
591 if (type
< NUM_OFFSETS
)
592 return offsets
[type
];
597 * Screen-specific privates
600 extern _X_EXPORT Bool
601 dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen
, DevPrivateKey key
,
602 DevPrivateType type
, unsigned size
)
607 if (!screen_specific_private
[type
])
608 FatalError("Attempt to allocate screen-specific private storage for type %s\n",
611 if (key
->initialized
) {
612 assert(size
== key
->size
);
616 /* Compute required space */
619 bytes
= sizeof(void *);
621 /* align to void * size */
622 bytes
= (bytes
+ sizeof(void *) - 1) & ~(sizeof(void *) - 1);
624 assert (!allocated_early
[type
]);
625 assert (!pScreen
->screenSpecificPrivates
[type
].created
);
626 offset
= pScreen
->screenSpecificPrivates
[type
].offset
;
627 pScreen
->screenSpecificPrivates
[type
].offset
+= bytes
;
630 key
->offset
= offset
;
632 key
->initialized
= TRUE
;
634 key
->allocated
= FALSE
;
635 key
->next
= pScreen
->screenSpecificPrivates
[type
].key
;
636 pScreen
->screenSpecificPrivates
[type
].key
= key
;
641 /* Clean up screen-specific privates before CloseScreen */
643 dixFreeScreenSpecificPrivates(ScreenPtr pScreen
)
647 /* Initialize screen-specific privates in AddScreen */
649 dixInitScreenSpecificPrivates(ScreenPtr pScreen
)
653 for (t
= PRIVATE_XSELINUX
; t
< PRIVATE_LAST
; t
++)
654 pScreen
->screenSpecificPrivates
[t
].offset
= global_keys
[t
].offset
;
657 /* Initialize screen-specific privates in AddScreen */
659 _dixInitScreenPrivates(ScreenPtr pScreen
, PrivatePtr
*privates
, void *addr
, DevPrivateType type
)
662 assert (screen_specific_private
[type
]);
665 privates_size
= pScreen
->screenSpecificPrivates
[type
].offset
;
666 pScreen
->screenSpecificPrivates
[type
].created
++;
669 privates_size
= global_keys
[type
].offset
;
671 global_keys
[type
].created
++;
672 if (xselinux_private
[type
])
673 global_keys
[PRIVATE_XSELINUX
].created
++;
674 if (privates_size
== 0)
677 memset(addr
, '\0', privates_size
);
681 _dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen
,
690 PrivatePtr
*devPrivates
;
693 assert(type
> PRIVATE_SCREEN
&& type
< PRIVATE_LAST
);
694 assert (screen_specific_private
[type
]);
697 privates_size
= pScreen
->screenSpecificPrivates
[type
].offset
;
699 privates_size
= global_keys
[type
].offset
;
700 /* round up so that void * is aligned */
701 baseSize
= (baseSize
+ sizeof(void *) - 1) & ~(sizeof(void *) - 1);
702 totalSize
= baseSize
+ privates_size
;
703 object
= malloc(totalSize
);
707 memset(object
, '\0', clear
);
708 privates
= (PrivatePtr
) (((char *) object
) + baseSize
);
709 devPrivates
= (PrivatePtr
*) ((char *) object
+ offset
);
711 _dixInitScreenPrivates(pScreen
, devPrivates
, privates
, type
);
717 dixScreenSpecificPrivatesSize(ScreenPtr pScreen
, DevPrivateType type
)
719 assert(type
>= PRIVATE_SCREEN
&& type
< PRIVATE_LAST
);
721 if (screen_specific_private
[type
])
722 return pScreen
->screenSpecificPrivates
[type
].offset
;
724 return global_keys
[type
].offset
;
728 dixPrivateUsage(void)
735 for (t
= PRIVATE_XSELINUX
+ 1; t
< PRIVATE_LAST
; t
++) {
736 if (global_keys
[t
].offset
) {
738 ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
739 key_names
[t
], global_keys
[t
].created
, global_keys
[t
].offset
,
740 global_keys
[t
].created
* global_keys
[t
].offset
, global_keys
[t
].allocated
);
741 bytes
+= global_keys
[t
].created
* global_keys
[t
].offset
;
742 objects
+= global_keys
[t
].created
;
743 alloc
+= global_keys
[t
].allocated
;
746 ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects
, bytes
, alloc
);
750 dixResetPrivates(void)
754 for (t
= PRIVATE_XSELINUX
; t
< PRIVATE_LAST
; t
++) {
755 DevPrivateKey key
, next
;
757 for (key
= global_keys
[t
].key
; key
; key
= next
) {
760 key
->initialized
= FALSE
;
766 if (global_keys
[t
].created
) {
767 ErrorF("%d %ss still allocated at reset\n",
768 global_keys
[t
].created
, key_names
[t
]);
771 global_keys
[t
].key
= NULL
;
772 global_keys
[t
].offset
= 0;
773 global_keys
[t
].created
= 0;
774 global_keys
[t
].allocated
= 0;