misyncshm.c (5296B)
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