Imported Upstream version 1.15.1
[deb_xorg-server.git] / miext / sync / misyncshm.c
CommitLineData
a09e091a
JB
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
38static DevPrivateKeyRec syncShmFencePrivateKey;
39
40typedef 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
48static void
49miSyncShmFenceSetTriggered(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
58static void
59miSyncShmFenceReset(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
68static Bool
69miSyncShmFenceCheckTriggered(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
79static void
80miSyncShmFenceAddTrigger(SyncTrigger * pTrigger)
81{
82 miSyncFenceAddTrigger(pTrigger);
83}
84
85static void
86miSyncShmFenceDeleteTrigger(SyncTrigger * pTrigger)
87{
88 miSyncFenceDeleteTrigger(pTrigger);
89}
90
91static const SyncFenceFuncsRec miSyncShmFenceFuncs = {
92 &miSyncShmFenceSetTriggered,
93 &miSyncShmFenceReset,
94 &miSyncShmFenceCheckTriggered,
95 &miSyncShmFenceAddTrigger,
96 &miSyncShmFenceDeleteTrigger
97};
98
99static void
100miSyncShmScreenCreateFence(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
110static void
111miSyncShmScreenDestroyFence(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
123static int
124miSyncShmCreateFenceFromFd(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
141static int
142miSyncShmGetFenceFd(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
160static 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