winsys/radeon: add the implementation of fences from r300g
authorMarek Olšák <marek.olsak@amd.com>
Tue, 8 Oct 2013 19:26:34 +0000 (21:26 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Fri, 25 Oct 2013 09:55:55 +0000 (11:55 +0200)
src/gallium/drivers/r300/r300_flush.c
src/gallium/drivers/r300/r300_screen.c
src/gallium/winsys/radeon/drm/radeon_drm_cs.c
src/gallium/winsys/radeon/drm/radeon_winsys.h

index 3dd3864353c9000446584b78d9b4af7996ded532..cbe2b5784489e73d9a850ab8a9f08c01c50c0cea 100644 (file)
@@ -76,26 +76,19 @@ void r300_flush(struct pipe_context *pipe,
                 struct pipe_fence_handle **fence)
 {
     struct r300_context *r300 = r300_context(pipe);
-    struct pb_buffer **rfence = (struct pb_buffer**)fence;
 
     if (r300->screen->info.drm_minor >= 12) {
         flags |= RADEON_FLUSH_KEEP_TILING_FLAGS;
     }
 
-    if (rfence) {
-        /* Create a fence, which is a dummy BO. */
-        *rfence = r300->rws->buffer_create(r300->rws, 1, 1, TRUE,
-                                           RADEON_DOMAIN_GTT);
-        /* Add the fence as a dummy relocation. */
-        r300->rws->cs_add_reloc(r300->cs,
-                                r300->rws->buffer_get_cs_handle(*rfence),
-                                RADEON_USAGE_READWRITE, RADEON_DOMAIN_GTT);
+    if (fence) {
+        *fence = r300->rws->cs_create_fence(r300->cs);
     }
 
     if (r300->dirty_hw) {
         r300_flush_and_cleanup(r300, flags);
     } else {
-        if (rfence) {
+        if (fence) {
             /* We have to create a fence object, but the command stream is empty
              * and we cannot emit an empty CS. Let's write to some reg. */
             CS_LOCALS(r300);
index dd036fcd8371c6a22dbbc5d2ec894b656b4da358..9ec58a9f504b0dd0a36984b425f037d4ad66b083 100644 (file)
@@ -558,17 +558,17 @@ static void r300_fence_reference(struct pipe_screen *screen,
                                  struct pipe_fence_handle **ptr,
                                  struct pipe_fence_handle *fence)
 {
-    pb_reference((struct pb_buffer**)ptr,
-                             (struct pb_buffer*)fence);
+    struct radeon_winsys *rws = r300_screen(screen)->rws;
+
+    rws->fence_reference(ptr, fence);
 }
 
 static boolean r300_fence_signalled(struct pipe_screen *screen,
                                     struct pipe_fence_handle *fence)
 {
     struct radeon_winsys *rws = r300_screen(screen)->rws;
-    struct pb_buffer *rfence = (struct pb_buffer*)fence;
 
-    return !rws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE);
+    return rws->fence_wait(rws, fence, 0);
 }
 
 static boolean r300_fence_finish(struct pipe_screen *screen,
@@ -576,26 +576,8 @@ static boolean r300_fence_finish(struct pipe_screen *screen,
                                  uint64_t timeout)
 {
     struct radeon_winsys *rws = r300_screen(screen)->rws;
-    struct pb_buffer *rfence = (struct pb_buffer*)fence;
-
-    if (timeout != PIPE_TIMEOUT_INFINITE) {
-        int64_t start_time = os_time_get();
-
-        /* Convert to microseconds. */
-        timeout /= 1000;
-
-        /* Wait in a loop. */
-        while (rws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE)) {
-            if (os_time_get() - start_time >= timeout) {
-                return FALSE;
-            }
-            os_time_sleep(10);
-        }
-        return TRUE;
-    }
 
-    rws->buffer_wait(rfence, RADEON_USAGE_READWRITE);
-    return TRUE;
+    return rws->fence_wait(rws, fence, timeout);
 }
 
 struct pipe_screen* r300_screen_create(struct radeon_winsys *rws)
index 0782e10c800f321e2742aa45e87ba058bc68239d..e5723a5874e7a2f370cf94554f9f94b60a86acb8 100644 (file)
@@ -65,6 +65,7 @@
 #include "radeon_drm_cs.h"
 
 #include "util/u_memory.h"
+#include "os/os_time.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -630,6 +631,58 @@ static boolean radeon_bo_is_referenced(struct radeon_winsys_cs *rcs,
     return FALSE;
 }
 
+/* FENCES */
+
+static struct pipe_fence_handle *
+radeon_cs_create_fence(struct radeon_winsys_cs *rcs)
+{
+    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+    struct pb_buffer *fence;
+
+    /* Create a fence, which is a dummy BO. */
+    fence = cs->ws->base.buffer_create(&cs->ws->base, 1, 1, TRUE,
+                                       RADEON_DOMAIN_GTT);
+    /* Add the fence as a dummy relocation. */
+    cs->ws->base.cs_add_reloc(rcs, cs->ws->base.buffer_get_cs_handle(fence),
+                              RADEON_USAGE_READWRITE, RADEON_DOMAIN_GTT);
+    return (struct pipe_fence_handle*)fence;
+}
+
+static bool radeon_fence_wait(struct radeon_winsys *ws,
+                              struct pipe_fence_handle *fence,
+                              uint64_t timeout)
+{
+    struct pb_buffer *rfence = (struct pb_buffer*)fence;
+
+    if (timeout == 0)
+        return !ws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE);
+
+    if (timeout != PIPE_TIMEOUT_INFINITE) {
+        int64_t start_time = os_time_get();
+
+        /* Convert to microseconds. */
+        timeout /= 1000;
+
+        /* Wait in a loop. */
+        while (ws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE)) {
+            if (os_time_get() - start_time >= timeout) {
+                return FALSE;
+            }
+            os_time_sleep(10);
+        }
+        return TRUE;
+    }
+
+    ws->buffer_wait(rfence, RADEON_USAGE_READWRITE);
+    return TRUE;
+}
+
+static void radeon_fence_reference(struct pipe_fence_handle **dst,
+                                   struct pipe_fence_handle *src)
+{
+    pb_reference((struct pb_buffer**)dst, (struct pb_buffer*)src);
+}
+
 void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
 {
     ws->base.cs_create = radeon_drm_cs_create;
@@ -642,4 +695,7 @@ void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
     ws->base.cs_set_flush_callback = radeon_drm_cs_set_flush;
     ws->base.cs_is_buffer_referenced = radeon_bo_is_referenced;
     ws->base.cs_sync_flush = radeon_drm_cs_sync_flush;
+    ws->base.cs_create_fence = radeon_cs_create_fence;
+    ws->base.fence_wait = radeon_fence_wait;
+    ws->base.fence_reference = radeon_fence_reference;
 }
index 581cd841cd8626fe66ba1e2995dc142d83d1ef7d..c0003711bee853bf56ed053e624cc1da853aa8be 100644 (file)
@@ -484,6 +484,29 @@ struct radeon_winsys {
       */
     void (*cs_sync_flush)(struct radeon_winsys_cs *cs);
 
+    /**
+     * Return a fence associated with the CS. The fence will be signalled
+     * once the CS is flushed and all commands in the CS are completed
+     * by the GPU.
+     */
+    struct pipe_fence_handle *(*cs_create_fence)(struct radeon_winsys_cs *cs);
+
+    /**
+     * Wait for the fence and return true if the fence has been signalled.
+     * The timeout of 0 will only return the status.
+     * The timeout of PIPE_TIMEOUT_INFINITE will always wait until the fence
+     * is signalled.
+     */
+    bool (*fence_wait)(struct radeon_winsys *ws,
+                       struct pipe_fence_handle *fence,
+                       uint64_t timeout);
+
+    /**
+     * Reference counting for fences.
+     */
+    void (*fence_reference)(struct pipe_fence_handle **dst,
+                            struct pipe_fence_handle *src);
+
     /**
      * Initialize surface
      *