Home | History | Annotate | Download | only in main
      1 /*
      2  * Copyright  2009 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 /**
     25  * \file syncobj.c
     26  * Sync object management.
     27  *
     28  * Unlike textures and other objects that are shared between contexts, sync
     29  * objects are not bound to the context.  As a result, the reference counting
     30  * and delete behavior of sync objects is slightly different.  References to
     31  * sync objects are added:
     32  *
     33  *    - By \c glFencSynce.  This sets the initial reference count to 1.
     34  *    - At the start of \c glClientWaitSync.  The reference is held for the
     35  *      duration of the wait call.
     36  *
     37  * References are removed:
     38  *
     39  *    - By \c glDeleteSync.
     40  *    - At the end of \c glClientWaitSync.
     41  *
     42  * Additionally, drivers may call \c _mesa_ref_sync_object and
     43  * \c _mesa_unref_sync_object as needed to implement \c ServerWaitSync.
     44  *
     45  * As with shader objects, sync object names become invalid as soon as
     46  * \c glDeleteSync is called.  For this reason \c glDeleteSync sets the
     47  * \c DeletePending flag.  All functions validate object handles by testing
     48  * this flag.
     49  *
     50  * \note
     51  * Only \c GL_ARB_sync objects are shared between contexts.  If support is ever
     52  * added for either \c GL_NV_fence or \c GL_APPLE_fence different semantics
     53  * will need to be implemented.
     54  *
     55  * \author Ian Romanick <ian.d.romanick (at) intel.com>
     56  */
     57 
     58 #include "glheader.h"
     59 #include "imports.h"
     60 #include "context.h"
     61 #include "macros.h"
     62 #include "mfeatures.h"
     63 #include "get.h"
     64 #include "dispatch.h"
     65 #include "mtypes.h"
     66 
     67 #if FEATURE_ARB_sync
     68 #include "syncobj.h"
     69 
     70 static struct gl_sync_object *
     71 _mesa_new_sync_object(struct gl_context *ctx, GLenum type)
     72 {
     73    struct gl_sync_object *s = MALLOC_STRUCT(gl_sync_object);
     74    (void) ctx;
     75    (void) type;
     76 
     77    return s;
     78 }
     79 
     80 
     81 static void
     82 _mesa_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
     83 {
     84    (void) ctx;
     85    free(syncObj);
     86 }
     87 
     88 
     89 static void
     90 _mesa_fence_sync(struct gl_context *ctx, struct gl_sync_object *syncObj,
     91 		 GLenum condition, GLbitfield flags)
     92 {
     93    (void) ctx;
     94    (void) condition;
     95    (void) flags;
     96 
     97    syncObj->StatusFlag = 1;
     98 }
     99 
    100 
    101 static void
    102 _mesa_check_sync(struct gl_context *ctx, struct gl_sync_object *syncObj)
    103 {
    104    (void) ctx;
    105    (void) syncObj;
    106 
    107    /* No-op for software rendering.  Hardware drivers will need to determine
    108     * whether the state of the sync object has changed.
    109     */
    110 }
    111 
    112 
    113 static void
    114 _mesa_wait_sync(struct gl_context *ctx, struct gl_sync_object *syncObj,
    115 		GLbitfield flags, GLuint64 timeout)
    116 {
    117    (void) ctx;
    118    (void) syncObj;
    119    (void) flags;
    120    (void) timeout;
    121 
    122    /* No-op for software rendering.  Hardware drivers will need to wait until
    123     * the state of the sync object changes or the timeout expires.
    124     */
    125 }
    126 
    127 
    128 void
    129 _mesa_init_sync_object_functions(struct dd_function_table *driver)
    130 {
    131    driver->NewSyncObject = _mesa_new_sync_object;
    132    driver->FenceSync = _mesa_fence_sync;
    133    driver->DeleteSyncObject = _mesa_delete_sync_object;
    134    driver->CheckSync = _mesa_check_sync;
    135 
    136    /* Use the same no-op wait function for both.
    137     */
    138    driver->ClientWaitSync = _mesa_wait_sync;
    139    driver->ServerWaitSync = _mesa_wait_sync;
    140 }
    141 
    142 
    143 void
    144 _mesa_init_sync_dispatch(struct _glapi_table *disp)
    145 {
    146    SET_IsSync(disp, _mesa_IsSync);
    147    SET_DeleteSync(disp, _mesa_DeleteSync);
    148    SET_FenceSync(disp, _mesa_FenceSync);
    149    SET_ClientWaitSync(disp, _mesa_ClientWaitSync);
    150    SET_WaitSync(disp, _mesa_WaitSync);
    151    SET_GetInteger64v(disp, _mesa_GetInteger64v);
    152    SET_GetSynciv(disp, _mesa_GetSynciv);
    153 }
    154 
    155 
    156 /**
    157  * Allocate/init the context state related to sync objects.
    158  */
    159 void
    160 _mesa_init_sync(struct gl_context *ctx)
    161 {
    162    (void) ctx;
    163 }
    164 
    165 
    166 /**
    167  * Free the context state related to sync objects.
    168  */
    169 void
    170 _mesa_free_sync_data(struct gl_context *ctx)
    171 {
    172    (void) ctx;
    173 }
    174 
    175 
    176 static int
    177 _mesa_validate_sync(struct gl_sync_object *syncObj)
    178 {
    179    return (syncObj != NULL)
    180       && (syncObj->Type == GL_SYNC_FENCE)
    181       && !syncObj->DeletePending;
    182 }
    183 
    184 
    185 void
    186 _mesa_ref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
    187 {
    188    _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
    189    syncObj->RefCount++;
    190    _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
    191 }
    192 
    193 
    194 void
    195 _mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj)
    196 {
    197    _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
    198    syncObj->RefCount--;
    199    if (syncObj->RefCount == 0) {
    200       remove_from_list(& syncObj->link);
    201       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
    202 
    203       ctx->Driver.DeleteSyncObject(ctx, syncObj);
    204    } else {
    205       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
    206    }
    207 }
    208 
    209 
    210 GLboolean GLAPIENTRY
    211 _mesa_IsSync(GLsync sync)
    212 {
    213    GET_CURRENT_CONTEXT(ctx);
    214    struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
    215    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
    216 
    217    return _mesa_validate_sync(syncObj) ? GL_TRUE : GL_FALSE;
    218 }
    219 
    220 
    221 void GLAPIENTRY
    222 _mesa_DeleteSync(GLsync sync)
    223 {
    224    GET_CURRENT_CONTEXT(ctx);
    225    struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
    226    ASSERT_OUTSIDE_BEGIN_END(ctx);
    227 
    228    /* From the GL_ARB_sync spec:
    229     *
    230     *    DeleteSync will silently ignore a <sync> value of zero. An
    231     *    INVALID_VALUE error is generated if <sync> is neither zero nor the
    232     *    name of a sync object.
    233     */
    234    if (sync == 0) {
    235       return;
    236    }
    237 
    238    if (!_mesa_validate_sync(syncObj)) {
    239       _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteSync");
    240       return;
    241    }
    242 
    243    /* If there are no client-waits or server-waits pending on this sync, delete
    244     * the underlying object.
    245     */
    246    syncObj->DeletePending = GL_TRUE;
    247    _mesa_unref_sync_object(ctx, syncObj);
    248 }
    249 
    250 
    251 GLsync GLAPIENTRY
    252 _mesa_FenceSync(GLenum condition, GLbitfield flags)
    253 {
    254    GET_CURRENT_CONTEXT(ctx);
    255    struct gl_sync_object *syncObj;
    256    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
    257 
    258    if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
    259       _mesa_error(ctx, GL_INVALID_ENUM, "glFenceSync(condition=0x%x)",
    260 		  condition);
    261       return 0;
    262    }
    263 
    264    if (flags != 0) {
    265       _mesa_error(ctx, GL_INVALID_VALUE, "glFenceSync(flags=0x%x)",
    266 		  condition);
    267       return 0;
    268    }
    269 
    270    syncObj = ctx->Driver.NewSyncObject(ctx, GL_SYNC_FENCE);
    271    if (syncObj != NULL) {
    272       syncObj->Type = GL_SYNC_FENCE;
    273       /* The name is not currently used, and it is never visible to
    274        * applications.  If sync support is extended to provide support for
    275        * NV_fence, this field will be used.  We'll also need to add an object
    276        * ID hashtable.
    277        */
    278       syncObj->Name = 1;
    279       syncObj->RefCount = 1;
    280       syncObj->DeletePending = GL_FALSE;
    281       syncObj->SyncCondition = condition;
    282       syncObj->Flags = flags;
    283       syncObj->StatusFlag = 0;
    284 
    285       ctx->Driver.FenceSync(ctx, syncObj, condition, flags);
    286 
    287       _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
    288       insert_at_tail(& ctx->Shared->SyncObjects, & syncObj->link);
    289       _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
    290 
    291       return (GLsync) syncObj;
    292    }
    293 
    294    return NULL;
    295 }
    296 
    297 
    298 GLenum GLAPIENTRY
    299 _mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
    300 {
    301    GET_CURRENT_CONTEXT(ctx);
    302    struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
    303    GLenum ret;
    304    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_WAIT_FAILED);
    305 
    306    if (!_mesa_validate_sync(syncObj)) {
    307       _mesa_error(ctx, GL_INVALID_OPERATION, "glClientWaitSync");
    308       return GL_WAIT_FAILED;
    309    }
    310 
    311    if ((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) != 0) {
    312       _mesa_error(ctx, GL_INVALID_ENUM, "glClientWaitSync(flags=0x%x)", flags);
    313       return GL_WAIT_FAILED;
    314    }
    315 
    316    _mesa_ref_sync_object(ctx, syncObj);
    317 
    318    /* From the GL_ARB_sync spec:
    319     *
    320     *    ClientWaitSync returns one of four status values. A return value of
    321     *    ALREADY_SIGNALED indicates that <sync> was signaled at the time
    322     *    ClientWaitSync was called. ALREADY_SIGNALED will always be returned
    323     *    if <sync> was signaled, even if the value of <timeout> is zero.
    324     */
    325    ctx->Driver.CheckSync(ctx, syncObj);
    326    if (syncObj->StatusFlag) {
    327       ret = GL_ALREADY_SIGNALED;
    328    } else {
    329       if (timeout == 0) {
    330          ret = GL_TIMEOUT_EXPIRED;
    331       } else {
    332          ctx->Driver.ClientWaitSync(ctx, syncObj, flags, timeout);
    333 
    334          ret = syncObj->StatusFlag ? GL_CONDITION_SATISFIED : GL_TIMEOUT_EXPIRED;
    335       }
    336    }
    337 
    338    _mesa_unref_sync_object(ctx, syncObj);
    339    return ret;
    340 }
    341 
    342 
    343 void GLAPIENTRY
    344 _mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
    345 {
    346    GET_CURRENT_CONTEXT(ctx);
    347    struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
    348    ASSERT_OUTSIDE_BEGIN_END(ctx);
    349 
    350    if (!_mesa_validate_sync(syncObj)) {
    351       _mesa_error(ctx, GL_INVALID_OPERATION, "glWaitSync");
    352       return;
    353    }
    354 
    355    if (flags != 0) {
    356       _mesa_error(ctx, GL_INVALID_ENUM, "glWaitSync(flags=0x%x)", flags);
    357       return;
    358    }
    359 
    360    /* From the GL_ARB_sync spec:
    361     *
    362     *     If the value of <timeout> is zero, then WaitSync does nothing.
    363     */
    364    if (timeout == 0) {
    365       return;
    366    }
    367 
    368    ctx->Driver.ServerWaitSync(ctx, syncObj, flags, timeout);
    369 }
    370 
    371 
    372 void GLAPIENTRY
    373 _mesa_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
    374 		GLint *values)
    375 {
    376    GET_CURRENT_CONTEXT(ctx);
    377    struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
    378    GLsizei size = 0;
    379    GLint v[1];
    380    ASSERT_OUTSIDE_BEGIN_END(ctx);
    381 
    382    if (!_mesa_validate_sync(syncObj)) {
    383       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSynciv");
    384       return;
    385    }
    386 
    387    switch (pname) {
    388    case GL_OBJECT_TYPE:
    389       v[0] = syncObj->Type;
    390       size = 1;
    391       break;
    392 
    393    case GL_SYNC_CONDITION:
    394       v[0] = syncObj->SyncCondition;
    395       size = 1;
    396       break;
    397 
    398    case GL_SYNC_STATUS:
    399       /* Update the state of the sync by dipping into the driver.  Note that
    400        * this call won't block.  It just updates state in the common object
    401        * data from the current driver state.
    402        */
    403       ctx->Driver.CheckSync(ctx, syncObj);
    404 
    405       v[0] = (syncObj->StatusFlag) ? GL_SIGNALED : GL_UNSIGNALED;
    406       size = 1;
    407       break;
    408 
    409    case GL_SYNC_FLAGS:
    410       v[0] = syncObj->Flags;
    411       size = 1;
    412       break;
    413 
    414    default:
    415       _mesa_error(ctx, GL_INVALID_ENUM, "glGetSynciv(pname=0x%x)\n", pname);
    416       return;
    417    }
    418 
    419    if (size > 0) {
    420       const GLsizei copy_count = MIN2(size, bufSize);
    421 
    422       memcpy(values, v, sizeof(GLint) * copy_count);
    423    }
    424 
    425    if (length != NULL) {
    426       *length = size;
    427    }
    428 }
    429 
    430 #endif /* FEATURE_ARB_sync */
    431