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