Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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@anholt.net>
  25.  *
  26.  */
  27.  
  28. /**
  29.  * \file
  30.  * \brief Support for GL_ARB_sync and EGL_KHR_fence_sync.
  31.  *
  32.  * GL_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/imports.h"
  42.  
  43. #include "brw_context.h"
  44. #include "intel_batchbuffer.h"
  45. #include "intel_reg.h"
  46.  
  47. struct brw_fence {
  48.    /** The fence waits for completion of this batch. */
  49.    drm_intel_bo *batch_bo;
  50.  
  51.    bool signalled;
  52. };
  53.  
  54. struct intel_gl_sync_object {
  55.    struct gl_sync_object Base;
  56.    struct brw_fence fence;
  57. };
  58.  
  59. static void
  60. brw_fence_finish(struct brw_fence *fence)
  61. {
  62.    if (fence->batch_bo)
  63.       drm_intel_bo_unreference(fence->batch_bo);
  64. }
  65.  
  66. static void
  67. brw_fence_insert(struct brw_context *brw, struct brw_fence *fence)
  68. {
  69.    assert(!fence->batch_bo);
  70.    assert(!fence->signalled);
  71.  
  72.    intel_batchbuffer_emit_mi_flush(brw);
  73.    fence->batch_bo = brw->batch.bo;
  74.    drm_intel_bo_reference(fence->batch_bo);
  75.    intel_batchbuffer_flush(brw);
  76. }
  77.  
  78. static bool
  79. brw_fence_has_completed(struct brw_fence *fence)
  80. {
  81.    if (fence->signalled)
  82.       return true;
  83.  
  84.    if (fence->batch_bo && !drm_intel_bo_busy(fence->batch_bo)) {
  85.       drm_intel_bo_unreference(fence->batch_bo);
  86.       fence->batch_bo = NULL;
  87.       fence->signalled = true;
  88.       return true;
  89.    }
  90.  
  91.    return false;
  92. }
  93.  
  94. /**
  95.  * Return true if the function successfully signals or has already signalled.
  96.  * (This matches the behavior expected from __DRI2fence::client_wait_sync).
  97.  */
  98. static bool
  99. brw_fence_client_wait(struct brw_context *brw, struct brw_fence *fence,
  100.                       uint64_t timeout)
  101. {
  102.    if (fence->signalled)
  103.       return true;
  104.  
  105.    assert(fence->batch_bo);
  106.  
  107.    /* DRM_IOCTL_I915_GEM_WAIT uses a signed 64 bit timeout and returns
  108.     * immediately for timeouts <= 0.  The best we can do is to clamp the
  109.     * timeout to INT64_MAX.  This limits the maximum timeout from 584 years to
  110.     * 292 years - likely not a big deal.
  111.     */
  112.    if (timeout > INT64_MAX)
  113.       timeout = INT64_MAX;
  114.  
  115.    if (drm_intel_gem_bo_wait(fence->batch_bo, timeout) != 0)
  116.       return false;
  117.  
  118.    fence->signalled = true;
  119.    drm_intel_bo_unreference(fence->batch_bo);
  120.    fence->batch_bo = NULL;
  121.  
  122.    return true;
  123. }
  124.  
  125. static void
  126. brw_fence_server_wait(struct brw_context *brw, struct brw_fence *fence)
  127. {
  128.    /* We have nothing to do for WaitSync.  Our GL command stream is sequential,
  129.     * so given that the sync object has already flushed the batchbuffer, any
  130.     * batchbuffers coming after this waitsync will naturally not occur until
  131.     * the previous one is done.
  132.     */
  133. }
  134.  
  135. static struct gl_sync_object *
  136. intel_gl_new_sync_object(struct gl_context *ctx, GLuint id)
  137. {
  138.    struct intel_gl_sync_object *sync;
  139.  
  140.    sync = calloc(1, sizeof(*sync));
  141.    if (!sync)
  142.       return NULL;
  143.  
  144.    return &sync->Base;
  145. }
  146.  
  147. static void
  148. intel_gl_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *s)
  149. {
  150.    struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
  151.  
  152.    brw_fence_finish(&sync->fence);
  153.    free(sync);
  154. }
  155.  
  156. static void
  157. intel_gl_fence_sync(struct gl_context *ctx, struct gl_sync_object *s,
  158.                     GLenum condition, GLbitfield flags)
  159. {
  160.    struct brw_context *brw = brw_context(ctx);
  161.    struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
  162.  
  163.    brw_fence_insert(brw, &sync->fence);
  164. }
  165.  
  166. static void
  167. intel_gl_client_wait_sync(struct gl_context *ctx, struct gl_sync_object *s,
  168.                           GLbitfield flags, GLuint64 timeout)
  169. {
  170.    struct brw_context *brw = brw_context(ctx);
  171.    struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
  172.  
  173.    if (brw_fence_client_wait(brw, &sync->fence, timeout))
  174.       s->StatusFlag = 1;
  175. }
  176.  
  177. static void
  178. intel_gl_server_wait_sync(struct gl_context *ctx, struct gl_sync_object *s,
  179.                           GLbitfield flags, GLuint64 timeout)
  180. {
  181.    struct brw_context *brw = brw_context(ctx);
  182.    struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
  183.  
  184.    brw_fence_server_wait(brw, &sync->fence);
  185. }
  186.  
  187. static void
  188. intel_gl_check_sync(struct gl_context *ctx, struct gl_sync_object *s)
  189. {
  190.    struct intel_gl_sync_object *sync = (struct intel_gl_sync_object *)s;
  191.  
  192.    if (brw_fence_has_completed(&sync->fence))
  193.       s->StatusFlag = 1;
  194. }
  195.  
  196. void
  197. intel_init_syncobj_functions(struct dd_function_table *functions)
  198. {
  199.    functions->NewSyncObject = intel_gl_new_sync_object;
  200.    functions->DeleteSyncObject = intel_gl_delete_sync_object;
  201.    functions->FenceSync = intel_gl_fence_sync;
  202.    functions->CheckSync = intel_gl_check_sync;
  203.    functions->ClientWaitSync = intel_gl_client_wait_sync;
  204.    functions->ServerWaitSync = intel_gl_server_wait_sync;
  205. }
  206.  
  207. static void *
  208. intel_dri_create_fence(__DRIcontext *ctx)
  209. {
  210.    struct brw_context *brw = ctx->driverPrivate;
  211.    struct brw_fence *fence;
  212.  
  213.    fence = calloc(1, sizeof(*fence));
  214.    if (!fence)
  215.       return NULL;
  216.  
  217.    brw_fence_insert(brw, fence);
  218.  
  219.    return fence;
  220. }
  221.  
  222. static void
  223. intel_dri_destroy_fence(__DRIscreen *screen, void *driver_fence)
  224. {
  225.    struct brw_fence *fence = driver_fence;
  226.  
  227.    brw_fence_finish(fence);
  228.    free(fence);
  229. }
  230.  
  231. static GLboolean
  232. intel_dri_client_wait_sync(__DRIcontext *ctx, void *driver_fence, unsigned flags,
  233.                            uint64_t timeout)
  234. {
  235.    struct brw_context *brw = ctx->driverPrivate;
  236.    struct brw_fence *fence = driver_fence;
  237.  
  238.    return brw_fence_client_wait(brw, fence, timeout);
  239. }
  240.  
  241. static void
  242. intel_dri_server_wait_sync(__DRIcontext *ctx, void *driver_fence, unsigned flags)
  243. {
  244.    struct brw_context *brw = ctx->driverPrivate;
  245.    struct brw_fence *fence = driver_fence;
  246.  
  247.    brw_fence_server_wait(brw, fence);
  248. }
  249.  
  250. const __DRI2fenceExtension intelFenceExtension = {
  251.    .base = { __DRI2_FENCE, 1 },
  252.  
  253.    .create_fence = intel_dri_create_fence,
  254.    .destroy_fence = intel_dri_destroy_fence,
  255.    .client_wait_sync = intel_dri_client_wait_sync,
  256.    .server_wait_sync = intel_dri_server_wait_sync,
  257.    .get_fence_from_cl_event = NULL,
  258. };
  259.