2 * Mesa 3-D graphics library
5 * Copyright (C) 2010 LunarG Inc.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 * Chia-I Wu <olv@lunarg.com>
29 #include "util/u_memory.h"
30 #include "util/u_atomic.h"
31 #include "os/os_thread.h"
33 #include "eglcurrent.h"
36 #include "egl_g3d_sync.h"
39 * Wait for the conditional variable.
42 egl_g3d_wait_sync_condvar(struct egl_g3d_sync
*gsync
, EGLTimeKHR timeout
)
44 _EGLDisplay
*dpy
= gsync
->base
.Resource
.Display
;
46 pipe_mutex_lock(gsync
->mutex
);
48 /* unlock display lock just before waiting */
49 _eglUnlockMutex(&dpy
->Mutex
);
51 /* No timed wait. Always treat timeout as EGL_FOREVER_KHR */
52 pipe_condvar_wait(gsync
->condvar
, gsync
->mutex
);
54 _eglLockMutex(&dpy
->Mutex
);
56 pipe_mutex_unlock(gsync
->mutex
);
58 return EGL_CONDITION_SATISFIED_KHR
;
62 * Signal the conditional variable.
65 egl_g3d_signal_sync_condvar(struct egl_g3d_sync
*gsync
)
67 pipe_mutex_lock(gsync
->mutex
);
68 pipe_condvar_broadcast(gsync
->condvar
);
69 pipe_mutex_unlock(gsync
->mutex
);
73 * Insert a fence command to the command stream of the current context.
76 egl_g3d_insert_fence_sync(struct egl_g3d_sync
*gsync
)
78 _EGLContext
*ctx
= _eglGetCurrentContext();
79 struct egl_g3d_context
*gctx
= egl_g3d_context(ctx
);
81 /* already checked in egl_g3d_create_sync */
84 /* insert the fence command */
85 gctx
->stctxi
->flush(gctx
->stctxi
, 0x0, &gsync
->fence
);
87 gsync
->base
.SyncStatus
= EGL_SIGNALED_KHR
;
93 * Wait for the fence sync to be signaled.
96 egl_g3d_wait_fence_sync(struct egl_g3d_sync
*gsync
, EGLTimeKHR timeout
)
101 _EGLDisplay
*dpy
= gsync
->base
.Resource
.Display
;
102 struct egl_g3d_display
*gdpy
= egl_g3d_display(dpy
);
103 struct pipe_screen
*screen
= gdpy
->native
->screen
;
104 struct pipe_fence_handle
*fence
= gsync
->fence
;
108 _eglUnlockMutex(&dpy
->Mutex
);
109 /* no timed finish? */
110 screen
->fence_finish(screen
, fence
, PIPE_TIMEOUT_INFINITE
);
111 ret
= EGL_CONDITION_SATISFIED_KHR
;
112 _eglLockMutex(&dpy
->Mutex
);
114 gsync
->base
.SyncStatus
= EGL_SIGNALED_KHR
;
116 screen
->fence_reference(screen
, &fence
, NULL
);
117 egl_g3d_signal_sync_condvar(gsync
);
120 ret
= egl_g3d_wait_sync_condvar(gsync
, timeout
);
127 egl_g3d_ref_sync(struct egl_g3d_sync
*gsync
)
129 _eglGetSync(&gsync
->base
);
133 egl_g3d_unref_sync(struct egl_g3d_sync
*gsync
)
135 if (_eglPutSync(&gsync
->base
)) {
136 pipe_condvar_destroy(gsync
->condvar
);
137 pipe_mutex_destroy(gsync
->mutex
);
140 struct egl_g3d_display
*gdpy
=
141 egl_g3d_display(gsync
->base
.Resource
.Display
);
142 struct pipe_screen
*screen
= gdpy
->native
->screen
;
144 screen
->fence_reference(screen
, &gsync
->fence
, NULL
);
152 egl_g3d_create_sync(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
153 EGLenum type
, const EGLint
*attrib_list
)
155 _EGLContext
*ctx
= _eglGetCurrentContext();
156 struct egl_g3d_sync
*gsync
;
159 if (!ctx
|| ctx
->Resource
.Display
!= dpy
) {
160 _eglError(EGL_BAD_MATCH
, "eglCreateSyncKHR");
164 gsync
= CALLOC_STRUCT(egl_g3d_sync
);
166 _eglError(EGL_BAD_ALLOC
, "eglCreateSyncKHR");
170 if (!_eglInitSync(&gsync
->base
, dpy
, type
, attrib_list
)) {
176 case EGL_SYNC_REUSABLE_KHR
:
179 case EGL_SYNC_FENCE_KHR
:
180 err
= egl_g3d_insert_fence_sync(gsync
);
183 err
= EGL_BAD_ATTRIBUTE
;
187 if (err
!= EGL_SUCCESS
) {
188 _eglError(err
, "eglCreateSyncKHR");
193 pipe_mutex_init(gsync
->mutex
);
194 pipe_condvar_init(gsync
->condvar
);
200 egl_g3d_destroy_sync(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSync
*sync
)
202 struct egl_g3d_sync
*gsync
= egl_g3d_sync(sync
);
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
);
216 egl_g3d_unref_sync(gsync
);
222 egl_g3d_client_wait_sync(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSync
*sync
,
223 EGLint flags
, EGLTimeKHR timeout
)
225 struct egl_g3d_sync
*gsync
= egl_g3d_sync(sync
);
226 EGLint ret
= EGL_CONDITION_SATISFIED_KHR
;
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
);
235 gctx
->stctxi
->flush(gctx
->stctxi
, ST_FLUSH_FRONT
, NULL
);
239 /* reference the sync object in case it is destroyed while waiting */
240 egl_g3d_ref_sync(gsync
);
242 switch (gsync
->base
.Type
) {
243 case EGL_SYNC_REUSABLE_KHR
:
244 ret
= egl_g3d_wait_sync_condvar(gsync
, timeout
);
246 case EGL_SYNC_FENCE_KHR
:
247 ret
= egl_g3d_wait_fence_sync(gsync
, timeout
);
252 egl_g3d_unref_sync(gsync
);
255 ret
= EGL_TIMEOUT_EXPIRED_KHR
;
263 egl_g3d_signal_sync(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSync
*sync
,
266 struct egl_g3d_sync
*gsync
= egl_g3d_sync(sync
);
268 /* only for reusable sync */
269 if (sync
->Type
!= EGL_SYNC_REUSABLE_KHR
)
270 return _eglError(EGL_BAD_MATCH
, "eglSignalSyncKHR");
272 if (gsync
->base
.SyncStatus
!= mode
) {
273 gsync
->base
.SyncStatus
= mode
;
274 if (mode
== EGL_SIGNALED_KHR
)
275 egl_g3d_signal_sync_condvar(gsync
);