xref: /aosp_15_r20/external/mesa3d/src/mesa/main/syncobj.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2009 Intel Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*61046927SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker /**
25*61046927SAndroid Build Coastguard Worker  * \file syncobj.c
26*61046927SAndroid Build Coastguard Worker  * Sync object management.
27*61046927SAndroid Build Coastguard Worker  *
28*61046927SAndroid Build Coastguard Worker  * Unlike textures and other objects that are shared between contexts, sync
29*61046927SAndroid Build Coastguard Worker  * objects are not bound to the context.  As a result, the reference counting
30*61046927SAndroid Build Coastguard Worker  * and delete behavior of sync objects is slightly different.  References to
31*61046927SAndroid Build Coastguard Worker  * sync objects are added:
32*61046927SAndroid Build Coastguard Worker  *
33*61046927SAndroid Build Coastguard Worker  *    - By \c glFencSynce.  This sets the initial reference count to 1.
34*61046927SAndroid Build Coastguard Worker  *    - At the start of \c glClientWaitSync.  The reference is held for the
35*61046927SAndroid Build Coastguard Worker  *      duration of the wait call.
36*61046927SAndroid Build Coastguard Worker  *
37*61046927SAndroid Build Coastguard Worker  * References are removed:
38*61046927SAndroid Build Coastguard Worker  *
39*61046927SAndroid Build Coastguard Worker  *    - By \c glDeleteSync.
40*61046927SAndroid Build Coastguard Worker  *    - At the end of \c glClientWaitSync.
41*61046927SAndroid Build Coastguard Worker  *
42*61046927SAndroid Build Coastguard Worker  * Additionally, drivers may call \c _mesa_ref_sync_object and
43*61046927SAndroid Build Coastguard Worker  * \c _mesa_unref_sync_object as needed to implement \c ServerWaitSync.
44*61046927SAndroid Build Coastguard Worker  *
45*61046927SAndroid Build Coastguard Worker  * As with shader objects, sync object names become invalid as soon as
46*61046927SAndroid Build Coastguard Worker  * \c glDeleteSync is called.  For this reason \c glDeleteSync sets the
47*61046927SAndroid Build Coastguard Worker  * \c DeletePending flag.  All functions validate object handles by testing
48*61046927SAndroid Build Coastguard Worker  * this flag.
49*61046927SAndroid Build Coastguard Worker  *
50*61046927SAndroid Build Coastguard Worker  * \note
51*61046927SAndroid Build Coastguard Worker  * Only \c GL_ARB_sync objects are shared between contexts.  If support is ever
52*61046927SAndroid Build Coastguard Worker  * added for either \c GL_NV_fence or \c GL_APPLE_fence different semantics
53*61046927SAndroid Build Coastguard Worker  * will need to be implemented.
54*61046927SAndroid Build Coastguard Worker  *
55*61046927SAndroid Build Coastguard Worker  * \author Ian Romanick <[email protected]>
56*61046927SAndroid Build Coastguard Worker  */
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
59*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker #include "context.h"
62*61046927SAndroid Build Coastguard Worker #include "macros.h"
63*61046927SAndroid Build Coastguard Worker #include "get.h"
64*61046927SAndroid Build Coastguard Worker #include "mtypes.h"
65*61046927SAndroid Build Coastguard Worker #include "util/hash_table.h"
66*61046927SAndroid Build Coastguard Worker #include "util/set.h"
67*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
68*61046927SAndroid Build Coastguard Worker #include "util/perf/cpu_trace.h"
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker #include "syncobj.h"
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker #include "api_exec_decl.h"
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker #include "pipe/p_context.h"
75*61046927SAndroid Build Coastguard Worker #include "pipe/p_screen.h"
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker /**
78*61046927SAndroid Build Coastguard Worker  * Allocate/init the context state related to sync objects.
79*61046927SAndroid Build Coastguard Worker  */
80*61046927SAndroid Build Coastguard Worker void
_mesa_init_sync(struct gl_context * ctx)81*61046927SAndroid Build Coastguard Worker _mesa_init_sync(struct gl_context *ctx)
82*61046927SAndroid Build Coastguard Worker {
83*61046927SAndroid Build Coastguard Worker    (void) ctx;
84*61046927SAndroid Build Coastguard Worker }
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker /**
88*61046927SAndroid Build Coastguard Worker  * Free the context state related to sync objects.
89*61046927SAndroid Build Coastguard Worker  */
90*61046927SAndroid Build Coastguard Worker void
_mesa_free_sync_data(struct gl_context * ctx)91*61046927SAndroid Build Coastguard Worker _mesa_free_sync_data(struct gl_context *ctx)
92*61046927SAndroid Build Coastguard Worker {
93*61046927SAndroid Build Coastguard Worker    (void) ctx;
94*61046927SAndroid Build Coastguard Worker }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker static struct gl_sync_object *
new_sync_object(struct gl_context * ctx)97*61046927SAndroid Build Coastguard Worker new_sync_object(struct gl_context *ctx)
98*61046927SAndroid Build Coastguard Worker {
99*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *so = CALLOC_STRUCT(gl_sync_object);
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&so->mutex, mtx_plain);
102*61046927SAndroid Build Coastguard Worker    return so;
103*61046927SAndroid Build Coastguard Worker }
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker static void
delete_sync_object(struct gl_context * ctx,struct gl_sync_object * obj)106*61046927SAndroid Build Coastguard Worker delete_sync_object(struct gl_context *ctx,
107*61046927SAndroid Build Coastguard Worker                       struct gl_sync_object *obj)
108*61046927SAndroid Build Coastguard Worker {
109*61046927SAndroid Build Coastguard Worker    struct pipe_screen *screen = ctx->pipe->screen;
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    screen->fence_reference(screen, &obj->fence, NULL);
112*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&obj->mutex);
113*61046927SAndroid Build Coastguard Worker    free(obj->Label);
114*61046927SAndroid Build Coastguard Worker    FREE(obj);
115*61046927SAndroid Build Coastguard Worker }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker static void
__client_wait_sync(struct gl_context * ctx,struct gl_sync_object * obj,GLbitfield flags,GLuint64 timeout)118*61046927SAndroid Build Coastguard Worker __client_wait_sync(struct gl_context *ctx,
119*61046927SAndroid Build Coastguard Worker                    struct gl_sync_object *obj,
120*61046927SAndroid Build Coastguard Worker                    GLbitfield flags, GLuint64 timeout)
121*61046927SAndroid Build Coastguard Worker {
122*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = ctx->pipe;
123*61046927SAndroid Build Coastguard Worker    struct pipe_screen *screen = pipe->screen;
124*61046927SAndroid Build Coastguard Worker    struct pipe_fence_handle *fence = NULL;
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker    MESA_TRACE_FUNC();
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    /* If the fence doesn't exist, assume it's signalled. */
129*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&obj->mutex);
130*61046927SAndroid Build Coastguard Worker    if (!obj->fence) {
131*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&obj->mutex);
132*61046927SAndroid Build Coastguard Worker       obj->StatusFlag = GL_TRUE;
133*61046927SAndroid Build Coastguard Worker       return;
134*61046927SAndroid Build Coastguard Worker    }
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker    /* We need a local copy of the fence pointer, so that we can call
137*61046927SAndroid Build Coastguard Worker     * fence_finish unlocked.
138*61046927SAndroid Build Coastguard Worker     */
139*61046927SAndroid Build Coastguard Worker    screen->fence_reference(screen, &fence, obj->fence);
140*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&obj->mutex);
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker    /* Section 4.1.2 of OpenGL 4.5 (Compatibility Profile) says:
143*61046927SAndroid Build Coastguard Worker     *    [...] if ClientWaitSync is called and all of the following are true:
144*61046927SAndroid Build Coastguard Worker     *    - the SYNC_FLUSH_COMMANDS_BIT bit is set in flags,
145*61046927SAndroid Build Coastguard Worker     *    - sync is unsignaled when ClientWaitSync is called,
146*61046927SAndroid Build Coastguard Worker     *    - and the calls to ClientWaitSync and FenceSync were issued from
147*61046927SAndroid Build Coastguard Worker     *      the same context,
148*61046927SAndroid Build Coastguard Worker     *    then the GL will behave as if the equivalent of Flush were inserted
149*61046927SAndroid Build Coastguard Worker     *    immediately after the creation of sync.
150*61046927SAndroid Build Coastguard Worker     *
151*61046927SAndroid Build Coastguard Worker     * Assume GL_SYNC_FLUSH_COMMANDS_BIT is always set, because applications
152*61046927SAndroid Build Coastguard Worker     * forget to set it.
153*61046927SAndroid Build Coastguard Worker     */
154*61046927SAndroid Build Coastguard Worker    if (screen->fence_finish(screen, pipe, fence, timeout)) {
155*61046927SAndroid Build Coastguard Worker       simple_mtx_lock(&obj->mutex);
156*61046927SAndroid Build Coastguard Worker       screen->fence_reference(screen, &obj->fence, NULL);
157*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&obj->mutex);
158*61046927SAndroid Build Coastguard Worker       obj->StatusFlag = GL_TRUE;
159*61046927SAndroid Build Coastguard Worker    }
160*61046927SAndroid Build Coastguard Worker    screen->fence_reference(screen, &fence, NULL);
161*61046927SAndroid Build Coastguard Worker }
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker /**
164*61046927SAndroid Build Coastguard Worker  * Check if the given sync object is:
165*61046927SAndroid Build Coastguard Worker  *  - non-null
166*61046927SAndroid Build Coastguard Worker  *  - not in sync objects hash table
167*61046927SAndroid Build Coastguard Worker  *  - not marked as deleted
168*61046927SAndroid Build Coastguard Worker  *
169*61046927SAndroid Build Coastguard Worker  * Returns the internal gl_sync_object pointer if the sync object is valid
170*61046927SAndroid Build Coastguard Worker  * or NULL if it isn't.
171*61046927SAndroid Build Coastguard Worker  *
172*61046927SAndroid Build Coastguard Worker  * If "incRefCount" is true, the reference count is incremented, which is
173*61046927SAndroid Build Coastguard Worker  * normally what you want; otherwise, a glDeleteSync from another thread
174*61046927SAndroid Build Coastguard Worker  * could delete the sync object while you are still working on it.
175*61046927SAndroid Build Coastguard Worker  */
176*61046927SAndroid Build Coastguard Worker struct gl_sync_object *
_mesa_get_and_ref_sync(struct gl_context * ctx,GLsync sync,bool incRefCount)177*61046927SAndroid Build Coastguard Worker _mesa_get_and_ref_sync(struct gl_context *ctx, GLsync sync, bool incRefCount)
178*61046927SAndroid Build Coastguard Worker {
179*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *syncObj = (struct gl_sync_object *) sync;
180*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ctx->Shared->Mutex);
181*61046927SAndroid Build Coastguard Worker    if (syncObj != NULL
182*61046927SAndroid Build Coastguard Worker       && _mesa_set_search(ctx->Shared->SyncObjects, syncObj) != NULL
183*61046927SAndroid Build Coastguard Worker       && !syncObj->DeletePending) {
184*61046927SAndroid Build Coastguard Worker      if (incRefCount) {
185*61046927SAndroid Build Coastguard Worker        syncObj->RefCount++;
186*61046927SAndroid Build Coastguard Worker      }
187*61046927SAndroid Build Coastguard Worker    } else {
188*61046927SAndroid Build Coastguard Worker      syncObj = NULL;
189*61046927SAndroid Build Coastguard Worker    }
190*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&ctx->Shared->Mutex);
191*61046927SAndroid Build Coastguard Worker    return syncObj;
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker void
_mesa_unref_sync_object(struct gl_context * ctx,struct gl_sync_object * syncObj,int amount)196*61046927SAndroid Build Coastguard Worker _mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj,
197*61046927SAndroid Build Coastguard Worker                         int amount)
198*61046927SAndroid Build Coastguard Worker {
199*61046927SAndroid Build Coastguard Worker    struct set_entry *entry;
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ctx->Shared->Mutex);
202*61046927SAndroid Build Coastguard Worker    syncObj->RefCount -= amount;
203*61046927SAndroid Build Coastguard Worker    if (syncObj->RefCount == 0) {
204*61046927SAndroid Build Coastguard Worker       entry = _mesa_set_search(ctx->Shared->SyncObjects, syncObj);
205*61046927SAndroid Build Coastguard Worker       assert (entry != NULL);
206*61046927SAndroid Build Coastguard Worker       _mesa_set_remove(ctx->Shared->SyncObjects, entry);
207*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&ctx->Shared->Mutex);
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker       delete_sync_object(ctx, syncObj);
210*61046927SAndroid Build Coastguard Worker    } else {
211*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&ctx->Shared->Mutex);
212*61046927SAndroid Build Coastguard Worker    }
213*61046927SAndroid Build Coastguard Worker }
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker GLboolean GLAPIENTRY
_mesa_IsSync(GLsync sync)217*61046927SAndroid Build Coastguard Worker _mesa_IsSync(GLsync sync)
218*61046927SAndroid Build Coastguard Worker {
219*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
220*61046927SAndroid Build Coastguard Worker    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker    return _mesa_get_and_ref_sync(ctx, sync, false) ? GL_TRUE : GL_FALSE;
223*61046927SAndroid Build Coastguard Worker }
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
delete_sync(struct gl_context * ctx,GLsync sync,bool no_error)227*61046927SAndroid Build Coastguard Worker delete_sync(struct gl_context *ctx, GLsync sync, bool no_error)
228*61046927SAndroid Build Coastguard Worker {
229*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *syncObj;
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    /* From the GL_ARB_sync spec:
232*61046927SAndroid Build Coastguard Worker     *
233*61046927SAndroid Build Coastguard Worker     *    DeleteSync will silently ignore a <sync> value of zero. An
234*61046927SAndroid Build Coastguard Worker     *    INVALID_VALUE error is generated if <sync> is neither zero nor the
235*61046927SAndroid Build Coastguard Worker     *    name of a sync object.
236*61046927SAndroid Build Coastguard Worker     */
237*61046927SAndroid Build Coastguard Worker    if (sync == 0) {
238*61046927SAndroid Build Coastguard Worker       return;
239*61046927SAndroid Build Coastguard Worker    }
240*61046927SAndroid Build Coastguard Worker 
241*61046927SAndroid Build Coastguard Worker    syncObj = _mesa_get_and_ref_sync(ctx, sync, true);
242*61046927SAndroid Build Coastguard Worker    if (!no_error && !syncObj) {
243*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
244*61046927SAndroid Build Coastguard Worker                   "glDeleteSync (not a valid sync object)");
245*61046927SAndroid Build Coastguard Worker       return;
246*61046927SAndroid Build Coastguard Worker    }
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker    /* If there are no client-waits or server-waits pending on this sync, delete
249*61046927SAndroid Build Coastguard Worker     * the underlying object. Note that we double-unref the object, as
250*61046927SAndroid Build Coastguard Worker     * _mesa_get_and_ref_sync above took an extra refcount to make sure the
251*61046927SAndroid Build Coastguard Worker     * pointer is valid for us to manipulate.
252*61046927SAndroid Build Coastguard Worker     */
253*61046927SAndroid Build Coastguard Worker    syncObj->DeletePending = GL_TRUE;
254*61046927SAndroid Build Coastguard Worker    _mesa_unref_sync_object(ctx, syncObj, 2);
255*61046927SAndroid Build Coastguard Worker }
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DeleteSync_no_error(GLsync sync)259*61046927SAndroid Build Coastguard Worker _mesa_DeleteSync_no_error(GLsync sync)
260*61046927SAndroid Build Coastguard Worker {
261*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
262*61046927SAndroid Build Coastguard Worker    delete_sync(ctx, sync, true);
263*61046927SAndroid Build Coastguard Worker }
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_DeleteSync(GLsync sync)267*61046927SAndroid Build Coastguard Worker _mesa_DeleteSync(GLsync sync)
268*61046927SAndroid Build Coastguard Worker {
269*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
270*61046927SAndroid Build Coastguard Worker    delete_sync(ctx, sync, false);
271*61046927SAndroid Build Coastguard Worker }
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker GLsync
_mesa_fence_sync(struct gl_context * ctx,GLenum condition,GLbitfield flags)275*61046927SAndroid Build Coastguard Worker _mesa_fence_sync(struct gl_context *ctx, GLenum condition, GLbitfield flags)
276*61046927SAndroid Build Coastguard Worker {
277*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *syncObj;
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    syncObj = new_sync_object(ctx);
280*61046927SAndroid Build Coastguard Worker    if (syncObj != NULL) {
281*61046927SAndroid Build Coastguard Worker       /* The name is not currently used, and it is never visible to
282*61046927SAndroid Build Coastguard Worker        * applications.  If sync support is extended to provide support for
283*61046927SAndroid Build Coastguard Worker        * NV_fence, this field will be used.  We'll also need to add an object
284*61046927SAndroid Build Coastguard Worker        * ID hashtable.
285*61046927SAndroid Build Coastguard Worker        */
286*61046927SAndroid Build Coastguard Worker       syncObj->Name = 1;
287*61046927SAndroid Build Coastguard Worker       syncObj->RefCount = 1;
288*61046927SAndroid Build Coastguard Worker       syncObj->DeletePending = GL_FALSE;
289*61046927SAndroid Build Coastguard Worker       syncObj->SyncCondition = condition;
290*61046927SAndroid Build Coastguard Worker       syncObj->Flags = flags;
291*61046927SAndroid Build Coastguard Worker       syncObj->StatusFlag = 0;
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker       assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0);
294*61046927SAndroid Build Coastguard Worker       assert(syncObj->fence == NULL);
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker       /* Deferred flush are only allowed when there's a single context. See issue 1430 */
297*61046927SAndroid Build Coastguard Worker       ctx->pipe->flush(ctx->pipe, &syncObj->fence, ctx->Shared->RefCount == 1 ? PIPE_FLUSH_DEFERRED : 0);
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker       simple_mtx_lock(&ctx->Shared->Mutex);
300*61046927SAndroid Build Coastguard Worker       _mesa_set_add(ctx->Shared->SyncObjects, syncObj);
301*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&ctx->Shared->Mutex);
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker       return (GLsync)syncObj;
304*61046927SAndroid Build Coastguard Worker    }
305*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker    return NULL;
307*61046927SAndroid Build Coastguard Worker }
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker GLsync GLAPIENTRY
_mesa_FenceSync_no_error(GLenum condition,GLbitfield flags)311*61046927SAndroid Build Coastguard Worker _mesa_FenceSync_no_error(GLenum condition, GLbitfield flags)
312*61046927SAndroid Build Coastguard Worker {
313*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
314*61046927SAndroid Build Coastguard Worker    return _mesa_fence_sync(ctx, condition, flags);
315*61046927SAndroid Build Coastguard Worker }
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker 
318*61046927SAndroid Build Coastguard Worker GLsync GLAPIENTRY
_mesa_FenceSync(GLenum condition,GLbitfield flags)319*61046927SAndroid Build Coastguard Worker _mesa_FenceSync(GLenum condition, GLbitfield flags)
320*61046927SAndroid Build Coastguard Worker {
321*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
322*61046927SAndroid Build Coastguard Worker    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker    if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
325*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_ENUM, "glFenceSync(condition=0x%x)",
326*61046927SAndroid Build Coastguard Worker                   condition);
327*61046927SAndroid Build Coastguard Worker       return 0;
328*61046927SAndroid Build Coastguard Worker    }
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker    if (flags != 0) {
331*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "glFenceSync(flags=0x%x)", condition);
332*61046927SAndroid Build Coastguard Worker       return 0;
333*61046927SAndroid Build Coastguard Worker    }
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker    return _mesa_fence_sync(ctx, condition, flags);
336*61046927SAndroid Build Coastguard Worker }
337*61046927SAndroid Build Coastguard Worker 
338*61046927SAndroid Build Coastguard Worker 
339*61046927SAndroid Build Coastguard Worker static GLenum
client_wait_sync(struct gl_context * ctx,struct gl_sync_object * syncObj,GLbitfield flags,GLuint64 timeout)340*61046927SAndroid Build Coastguard Worker client_wait_sync(struct gl_context *ctx, struct gl_sync_object *syncObj,
341*61046927SAndroid Build Coastguard Worker                  GLbitfield flags, GLuint64 timeout)
342*61046927SAndroid Build Coastguard Worker {
343*61046927SAndroid Build Coastguard Worker    GLenum ret;
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker    /* From the GL_ARB_sync spec:
346*61046927SAndroid Build Coastguard Worker     *
347*61046927SAndroid Build Coastguard Worker     *    ClientWaitSync returns one of four status values. A return value of
348*61046927SAndroid Build Coastguard Worker     *    ALREADY_SIGNALED indicates that <sync> was signaled at the time
349*61046927SAndroid Build Coastguard Worker     *    ClientWaitSync was called. ALREADY_SIGNALED will always be returned
350*61046927SAndroid Build Coastguard Worker     *    if <sync> was signaled, even if the value of <timeout> is zero.
351*61046927SAndroid Build Coastguard Worker     */
352*61046927SAndroid Build Coastguard Worker    __client_wait_sync(ctx, syncObj, 0, 0);
353*61046927SAndroid Build Coastguard Worker    if (syncObj->StatusFlag) {
354*61046927SAndroid Build Coastguard Worker       ret = GL_ALREADY_SIGNALED;
355*61046927SAndroid Build Coastguard Worker    } else {
356*61046927SAndroid Build Coastguard Worker       if (timeout == 0) {
357*61046927SAndroid Build Coastguard Worker          ret = GL_TIMEOUT_EXPIRED;
358*61046927SAndroid Build Coastguard Worker       } else {
359*61046927SAndroid Build Coastguard Worker          __client_wait_sync(ctx, syncObj, flags, timeout);
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker          ret = syncObj->StatusFlag
362*61046927SAndroid Build Coastguard Worker             ? GL_CONDITION_SATISFIED : GL_TIMEOUT_EXPIRED;
363*61046927SAndroid Build Coastguard Worker       }
364*61046927SAndroid Build Coastguard Worker    }
365*61046927SAndroid Build Coastguard Worker 
366*61046927SAndroid Build Coastguard Worker    _mesa_unref_sync_object(ctx, syncObj, 1);
367*61046927SAndroid Build Coastguard Worker    return ret;
368*61046927SAndroid Build Coastguard Worker }
369*61046927SAndroid Build Coastguard Worker 
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker GLenum GLAPIENTRY
_mesa_ClientWaitSync_no_error(GLsync sync,GLbitfield flags,GLuint64 timeout)372*61046927SAndroid Build Coastguard Worker _mesa_ClientWaitSync_no_error(GLsync sync, GLbitfield flags, GLuint64 timeout)
373*61046927SAndroid Build Coastguard Worker {
374*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *syncObj = _mesa_get_and_ref_sync(ctx, sync, true);
377*61046927SAndroid Build Coastguard Worker    return client_wait_sync(ctx, syncObj, flags, timeout);
378*61046927SAndroid Build Coastguard Worker }
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker GLenum GLAPIENTRY
_mesa_ClientWaitSync(GLsync sync,GLbitfield flags,GLuint64 timeout)382*61046927SAndroid Build Coastguard Worker _mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
383*61046927SAndroid Build Coastguard Worker {
384*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
385*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *syncObj;
386*61046927SAndroid Build Coastguard Worker 
387*61046927SAndroid Build Coastguard Worker    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_WAIT_FAILED);
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    if ((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) != 0) {
390*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "glClientWaitSync(flags=0x%x)", flags);
391*61046927SAndroid Build Coastguard Worker       return GL_WAIT_FAILED;
392*61046927SAndroid Build Coastguard Worker    }
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker    syncObj = _mesa_get_and_ref_sync(ctx, sync, true);
395*61046927SAndroid Build Coastguard Worker    if (!syncObj) {
396*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
397*61046927SAndroid Build Coastguard Worker                   "glClientWaitSync (not a valid sync object)");
398*61046927SAndroid Build Coastguard Worker       return GL_WAIT_FAILED;
399*61046927SAndroid Build Coastguard Worker    }
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker    return client_wait_sync(ctx, syncObj, flags, timeout);
402*61046927SAndroid Build Coastguard Worker }
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker static void
wait_sync(struct gl_context * ctx,struct gl_sync_object * syncObj,GLbitfield flags,GLuint64 timeout)406*61046927SAndroid Build Coastguard Worker wait_sync(struct gl_context *ctx, struct gl_sync_object *syncObj,
407*61046927SAndroid Build Coastguard Worker           GLbitfield flags, GLuint64 timeout)
408*61046927SAndroid Build Coastguard Worker {
409*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = ctx->pipe;
410*61046927SAndroid Build Coastguard Worker    struct pipe_screen *screen = pipe->screen;
411*61046927SAndroid Build Coastguard Worker    struct pipe_fence_handle *fence = NULL;
412*61046927SAndroid Build Coastguard Worker 
413*61046927SAndroid Build Coastguard Worker    /* Nothing needs to be done here if the driver does not support async
414*61046927SAndroid Build Coastguard Worker     * flushes. */
415*61046927SAndroid Build Coastguard Worker    if (!pipe->fence_server_sync) {
416*61046927SAndroid Build Coastguard Worker       _mesa_unref_sync_object(ctx, syncObj, 1);
417*61046927SAndroid Build Coastguard Worker       return;
418*61046927SAndroid Build Coastguard Worker    }
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker    /* If the fence doesn't exist, assume it's signalled. */
421*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&syncObj->mutex);
422*61046927SAndroid Build Coastguard Worker    if (!syncObj->fence) {
423*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&syncObj->mutex);
424*61046927SAndroid Build Coastguard Worker       syncObj->StatusFlag = GL_TRUE;
425*61046927SAndroid Build Coastguard Worker       _mesa_unref_sync_object(ctx, syncObj, 1);
426*61046927SAndroid Build Coastguard Worker       return;
427*61046927SAndroid Build Coastguard Worker    }
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker    /* We need a local copy of the fence pointer. */
430*61046927SAndroid Build Coastguard Worker    screen->fence_reference(screen, &fence, syncObj->fence);
431*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&syncObj->mutex);
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker    pipe->fence_server_sync(pipe, fence);
434*61046927SAndroid Build Coastguard Worker    screen->fence_reference(screen, &fence, NULL);
435*61046927SAndroid Build Coastguard Worker    _mesa_unref_sync_object(ctx, syncObj, 1);
436*61046927SAndroid Build Coastguard Worker }
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker 
439*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_WaitSync_no_error(GLsync sync,GLbitfield flags,GLuint64 timeout)440*61046927SAndroid Build Coastguard Worker _mesa_WaitSync_no_error(GLsync sync, GLbitfield flags, GLuint64 timeout)
441*61046927SAndroid Build Coastguard Worker {
442*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *syncObj = _mesa_get_and_ref_sync(ctx, sync, true);
445*61046927SAndroid Build Coastguard Worker    wait_sync(ctx, syncObj, flags, timeout);
446*61046927SAndroid Build Coastguard Worker }
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_WaitSync(GLsync sync,GLbitfield flags,GLuint64 timeout)450*61046927SAndroid Build Coastguard Worker _mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
451*61046927SAndroid Build Coastguard Worker {
452*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
453*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *syncObj;
454*61046927SAndroid Build Coastguard Worker 
455*61046927SAndroid Build Coastguard Worker    if (flags != 0) {
456*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "glWaitSync(flags=0x%x)", flags);
457*61046927SAndroid Build Coastguard Worker       return;
458*61046927SAndroid Build Coastguard Worker    }
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker    if (timeout != GL_TIMEOUT_IGNORED) {
461*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "glWaitSync(timeout=0x%" PRIx64 ")",
462*61046927SAndroid Build Coastguard Worker                   (uint64_t) timeout);
463*61046927SAndroid Build Coastguard Worker       return;
464*61046927SAndroid Build Coastguard Worker    }
465*61046927SAndroid Build Coastguard Worker 
466*61046927SAndroid Build Coastguard Worker    syncObj = _mesa_get_and_ref_sync(ctx, sync, true);
467*61046927SAndroid Build Coastguard Worker    if (!syncObj) {
468*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
469*61046927SAndroid Build Coastguard Worker                   "glWaitSync (not a valid sync object)");
470*61046927SAndroid Build Coastguard Worker       return;
471*61046927SAndroid Build Coastguard Worker    }
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker    wait_sync(ctx, syncObj, flags, timeout);
474*61046927SAndroid Build Coastguard Worker }
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_GetSynciv(GLsync sync,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * values)478*61046927SAndroid Build Coastguard Worker _mesa_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
479*61046927SAndroid Build Coastguard Worker                 GLint *values)
480*61046927SAndroid Build Coastguard Worker {
481*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
482*61046927SAndroid Build Coastguard Worker    struct gl_sync_object *syncObj;
483*61046927SAndroid Build Coastguard Worker    GLsizei size = 0;
484*61046927SAndroid Build Coastguard Worker    GLint v[1];
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker    syncObj = _mesa_get_and_ref_sync(ctx, sync, true);
487*61046927SAndroid Build Coastguard Worker    if (!syncObj) {
488*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE,
489*61046927SAndroid Build Coastguard Worker                   "glGetSynciv (not a valid sync object)");
490*61046927SAndroid Build Coastguard Worker       return;
491*61046927SAndroid Build Coastguard Worker    }
492*61046927SAndroid Build Coastguard Worker 
493*61046927SAndroid Build Coastguard Worker    switch (pname) {
494*61046927SAndroid Build Coastguard Worker    case GL_OBJECT_TYPE:
495*61046927SAndroid Build Coastguard Worker       v[0] = GL_SYNC_FENCE;
496*61046927SAndroid Build Coastguard Worker       size = 1;
497*61046927SAndroid Build Coastguard Worker       break;
498*61046927SAndroid Build Coastguard Worker 
499*61046927SAndroid Build Coastguard Worker    case GL_SYNC_CONDITION:
500*61046927SAndroid Build Coastguard Worker       v[0] = syncObj->SyncCondition;
501*61046927SAndroid Build Coastguard Worker       size = 1;
502*61046927SAndroid Build Coastguard Worker       break;
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker    case GL_SYNC_STATUS:
505*61046927SAndroid Build Coastguard Worker       /* Update the state of the sync by dipping into the driver.  Note that
506*61046927SAndroid Build Coastguard Worker        * this call won't block.  It just updates state in the common object
507*61046927SAndroid Build Coastguard Worker        * data from the current driver state.
508*61046927SAndroid Build Coastguard Worker        */
509*61046927SAndroid Build Coastguard Worker       __client_wait_sync(ctx, syncObj, 0, 0);
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker       v[0] = (syncObj->StatusFlag) ? GL_SIGNALED : GL_UNSIGNALED;
512*61046927SAndroid Build Coastguard Worker       size = 1;
513*61046927SAndroid Build Coastguard Worker       break;
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    case GL_SYNC_FLAGS:
516*61046927SAndroid Build Coastguard Worker       v[0] = syncObj->Flags;
517*61046927SAndroid Build Coastguard Worker       size = 1;
518*61046927SAndroid Build Coastguard Worker       break;
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker    default:
521*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_ENUM, "glGetSynciv(pname=0x%x)\n", pname);
522*61046927SAndroid Build Coastguard Worker       _mesa_unref_sync_object(ctx, syncObj, 1);
523*61046927SAndroid Build Coastguard Worker       return;
524*61046927SAndroid Build Coastguard Worker    }
525*61046927SAndroid Build Coastguard Worker 
526*61046927SAndroid Build Coastguard Worker    /* Section 4.1.3 (Sync Object Queries) of the OpenGL ES 3.10 spec says:
527*61046927SAndroid Build Coastguard Worker     *
528*61046927SAndroid Build Coastguard Worker     *    "An INVALID_VALUE error is generated if bufSize is negative."
529*61046927SAndroid Build Coastguard Worker     */
530*61046927SAndroid Build Coastguard Worker    if (bufSize < 0) {
531*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_VALUE, "glGetSynciv(pname=0x%x)\n", pname);
532*61046927SAndroid Build Coastguard Worker    }
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker    if (size > 0 && bufSize > 0) {
535*61046927SAndroid Build Coastguard Worker       const GLsizei copy_count = MIN2(size, bufSize);
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker       memcpy(values, v, sizeof(GLint) * copy_count);
538*61046927SAndroid Build Coastguard Worker    }
539*61046927SAndroid Build Coastguard Worker 
540*61046927SAndroid Build Coastguard Worker    if (length != NULL) {
541*61046927SAndroid Build Coastguard Worker       *length = size;
542*61046927SAndroid Build Coastguard Worker    }
543*61046927SAndroid Build Coastguard Worker 
544*61046927SAndroid Build Coastguard Worker    _mesa_unref_sync_object(ctx, syncObj, 1);
545*61046927SAndroid Build Coastguard Worker }
546