Add penmount touchscreen configuration file
[profile/ivi/xorg-x11-server.git] / dix / privates.c
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
66 static struct {
67     DevPrivateKey       key;
68     unsigned            offset;
69     int                 created;
70     int                 allocated;
71 } keys[PRIVATE_LAST];
72
73 static const Bool xselinux_private[PRIVATE_LAST] = {
74     [PRIVATE_SCREEN] = TRUE,
75     [PRIVATE_CLIENT] = TRUE,
76     [PRIVATE_WINDOW] = TRUE,
77     [PRIVATE_PIXMAP] = TRUE,
78     [PRIVATE_GC] = 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,
87 };
88
89 typedef Bool (*FixupFunc)(PrivatePtr *privates, int offset, unsigned bytes);
90
91 static Bool
92 dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
93 {
94     void        *new_privates;
95
96     new_privates = realloc(*privates, old_offset + bytes);
97     if (!new_privates)
98         return FALSE;
99     memset((char *) new_privates + old_offset, '\0', bytes);
100     *privates = new_privates;
101     return TRUE;
102 }
103
104 static Bool
105 dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
106 {
107     memmove((char *) *privates + bytes, *privates, new_offset - bytes);
108     memset(*privates, '\0', bytes);
109     return TRUE;
110 }
111
112 static Bool
113 fixupScreens(FixupFunc fixup, unsigned bytes)
114 {
115     int s;
116     for (s = 0; s < screenInfo.numScreens; s++)
117         if (!fixup(&screenInfo.screens[s]->devPrivates, keys[PRIVATE_SCREEN].offset, bytes))
118             return FALSE;
119     return TRUE;
120 }
121
122 static Bool
123 fixupServerClient(FixupFunc fixup, unsigned bytes)
124 {
125     if (serverClient)
126         return fixup(&serverClient->devPrivates, keys[PRIVATE_CLIENT].offset, bytes);
127     return TRUE;
128 }
129
130 static Bool
131 fixupExtensions(FixupFunc fixup, unsigned bytes)
132 {
133     unsigned char       major;
134     ExtensionEntry      *extension;
135     for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); major++)
136         if (!fixup(&extension->devPrivates, keys[PRIVATE_EXTENSION].offset, bytes))
137             return FALSE;
138     return TRUE;
139 }
140
141 static Bool
142 fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
143 {
144     int s;
145     for (s = 0; s < screenInfo.numScreens; s++) {
146         ColormapPtr cmap;
147         dixLookupResourceByType((pointer *) &cmap, screenInfo.screens[s]->defColormap,
148                                 RT_COLORMAP, serverClient, DixCreateAccess);
149         if (cmap && !fixup(&cmap->devPrivates, keys[PRIVATE_COLORMAP].offset, bytes))
150             return FALSE;
151     }
152     return TRUE;
153 }
154
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,
160 };
161
162 /*
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
169  */
170 Bool
171 dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
172 {
173     DevPrivateType      t;
174     int                 offset;
175     unsigned            bytes;
176
177     if (key->initialized) {
178         assert (size == key->size);
179         return TRUE;
180     }
181
182     /* Compute required space */
183     bytes = size;
184     if (size == 0)
185         bytes = sizeof (void *);
186
187     /* align to void * size */
188     bytes = (bytes + sizeof (void *) - 1) & ~(sizeof (void *) - 1);
189
190     /* Update offsets for all affected keys */
191     if (type == PRIVATE_XSELINUX) {
192         DevPrivateKey   k;
193
194         /* Resize if we can, or make sure nothing's allocated if we can't
195          */
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))
201                     return FALSE;
202             }
203
204         /* Move all existing keys up in the privates space to make
205          * room for this new global key
206          */
207         for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
208             if (xselinux_private[t]) {
209                 for (k = keys[t].key; k; k = k->next)
210                     k->offset += bytes;
211                 keys[t].offset += bytes;
212                 if (allocated_early[t])
213                     allocated_early[t](dixMovePrivates, bytes);
214             }
215         }
216
217         offset = 0;
218     } else {
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))
223             return FALSE;
224         offset = keys[type].offset;
225         keys[type].offset += bytes;
226     }
227
228     /* Setup this key */
229     key->offset = offset;
230     key->size = size;
231     key->initialized = TRUE;
232     key->type = type;
233     key->allocated = FALSE;
234     key->next = keys[type].key;
235     keys[type].key = key;
236
237     return TRUE;
238 }
239
240 /*
241  * Allocate a new private key.
242  *
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
247  */
248 DevPrivateKey
249 dixCreatePrivateKey(DevPrivateType type, unsigned size)
250 {
251     DevPrivateKey       key;
252
253     key = calloc(sizeof (DevPrivateKeyRec), 1);
254     if (!key)
255         return NULL;
256     if (!dixRegisterPrivateKey(key, type, size)) {
257         free(key);
258         return NULL;
259     }
260     key->allocated = TRUE;
261     return key;
262 }
263
264 /*
265  * Initialize privates by zeroing them
266  */
267 void
268 _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
269 {
270     keys[type].created++;
271     if (xselinux_private[type])
272         keys[PRIVATE_XSELINUX].created++;
273     if (keys[type].offset == 0)
274         addr = 0;
275     *privates = addr;
276     memset(addr, '\0', keys[type].offset);
277 }
278
279 /*
280  * Clean up privates
281  */
282 void
283 _dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
284 {
285     keys[type].created--;
286     if (xselinux_private[type])
287         keys[PRIVATE_XSELINUX].created--;
288 }
289
290 /*
291  * Allocate new object with privates.
292  *
293  * This is expected to be invoked from the
294  * dixAllocateObjectWithPrivates macro
295  */
296 void *
297 _dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, unsigned offset, DevPrivateType type)
298 {
299     unsigned            totalSize;
300     void                *object;
301     PrivatePtr          privates;
302     PrivatePtr          *devPrivates;
303
304     assert (type > PRIVATE_SCREEN && type < PRIVATE_LAST);
305
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);
310     if (!object)
311         return NULL;
312
313     memset(object, '\0', clear);
314     privates = (PrivatePtr) (((char *) object) + baseSize);
315     devPrivates = (PrivatePtr *) ((char *) object + offset);
316
317     _dixInitPrivates(devPrivates, privates, type);
318
319     return object;
320 }
321
322 /*
323  * Allocate privates separately from containing object.
324  * Used for clients and screens.
325  */
326 Bool
327 dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
328 {
329     unsigned    size;
330     PrivatePtr  p;
331
332     assert (type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
333
334     size = keys[type].offset;
335     if (!size) {
336         p = NULL;
337     } else {
338         if (!(p = malloc(size)))
339             return FALSE;
340     }
341
342     _dixInitPrivates(privates, p, type);
343     ++keys[type].allocated;
344
345     return TRUE;
346 }
347
348 /*
349  * Free an object that has privates
350  *
351  * This is expected to be invoked from the
352  * dixFreeObjectWithPrivates macro
353  */
354 void
355 _dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type)
356 {
357     _dixFiniPrivates(privates, type);
358     free(object);
359 }
360
361 /*
362  * Called to free screen or client privates
363  */
364 void
365 dixFreePrivates(PrivatePtr privates, DevPrivateType type)
366 {
367     _dixFiniPrivates(privates, type);
368     --keys[type].allocated;
369     free(privates);
370 }
371
372 /*
373  * Return size of privates for the specified type
374  */
375 extern _X_EXPORT int
376 dixPrivatesSize(DevPrivateType type)
377 {
378     assert (type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
379
380     return keys[type].offset;
381 }
382
383 /* Table of devPrivates offsets */
384 static const int offsets[] = {
385     -1,                                 /* RT_NONE */
386     offsetof(WindowRec, devPrivates),   /* RT_WINDOW */
387     offsetof(PixmapRec, devPrivates),   /* RT_PIXMAP */
388     offsetof(GC, devPrivates),          /* RT_GC */
389     -1,                                 /* RT_FONT */
390     offsetof(CursorRec, devPrivates),   /* RT_CURSOR */
391     offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
392 };
393
394 #define NUM_OFFSETS     (sizeof (offsets) / sizeof (offsets[0]))
395
396 int
397 dixLookupPrivateOffset(RESTYPE type)
398 {
399     /*
400      * Special kludge for DBE which registers a new resource type that
401      * points at pixmaps (thanks, DBE)
402      */
403     if (type & RC_DRAWABLE) {
404         if (type == RT_WINDOW)
405             return offsets[RT_WINDOW & TypeMask];
406         else
407             return offsets[RT_PIXMAP & TypeMask];
408     }
409     type = type & TypeMask;
410     if (type < NUM_OFFSETS)
411         return offsets[type];
412     return -1;
413 }
414
415 static const char *key_names[PRIVATE_LAST] = {
416     /* XSELinux uses the same private keys for numerous objects */
417     [PRIVATE_XSELINUX] = "XSELINUX",
418
419     /* Otherwise, you get a private in just the requested structure
420      */
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",
425
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",
433     [PRIVATE_GC] = "GC",
434     [PRIVATE_CURSOR] = "CURSOR",
435     [PRIVATE_CURSOR_BITS] = "CURSOR_BITS",
436
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",
444 };
445
446 void
447 dixPrivateUsage(void)
448 {
449     int objects = 0;
450     int bytes = 0;
451     int alloc = 0;
452     DevPrivateType t;
453
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,
458                    keys[t].allocated);
459             bytes += keys[t].created * keys[t].offset;
460             objects += keys[t].created;
461             alloc += keys[t].allocated;
462         }
463     }
464     ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n",
465            objects, bytes, alloc);
466 }
467
468 void
469 dixResetPrivates(void)
470 {
471     DevPrivateType      t;
472
473     for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
474         DevPrivateKey   key, next;
475
476         for (key = keys[t].key; key; key = next) {
477             next = key->next;
478             key->offset = 0;
479             key->initialized = FALSE;
480             key->size = 0;
481             key->type = 0;
482             if (key->allocated)
483                 free(key);
484         }
485         if (keys[t].created) {
486             ErrorF("%d %ss still allocated at reset\n",
487                    keys[t].created, key_names[t]);
488             dixPrivateUsage();
489         }
490         keys[t].key = NULL;
491         keys[t].offset = 0;
492         keys[t].created = 0;
493         keys[t].allocated = 0;
494     }
495 }