From 4b2495661f3a5ac8ed07b68c5d5bf90adee2c37d Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sat, 14 Aug 2010 23:56:46 +0800 Subject: [PATCH] st/egl: Add support for EGL_KHR_reusable_sync. The extension is implemented by pipe_condvar. --- .../state_trackers/egl/common/egl_g3d.c | 2 + .../state_trackers/egl/common/egl_g3d.h | 17 ++ .../state_trackers/egl/common/egl_g3d_api.c | 8 + .../state_trackers/egl/common/egl_g3d_sync.c | 217 ++++++++++++++++++ .../state_trackers/egl/common/egl_g3d_sync.h | 53 +++++ 5 files changed, 297 insertions(+) create mode 100644 src/gallium/state_trackers/egl/common/egl_g3d_sync.c create mode 100644 src/gallium/state_trackers/egl/common/egl_g3d_sync.h diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 56d575ffe08..10e2170729b 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -530,6 +530,8 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) dpy->Extensions.KHR_image_pixmap = EGL_TRUE; + dpy->Extensions.KHR_reusable_sync = EGL_TRUE; + if (egl_g3d_add_configs(drv, dpy, 1) == 1) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); goto fail; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index f33dc91cf90..dabcf841e2a 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -30,12 +30,14 @@ #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_format.h" +#include "os/os_thread.h" #include "egldriver.h" #include "egldisplay.h" #include "eglcontext.h" #include "eglsurface.h" #include "eglconfig.h" #include "eglimage.h" +#include "eglsync.h" #include "eglscreen.h" #include "eglmode.h" @@ -99,6 +101,21 @@ struct egl_g3d_image { _EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d) _EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj) +#ifdef EGL_KHR_reusable_sync + +struct egl_g3d_sync { + _EGLSync base; + + int refs; + + /* the mutex protects only the condvar, not the struct */ + pipe_mutex mutex; + pipe_condvar condvar; +}; +_EGL_DRIVER_TYPECAST(egl_g3d_sync, _EGLSync, obj) + +#endif /* EGL_KHR_reusable_sync */ + #ifdef EGL_MESA_screen_surface struct egl_g3d_screen { diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c index edac72a8223..1120945edc7 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -34,6 +34,7 @@ #include "egl_g3d.h" #include "egl_g3d_api.h" #include "egl_g3d_image.h" +#include "egl_g3d_sync.h" #include "egl_g3d_st.h" #include "egl_g3d_loader.h" #include "native.h" @@ -806,6 +807,13 @@ egl_g3d_init_driver_api(_EGLDriver *drv) drv->API.CreateImageKHR = egl_g3d_create_image; drv->API.DestroyImageKHR = egl_g3d_destroy_image; +#ifdef EGL_KHR_reusable_sync + drv->API.CreateSyncKHR = egl_g3d_create_sync; + drv->API.DestroySyncKHR = egl_g3d_destroy_sync; + drv->API.ClientWaitSyncKHR = egl_g3d_client_wait_sync; + drv->API.SignalSyncKHR = egl_g3d_signal_sync; +#endif + #ifdef EGL_MESA_screen_surface drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_sync.c b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c new file mode 100644 index 00000000000..3351973d83f --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c @@ -0,0 +1,217 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include "util/u_memory.h" +#include "util/u_atomic.h" +#include "os/os_thread.h" +#include "eglsync.h" +#include "eglcurrent.h" + +#include "egl_g3d.h" +#include "egl_g3d_sync.h" + +#ifdef EGL_KHR_reusable_sync + +/** + * Wait for the conditional variable. + */ +static EGLint +egl_g3d_wait_sync_condvar(struct egl_g3d_sync *gsync, EGLTimeKHR timeout) +{ + _EGLDisplay *dpy = gsync->base.Resource.Display; + + pipe_mutex_lock(gsync->mutex); + + /* unlock display lock just before waiting */ + _eglUnlockMutex(&dpy->Mutex); + + /* No timed wait. Always treat timeout as EGL_FOREVER_KHR */ + pipe_condvar_wait(gsync->condvar, gsync->mutex); + + _eglLockMutex(&dpy->Mutex); + + pipe_mutex_unlock(gsync->mutex); + + return EGL_CONDITION_SATISFIED_KHR; +} + +/** + * Signal the conditional variable. + */ +static void +egl_g3d_signal_sync_condvar(struct egl_g3d_sync *gsync) +{ + pipe_mutex_lock(gsync->mutex); + pipe_condvar_broadcast(gsync->condvar); + pipe_mutex_unlock(gsync->mutex); +} + +static INLINE void +egl_g3d_ref_sync(struct egl_g3d_sync *gsync) +{ + p_atomic_inc(&gsync->refs); +} + +static INLINE void +egl_g3d_unref_sync(struct egl_g3d_sync *gsync) +{ + if (p_atomic_dec_zero(&gsync->refs)) { + pipe_condvar_destroy(gsync->condvar); + pipe_mutex_destroy(gsync->mutex); + + FREE(gsync); + } +} + +_EGLSync * +egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy, + EGLenum type, const EGLint *attrib_list) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + struct egl_g3d_sync *gsync; + EGLint err; + + if (!ctx || ctx->Resource.Display != dpy) { + _eglError(EGL_BAD_MATCH, "eglCreateSyncKHR"); + return NULL; + } + + gsync = CALLOC_STRUCT(egl_g3d_sync); + if (!gsync) { + _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); + return NULL; + } + + if (!_eglInitSync(&gsync->base, dpy, type, attrib_list)) { + FREE(gsync); + return NULL; + } + + switch (type) { + case EGL_SYNC_REUSABLE_KHR: + err = EGL_SUCCESS; + break; + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + + if (err != EGL_SUCCESS) { + _eglError(err, "eglCreateSyncKHR"); + FREE(gsync); + return NULL; + } + + pipe_mutex_init(gsync->mutex); + pipe_condvar_init(gsync->condvar); + p_atomic_set(&gsync->refs, 1); + + return &gsync->base; +} + +EGLBoolean +egl_g3d_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync) +{ + struct egl_g3d_sync *gsync = egl_g3d_sync(sync); + + switch (gsync->base.Type) { + case EGL_SYNC_REUSABLE_KHR: + /* signal the waiters */ + if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) { + gsync->base.SyncStatus = EGL_SIGNALED_KHR; + egl_g3d_signal_sync_condvar(gsync); + } + break; + default: + break; + } + + egl_g3d_unref_sync(gsync); + + return EGL_TRUE; +} + +EGLint +egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, + EGLint flags, EGLTimeKHR timeout) +{ + struct egl_g3d_sync *gsync = egl_g3d_sync(sync); + EGLint ret = EGL_CONDITION_SATISFIED_KHR; + + if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) { + /* flush if there is a current context */ + if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) { + _EGLContext *ctx = _eglGetCurrentContext(); + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + + if (gctx) + gctx->stctxi->flush(gctx->stctxi, PIPE_FLUSH_RENDER_CACHE , NULL); + } + + if (timeout) { + /* reference the sync object in case it is destroyed while waiting */ + egl_g3d_ref_sync(gsync); + + switch (gsync->base.Type) { + case EGL_SYNC_REUSABLE_KHR: + ret = egl_g3d_wait_sync_condvar(gsync, timeout); + break; + default: + break; + } + + egl_g3d_unref_sync(gsync); + } + else { + ret = EGL_TIMEOUT_EXPIRED_KHR; + } + } + + return ret; +} + +EGLBoolean +egl_g3d_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, + EGLenum mode) +{ + struct egl_g3d_sync *gsync = egl_g3d_sync(sync); + + /* only for reusable sync */ + if (sync->Type != EGL_SYNC_REUSABLE_KHR) + return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR"); + + if (gsync->base.SyncStatus != mode) { + gsync->base.SyncStatus = mode; + if (mode == EGL_SIGNALED_KHR) + egl_g3d_signal_sync_condvar(gsync); + } + + return EGL_TRUE; +} + +#endif /* EGL_KHR_reusable_sync */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_sync.h b/src/gallium/state_trackers/egl/common/egl_g3d_sync.h new file mode 100644 index 00000000000..3179ca04e1a --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_sync.h @@ -0,0 +1,53 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#ifndef _EGL_G3D_SYNC_H_ +#define _EGL_G3D_SYNC_H_ + +#include "egl_g3d.h" + +#ifdef EGL_KHR_reusable_sync + +_EGLSync * +egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy, + EGLenum type, const EGLint *attrib_list); + +EGLBoolean +egl_g3d_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync); + +EGLint +egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, + EGLint flags, EGLTimeKHR timeout); + +EGLBoolean +egl_g3d_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, + EGLenum mode); + +#endif /* EGL_KHR_reusable_sync */ + +#endif /* _EGL_G3D_SYNC_H_ */ -- 2.30.2