Imported Upstream version 1.15.1
[deb_xorg-server.git] / miext / sync / misyncshm.c
1 /*
2 * Copyright © 2013 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
26
27 #include "scrnintstr.h"
28 #include "misync.h"
29 #include "misyncstr.h"
30 #include "misyncshm.h"
31 #include "misyncfd.h"
32 #include "pixmapstr.h"
33 #include <sys/mman.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <X11/xshmfence.h>
37
38 static DevPrivateKeyRec syncShmFencePrivateKey;
39
40 typedef struct _SyncShmFencePrivate {
41 struct xshmfence *fence;
42 int fd;
43 } SyncShmFencePrivateRec, *SyncShmFencePrivatePtr;
44
45 #define SYNC_FENCE_PRIV(pFence) \
46 (SyncShmFencePrivatePtr) dixLookupPrivate(&pFence->devPrivates, &syncShmFencePrivateKey)
47
48 static void
49 miSyncShmFenceSetTriggered(SyncFence * pFence)
50 {
51 SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
52
53 if (pPriv->fence)
54 xshmfence_trigger(pPriv->fence);
55 miSyncFenceSetTriggered(pFence);
56 }
57
58 static void
59 miSyncShmFenceReset(SyncFence * pFence)
60 {
61 SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
62
63 if (pPriv->fence)
64 xshmfence_reset(pPriv->fence);
65 miSyncFenceReset(pFence);
66 }
67
68 static Bool
69 miSyncShmFenceCheckTriggered(SyncFence * pFence)
70 {
71 SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
72
73 if (pPriv->fence)
74 return xshmfence_query(pPriv->fence);
75 else
76 return miSyncFenceCheckTriggered(pFence);
77 }
78
79 static void
80 miSyncShmFenceAddTrigger(SyncTrigger * pTrigger)
81 {
82 miSyncFenceAddTrigger(pTrigger);
83 }
84
85 static void
86 miSyncShmFenceDeleteTrigger(SyncTrigger * pTrigger)
87 {
88 miSyncFenceDeleteTrigger(pTrigger);
89 }
90
91 static const SyncFenceFuncsRec miSyncShmFenceFuncs = {
92 &miSyncShmFenceSetTriggered,
93 &miSyncShmFenceReset,
94 &miSyncShmFenceCheckTriggered,
95 &miSyncShmFenceAddTrigger,
96 &miSyncShmFenceDeleteTrigger
97 };
98
99 static void
100 miSyncShmScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence,
101 Bool initially_triggered)
102 {
103 SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
104
105 pPriv->fence = NULL;
106 miSyncScreenCreateFence(pScreen, pFence, initially_triggered);
107 pFence->funcs = miSyncShmFenceFuncs;
108 }
109
110 static void
111 miSyncShmScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence)
112 {
113 SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
114
115 if (pPriv->fence) {
116 xshmfence_trigger(pPriv->fence);
117 xshmfence_unmap_shm(pPriv->fence);
118 close(pPriv->fd);
119 }
120 miSyncScreenDestroyFence(pScreen, pFence);
121 }
122
123 static int
124 miSyncShmCreateFenceFromFd(ScreenPtr pScreen, SyncFence *pFence, int fd, Bool initially_triggered)
125 {
126 SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
127
128 miSyncInitFence(pScreen, pFence, initially_triggered);
129
130 fd = os_move_fd(fd);
131 pPriv->fence = xshmfence_map_shm(fd);
132 if (pPriv->fence) {
133 pPriv->fd = fd;
134 return Success;
135 }
136 else
137 close(fd);
138 return BadValue;
139 }
140
141 static int
142 miSyncShmGetFenceFd(ScreenPtr pScreen, SyncFence *pFence)
143 {
144 SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
145
146 if (!pPriv->fence) {
147 pPriv->fd = xshmfence_alloc_shm();
148 if (pPriv->fd < 0)
149 return -1;
150 pPriv->fd = os_move_fd(pPriv->fd);
151 pPriv->fence = xshmfence_map_shm(pPriv->fd);
152 if (!pPriv->fence) {
153 close (pPriv->fd);
154 return -1;
155 }
156 }
157 return pPriv->fd;
158 }
159
160 static const SyncFdScreenFuncsRec miSyncShmScreenFuncs = {
161 .version = SYNC_FD_SCREEN_FUNCS_VERSION,
162 .CreateFenceFromFd = miSyncShmCreateFenceFromFd,
163 .GetFenceFd = miSyncShmGetFenceFd
164 };
165
166 _X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen)
167 {
168 SyncScreenFuncsPtr funcs;
169
170 if (!miSyncFdScreenInit(pScreen, &miSyncShmScreenFuncs))
171 return FALSE;
172
173 if (!dixPrivateKeyRegistered(&syncShmFencePrivateKey)) {
174 if (!dixRegisterPrivateKey(&syncShmFencePrivateKey, PRIVATE_SYNC_FENCE,
175 sizeof(SyncShmFencePrivateRec)))
176 return FALSE;
177 }
178
179 funcs = miSyncGetScreenFuncs(pScreen);
180
181 funcs->CreateFence = miSyncShmScreenCreateFence;
182 funcs->DestroyFence = miSyncShmScreenDestroyFence;
183
184 return TRUE;
185 }
186