egl_g3d_sync.c revision f957cac772d34b3406be3236b81571e456ee40e8
15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Mesa 3-D graphics library 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Version: 7.9 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (C) 2010 LunarG Inc. 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * copy of this software and associated documentation files (the "Software"), 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to deal in the Software without restriction, including without limitation 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the rights to use, copy, modify, merge, publish, distribute, sublicense, 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * and/or sell copies of the Software, and to permit persons to whom the 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Software is furnished to do so, subject to the following conditions: 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The above copyright notice and this permission notice shall be included 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * in all copies or substantial portions of the Software. 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 219b3a4b03315af9bcdf282243059e8fd1ce1c5c70David 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2226b47fe632cf0de7962e79a1113d8a5d93459262David 'Digit' Turner * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2334c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner * DEALINGS IN THE SOFTWARE. 246af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner * 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Authors: 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Chia-I Wu <olv@lunarg.com> 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "util/u_memory.h" 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "util/u_atomic.h" 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "os/os_thread.h" 325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "eglsync.h" 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "eglcurrent.h" 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 35bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner#include "egl_g3d.h" 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "egl_g3d_sync.h" 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/** 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Wait for the conditional variable. 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic EGLint 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneregl_g3d_wait_sync_condvar(struct egl_g3d_sync *gsync, EGLTimeKHR timeout) 43bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner{ 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _EGLDisplay *dpy = gsync->base.Resource.Display; 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pipe_mutex_lock(gsync->mutex); 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* unlock display lock just before waiting */ 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _eglUnlockMutex(&dpy->Mutex); 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* No timed wait. Always treat timeout as EGL_FOREVER_KHR */ 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pipe_condvar_wait(gsync->condvar, gsync->mutex); 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _eglLockMutex(&dpy->Mutex); 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pipe_mutex_unlock(gsync->mutex); 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return EGL_CONDITION_SATISFIED_KHR; 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/** 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Signal the conditional variable. 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneregl_g3d_signal_sync_condvar(struct egl_g3d_sync *gsync) 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pipe_mutex_lock(gsync->mutex); 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pipe_condvar_broadcast(gsync->condvar); 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pipe_mutex_unlock(gsync->mutex); 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/** 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Insert a fence command to the command stream of the current context. 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic EGLint 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneregl_g3d_insert_fence_sync(struct egl_g3d_sync *gsync) 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _EGLContext *ctx = _eglGetCurrentContext(); 79bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner struct egl_g3d_context *gctx = egl_g3d_context(ctx); 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* already checked in egl_g3d_create_sync */ 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(gctx); 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* insert the fence command */ 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gctx->stctxi->flush(gctx->stctxi, 0x0, &gsync->fence); 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!gsync->fence) 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gsync->base.SyncStatus = EGL_SIGNALED_KHR; 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return EGL_SUCCESS; 90bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner} 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/** 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Wait for the fence sync to be signaled. 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic EGLint 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneregl_g3d_wait_fence_sync(struct egl_g3d_sync *gsync, EGLTimeKHR timeout) 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner EGLint ret; 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (gsync->fence) { 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _EGLDisplay *dpy = gsync->base.Resource.Display; 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct pipe_screen *screen = gdpy->native->screen; 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct pipe_fence_handle *fence = gsync->fence; 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gsync->fence = NULL; 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _eglUnlockMutex(&dpy->Mutex); 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* no timed finish? */ 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = EGL_CONDITION_SATISFIED_KHR; 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _eglLockMutex(&dpy->Mutex); 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gsync->base.SyncStatus = EGL_SIGNALED_KHR; 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner screen->fence_reference(screen, &fence, NULL); 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner egl_g3d_signal_sync_condvar(gsync); 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else { 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = egl_g3d_wait_sync_condvar(gsync, timeout); 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 122aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner 123aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner return ret; 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic INLINE void 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneregl_g3d_ref_sync(struct egl_g3d_sync *gsync) 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _eglGetSync(&gsync->base); 130bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner} 1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic INLINE void 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneregl_g3d_unref_sync(struct egl_g3d_sync *gsync) 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (_eglPutSync(&gsync->base)) { 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pipe_condvar_destroy(gsync->condvar); 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pipe_mutex_destroy(gsync->mutex); 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (gsync->fence) { 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct egl_g3d_display *gdpy = 141bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turner egl_g3d_display(gsync->base.Resource.Display); 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct pipe_screen *screen = gdpy->native->screen; 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner screen->fence_reference(screen, &gsync->fence, NULL); 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FREE(gsync); 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner_EGLSync * 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneregl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy, 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner EGLenum type, const EGLint *attrib_list) 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _EGLContext *ctx = _eglGetCurrentContext(); 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct egl_g3d_sync *gsync; 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner EGLint err; 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ctx || ctx->Resource.Display != dpy) { 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _eglError(EGL_BAD_MATCH, "eglCreateSyncKHR"); 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gsync = CALLOC_STRUCT(egl_g3d_sync); 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!gsync) { 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); 167 return NULL; 168 } 169 170 if (!_eglInitSync(&gsync->base, dpy, type, attrib_list)) { 171 FREE(gsync); 172 return NULL; 173 } 174 175 switch (type) { 176 case EGL_SYNC_REUSABLE_KHR: 177 err = EGL_SUCCESS; 178 break; 179 case EGL_SYNC_FENCE_KHR: 180 err = egl_g3d_insert_fence_sync(gsync); 181 break; 182 default: 183 err = EGL_BAD_ATTRIBUTE; 184 break; 185 } 186 187 if (err != EGL_SUCCESS) { 188 _eglError(err, "eglCreateSyncKHR"); 189 FREE(gsync); 190 return NULL; 191 } 192 193 pipe_mutex_init(gsync->mutex); 194 pipe_condvar_init(gsync->condvar); 195 196 return &gsync->base; 197} 198 199EGLBoolean 200egl_g3d_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync) 201{ 202 struct egl_g3d_sync *gsync = egl_g3d_sync(sync); 203 204 switch (gsync->base.Type) { 205 case EGL_SYNC_REUSABLE_KHR: 206 /* signal the waiters */ 207 if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) { 208 gsync->base.SyncStatus = EGL_SIGNALED_KHR; 209 egl_g3d_signal_sync_condvar(gsync); 210 } 211 break; 212 default: 213 break; 214 } 215 216 egl_g3d_unref_sync(gsync); 217 218 return EGL_TRUE; 219} 220 221EGLint 222egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, 223 EGLint flags, EGLTimeKHR timeout) 224{ 225 struct egl_g3d_sync *gsync = egl_g3d_sync(sync); 226 EGLint ret = EGL_CONDITION_SATISFIED_KHR; 227 228 if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) { 229 /* flush if there is a current context */ 230 if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) { 231 _EGLContext *ctx = _eglGetCurrentContext(); 232 struct egl_g3d_context *gctx = egl_g3d_context(ctx); 233 234 if (gctx) 235 gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL); 236 } 237 238 if (timeout) { 239 /* reference the sync object in case it is destroyed while waiting */ 240 egl_g3d_ref_sync(gsync); 241 242 switch (gsync->base.Type) { 243 case EGL_SYNC_REUSABLE_KHR: 244 ret = egl_g3d_wait_sync_condvar(gsync, timeout); 245 break; 246 case EGL_SYNC_FENCE_KHR: 247 ret = egl_g3d_wait_fence_sync(gsync, timeout); 248 default: 249 break; 250 } 251 252 egl_g3d_unref_sync(gsync); 253 } 254 else { 255 ret = EGL_TIMEOUT_EXPIRED_KHR; 256 } 257 } 258 259 return ret; 260} 261 262EGLBoolean 263egl_g3d_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, 264 EGLenum mode) 265{ 266 struct egl_g3d_sync *gsync = egl_g3d_sync(sync); 267 268 /* only for reusable sync */ 269 if (sync->Type != EGL_SYNC_REUSABLE_KHR) 270 return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR"); 271 272 if (gsync->base.SyncStatus != mode) { 273 gsync->base.SyncStatus = mode; 274 if (mode == EGL_SIGNALED_KHR) 275 egl_g3d_signal_sync_condvar(gsync); 276 } 277 278 return EGL_TRUE; 279} 280