Home | History | Annotate | Download | only in intel
      1 /*
      2  * Copyright  2008 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 DEALINGS
     21  * IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *    Eric Anholt <eric (at) anholt.net>
     25  *
     26  */
     27 
     28 /** @file intel_syncobj.c
     29  *
     30  * Support for ARB_sync
     31  *
     32  * ARB_sync is implemented by flushing the current batchbuffer and keeping a
     33  * reference on it.  We can then check for completion or wait for completion
     34  * using the normal buffer object mechanisms.  This does mean that if an
     35  * application is using many sync objects, it will emit small batchbuffers
     36  * which may end up being a significant overhead.  In other tests of removing
     37  * gratuitous batchbuffer syncs in Mesa, it hasn't appeared to be a significant
     38  * performance bottleneck, though.
     39  */
     40 
     41 #include "main/simple_list.h"
     42 #include "main/imports.h"
     43 
     44 #include "intel_context.h"
     45 #include "intel_batchbuffer.h"
     46 #include "intel_reg.h"
     47 
     48 static struct gl_sync_object *
     49 intel_new_sync_object(struct gl_context *ctx, GLuint id)
     50 {
     51    struct intel_sync_object *sync;
     52 
     53    sync = calloc(1, sizeof(struct intel_sync_object));
     54 
     55    return &sync->Base;
     56 }
     57 
     58 static void
     59 intel_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *s)
     60 {
     61    struct intel_sync_object *sync = (struct intel_sync_object *)s;
     62 
     63    drm_intel_bo_unreference(sync->bo);
     64    free(sync);
     65 }
     66 
     67 static void
     68 intel_fence_sync(struct gl_context *ctx, struct gl_sync_object *s,
     69 	       GLenum condition, GLbitfield flags)
     70 {
     71    struct intel_context *intel = intel_context(ctx);
     72    struct intel_sync_object *sync = (struct intel_sync_object *)s;
     73 
     74    assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
     75    intel_batchbuffer_emit_mi_flush(intel);
     76 
     77    sync->bo = intel->batch.bo;
     78    drm_intel_bo_reference(sync->bo);
     79 
     80    intel_flush(ctx);
     81 }
     82 
     83 /* We ignore the user-supplied timeout.  This is weaselly -- we're allowed to
     84  * round to an implementation-dependent accuracy, and right now our
     85  * implementation "rounds" to the wait-forever value.
     86  *
     87  * The fix would be a new kernel function to do the GTT transition with a
     88  * timeout.
     89  */
     90 static void intel_client_wait_sync(struct gl_context *ctx, struct gl_sync_object *s,
     91 				 GLbitfield flags, GLuint64 timeout)
     92 {
     93    struct intel_sync_object *sync = (struct intel_sync_object *)s;
     94 
     95    if (sync->bo) {
     96       drm_intel_bo_wait_rendering(sync->bo);
     97       s->StatusFlag = 1;
     98       drm_intel_bo_unreference(sync->bo);
     99       sync->bo = NULL;
    100    }
    101 }
    102 
    103 /* We have nothing to do for WaitSync.  Our GL command stream is sequential,
    104  * so given that the sync object has already flushed the batchbuffer,
    105  * any batchbuffers coming after this waitsync will naturally not occur until
    106  * the previous one is done.
    107  */
    108 static void intel_server_wait_sync(struct gl_context *ctx, struct gl_sync_object *s,
    109 				 GLbitfield flags, GLuint64 timeout)
    110 {
    111 }
    112 
    113 static void intel_check_sync(struct gl_context *ctx, struct gl_sync_object *s)
    114 {
    115    struct intel_sync_object *sync = (struct intel_sync_object *)s;
    116 
    117    if (sync->bo && !drm_intel_bo_busy(sync->bo)) {
    118       drm_intel_bo_unreference(sync->bo);
    119       sync->bo = NULL;
    120       s->StatusFlag = 1;
    121    }
    122 }
    123 
    124 void intel_init_syncobj_functions(struct dd_function_table *functions)
    125 {
    126    functions->NewSyncObject = intel_new_sync_object;
    127    functions->DeleteSyncObject = intel_delete_sync_object;
    128    functions->FenceSync = intel_fence_sync;
    129    functions->CheckSync = intel_check_sync;
    130    functions->ClientWaitSync = intel_client_wait_sync;
    131    functions->ServerWaitSync = intel_server_wait_sync;
    132 }
    133