egl_g3d_sync.c revision 4b2495661f3a5ac8ed07b68c5d5bf90adee2c37d
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.9 4 * 5 * Copyright (C) 2010 LunarG Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Chia-I Wu <olv@lunarg.com> 27 */ 28 29#include "util/u_memory.h" 30#include "util/u_atomic.h" 31#include "os/os_thread.h" 32#include "eglsync.h" 33#include "eglcurrent.h" 34 35#include "egl_g3d.h" 36#include "egl_g3d_sync.h" 37 38#ifdef EGL_KHR_reusable_sync 39 40/** 41 * Wait for the conditional variable. 42 */ 43static EGLint 44egl_g3d_wait_sync_condvar(struct egl_g3d_sync *gsync, EGLTimeKHR timeout) 45{ 46 _EGLDisplay *dpy = gsync->base.Resource.Display; 47 48 pipe_mutex_lock(gsync->mutex); 49 50 /* unlock display lock just before waiting */ 51 _eglUnlockMutex(&dpy->Mutex); 52 53 /* No timed wait. Always treat timeout as EGL_FOREVER_KHR */ 54 pipe_condvar_wait(gsync->condvar, gsync->mutex); 55 56 _eglLockMutex(&dpy->Mutex); 57 58 pipe_mutex_unlock(gsync->mutex); 59 60 return EGL_CONDITION_SATISFIED_KHR; 61} 62 63/** 64 * Signal the conditional variable. 65 */ 66static void 67egl_g3d_signal_sync_condvar(struct egl_g3d_sync *gsync) 68{ 69 pipe_mutex_lock(gsync->mutex); 70 pipe_condvar_broadcast(gsync->condvar); 71 pipe_mutex_unlock(gsync->mutex); 72} 73 74static INLINE void 75egl_g3d_ref_sync(struct egl_g3d_sync *gsync) 76{ 77 p_atomic_inc(&gsync->refs); 78} 79 80static INLINE void 81egl_g3d_unref_sync(struct egl_g3d_sync *gsync) 82{ 83 if (p_atomic_dec_zero(&gsync->refs)) { 84 pipe_condvar_destroy(gsync->condvar); 85 pipe_mutex_destroy(gsync->mutex); 86 87 FREE(gsync); 88 } 89} 90 91_EGLSync * 92egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy, 93 EGLenum type, const EGLint *attrib_list) 94{ 95 _EGLContext *ctx = _eglGetCurrentContext(); 96 struct egl_g3d_sync *gsync; 97 EGLint err; 98 99 if (!ctx || ctx->Resource.Display != dpy) { 100 _eglError(EGL_BAD_MATCH, "eglCreateSyncKHR"); 101 return NULL; 102 } 103 104 gsync = CALLOC_STRUCT(egl_g3d_sync); 105 if (!gsync) { 106 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); 107 return NULL; 108 } 109 110 if (!_eglInitSync(&gsync->base, dpy, type, attrib_list)) { 111 FREE(gsync); 112 return NULL; 113 } 114 115 switch (type) { 116 case EGL_SYNC_REUSABLE_KHR: 117 err = EGL_SUCCESS; 118 break; 119 default: 120 err = EGL_BAD_ATTRIBUTE; 121 break; 122 } 123 124 if (err != EGL_SUCCESS) { 125 _eglError(err, "eglCreateSyncKHR"); 126 FREE(gsync); 127 return NULL; 128 } 129 130 pipe_mutex_init(gsync->mutex); 131 pipe_condvar_init(gsync->condvar); 132 p_atomic_set(&gsync->refs, 1); 133 134 return &gsync->base; 135} 136 137EGLBoolean 138egl_g3d_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync) 139{ 140 struct egl_g3d_sync *gsync = egl_g3d_sync(sync); 141 142 switch (gsync->base.Type) { 143 case EGL_SYNC_REUSABLE_KHR: 144 /* signal the waiters */ 145 if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) { 146 gsync->base.SyncStatus = EGL_SIGNALED_KHR; 147 egl_g3d_signal_sync_condvar(gsync); 148 } 149 break; 150 default: 151 break; 152 } 153 154 egl_g3d_unref_sync(gsync); 155 156 return EGL_TRUE; 157} 158 159EGLint 160egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, 161 EGLint flags, EGLTimeKHR timeout) 162{ 163 struct egl_g3d_sync *gsync = egl_g3d_sync(sync); 164 EGLint ret = EGL_CONDITION_SATISFIED_KHR; 165 166 if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) { 167 /* flush if there is a current context */ 168 if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) { 169 _EGLContext *ctx = _eglGetCurrentContext(); 170 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 171 172 if (gctx) 173 gctx->stctxi->flush(gctx->stctxi, PIPE_FLUSH_RENDER_CACHE , NULL); 174 } 175 176 if (timeout) { 177 /* reference the sync object in case it is destroyed while waiting */ 178 egl_g3d_ref_sync(gsync); 179 180 switch (gsync->base.Type) { 181 case EGL_SYNC_REUSABLE_KHR: 182 ret = egl_g3d_wait_sync_condvar(gsync, timeout); 183 break; 184 default: 185 break; 186 } 187 188 egl_g3d_unref_sync(gsync); 189 } 190 else { 191 ret = EGL_TIMEOUT_EXPIRED_KHR; 192 } 193 } 194 195 return ret; 196} 197 198EGLBoolean 199egl_g3d_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, 200 EGLenum mode) 201{ 202 struct egl_g3d_sync *gsync = egl_g3d_sync(sync); 203 204 /* only for reusable sync */ 205 if (sync->Type != EGL_SYNC_REUSABLE_KHR) 206 return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR"); 207 208 if (gsync->base.SyncStatus != mode) { 209 gsync->base.SyncStatus = mode; 210 if (mode == EGL_SIGNALED_KHR) 211 egl_g3d_signal_sync_condvar(gsync); 212 } 213 214 return EGL_TRUE; 215} 216 217#endif /* EGL_KHR_reusable_sync */ 218