freedreno: Remove the Emacs mode lines
[mesa.git] / src / gallium / drivers / freedreno / freedreno_fence.c
index 5125f0918601aa7d3e041780a0ee62ff33ea85c8..68bbb25ee645dc373e41bdf5c64a0040e5f7feac 100644 (file)
@@ -1,5 +1,3 @@
-/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
-
 /*
  * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
  *
@@ -26,6 +24,8 @@
  *    Rob Clark <robclark@freedesktop.org>
  */
 
+#include <libsync.h>
+
 #include "util/u_inlines.h"
 
 #include "freedreno_fence.h"
 
 struct pipe_fence_handle {
        struct pipe_reference reference;
-       struct fd_context *ctx;
+       /* fence holds a weak reference to the batch until the batch is flushed,
+        * at which point fd_fence_populate() is called and timestamp and possibly
+        * fence_fd become valid and the week reference is dropped.
+        */
+       struct fd_batch *batch;
+       struct fd_pipe *pipe;
        struct fd_screen *screen;
+       int fence_fd;
        uint32_t timestamp;
 };
 
-void
-fd_screen_fence_ref(struct pipe_screen *pscreen,
+static void fence_flush(struct pipe_fence_handle *fence)
+{
+       if (fence->batch)
+               fd_batch_flush(fence->batch, true, true);
+       debug_assert(!fence->batch);
+}
+
+void fd_fence_populate(struct pipe_fence_handle *fence,
+               uint32_t timestamp, int fence_fd)
+{
+       if (!fence->batch)
+               return;
+       fence->timestamp = timestamp;
+       fence->fence_fd = fence_fd;
+       fence->batch = NULL;
+}
+
+static void fd_fence_destroy(struct pipe_fence_handle *fence)
+{
+       if (fence->fence_fd != -1)
+               close(fence->fence_fd);
+       fd_pipe_del(fence->pipe);
+       FREE(fence);
+}
+
+void fd_fence_ref(struct pipe_screen *pscreen,
                struct pipe_fence_handle **ptr,
                struct pipe_fence_handle *pfence)
 {
        if (pipe_reference(&(*ptr)->reference, &pfence->reference))
-               FREE(*ptr);
+               fd_fence_destroy(*ptr);
 
        *ptr = pfence;
 }
 
-boolean fd_screen_fence_finish(struct pipe_screen *screen,
+boolean fd_fence_finish(struct pipe_screen *pscreen,
+               struct pipe_context *ctx,
                struct pipe_fence_handle *fence,
                uint64_t timeout)
 {
-       if (fd_pipe_wait_timeout(fence->screen->pipe, fence->timestamp, timeout))
+       fence_flush(fence);
+
+       if (fence->fence_fd != -1) {
+               int ret = sync_wait(fence->fence_fd, timeout / 1000000);
+               return ret == 0;
+       }
+
+       if (fd_pipe_wait_timeout(fence->pipe, fence->timestamp, timeout))
                return false;
 
        return true;
 }
 
-struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx,
-               uint32_t timestamp)
+static struct pipe_fence_handle * fence_create(struct fd_context *ctx,
+               struct fd_batch *batch, uint32_t timestamp, int fence_fd)
 {
        struct pipe_fence_handle *fence;
-       struct fd_context *ctx = fd_context(pctx);
 
        fence = CALLOC_STRUCT(pipe_fence_handle);
        if (!fence)
@@ -72,9 +109,48 @@ struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx,
 
        pipe_reference_init(&fence->reference, 1);
 
-       fence->ctx = ctx;
+       fence->batch = batch;
+       fence->pipe = fd_pipe_ref(ctx->pipe);
        fence->screen = ctx->screen;
        fence->timestamp = timestamp;
+       fence->fence_fd = fence_fd;
 
        return fence;
 }
+
+void fd_create_fence_fd(struct pipe_context *pctx,
+               struct pipe_fence_handle **pfence, int fd,
+               enum pipe_fd_type type)
+{
+       assert(type == PIPE_FD_TYPE_NATIVE_SYNC);
+       *pfence = fence_create(fd_context(pctx), NULL, 0, dup(fd));
+}
+
+void fd_fence_server_sync(struct pipe_context *pctx,
+               struct pipe_fence_handle *fence)
+{
+       struct fd_context *ctx = fd_context(pctx);
+       struct fd_batch *batch = fd_context_batch(ctx);
+
+       fence_flush(fence);
+
+       /* if not an external fence, then nothing more to do without preemption: */
+       if (fence->fence_fd == -1)
+               return;
+
+       if (sync_accumulate("freedreno", &batch->in_fence_fd, fence->fence_fd)) {
+               /* error */
+       }
+}
+
+int fd_fence_get_fd(struct pipe_screen *pscreen,
+               struct pipe_fence_handle *fence)
+{
+       fence_flush(fence);
+       return dup(fence->fence_fd);
+}
+
+struct pipe_fence_handle * fd_fence_create(struct fd_batch *batch)
+{
+       return fence_create(batch->ctx, batch, 0, -1);
+}