Module: Mesa
Branch: master
Commit: bf40c346637325862d6d9cdbc9838c5726abc0c0
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=bf40c346637325862d6d9cdbc9838c5726abc0c0

Author: José Fonseca <[email protected]>
Date:   Sat Mar 13 16:13:26 2010 +0000

llvmpipe: Ensure the context is flushed before modifying textures.

---

 src/gallium/drivers/llvmpipe/lp_flush.c   |   65 +++++++++++++++++++++++++++++
 src/gallium/drivers/llvmpipe/lp_flush.h   |   12 +++++
 src/gallium/drivers/llvmpipe/lp_surface.c |   15 +++++++
 src/gallium/drivers/llvmpipe/lp_texture.c |   10 ++++
 4 files changed, 102 insertions(+), 0 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c 
b/src/gallium/drivers/llvmpipe/lp_flush.c
index 1b4e889..636d72a 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.c
+++ b/src/gallium/drivers/llvmpipe/lp_flush.c
@@ -92,3 +92,68 @@ llvmpipe_flush( struct pipe_context *pipe,
 #endif
 }
 
+
+/**
+ * Flush context if necessary.
+ *
+ * TODO: move this logic to an auxiliary library?
+ *
+ * FIXME: We must implement DISCARD/DONTBLOCK/UNSYNCHRONIZED/etc for
+ * textures to avoid blocking.
+ */
+boolean
+llvmpipe_flush_texture(struct pipe_context *pipe,
+                       struct pipe_texture *texture,
+                       unsigned face,
+                       unsigned level,
+                       unsigned flush_flags,
+                       boolean read_only,
+                       boolean cpu_access,
+                       boolean do_not_flush)
+{
+   struct pipe_fence_handle *last_fence = NULL;
+   unsigned referenced;
+
+   referenced = pipe->is_texture_referenced(pipe, texture, face, level);
+
+   if ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
+       ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) {
+
+      if (do_not_flush)
+         return FALSE;
+
+      /*
+       * TODO: The semantics of these flush flags are too obtuse. They should
+       * disappear and the pipe driver should just ensure that all visible
+       * side-effects happen when they need to happen.
+       */
+      if (referenced & PIPE_REFERENCED_FOR_WRITE)
+         flush_flags |= PIPE_FLUSH_RENDER_CACHE;
+
+      if (referenced & PIPE_REFERENCED_FOR_READ)
+         flush_flags |= PIPE_FLUSH_TEXTURE_CACHE;
+
+      if (cpu_access) {
+         /*
+          * Flush and wait.
+          */
+
+         struct pipe_fence_handle *fence = NULL;
+
+         pipe->flush(pipe, flush_flags, &fence);
+
+         if (last_fence) {
+            pipe->screen->fence_finish(pipe->screen, fence, 0);
+            pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+         }
+      } else {
+         /*
+          * Just flush.
+          */
+
+         pipe->flush(pipe, flush_flags, NULL);
+      }
+   }
+
+   return TRUE;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.h 
b/src/gallium/drivers/llvmpipe/lp_flush.h
index 10b2b52..e13f57c 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.h
+++ b/src/gallium/drivers/llvmpipe/lp_flush.h
@@ -28,10 +28,22 @@
 #ifndef LP_FLUSH_H
 #define LP_FLUSH_H
 
+#include "pipe/p_compiler.h"
+
 struct pipe_context;
 struct pipe_fence_handle;
 
 void llvmpipe_flush(struct pipe_context *pipe, unsigned flags,
                     struct pipe_fence_handle **fence);
 
+boolean
+llvmpipe_flush_texture(struct pipe_context *pipe,
+                       struct pipe_texture *texture,
+                       unsigned face,
+                       unsigned level,
+                       unsigned flush_flags,
+                       boolean read_only,
+                       boolean cpu_access,
+                       boolean do_not_flush);
+
 #endif
diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c 
b/src/gallium/drivers/llvmpipe/lp_surface.c
index 6110b0a..ca3d62c 100644
--- a/src/gallium/drivers/llvmpipe/lp_surface.c
+++ b/src/gallium/drivers/llvmpipe/lp_surface.c
@@ -27,6 +27,7 @@
 
 #include "util/u_rect.h"
 #include "lp_context.h"
+#include "lp_flush.h"
 #include "lp_surface.h"
 
 
@@ -36,6 +37,20 @@ lp_surface_copy(struct pipe_context *pipe,
                 struct pipe_surface *src, unsigned srcx, unsigned srcy,
                 unsigned width, unsigned height)
 {
+   llvmpipe_flush_texture(pipe,
+                          dest->texture, dest->face, dest->level,
+                          0, /* flush_flags */
+                          FALSE, /* read_only */
+                          FALSE, /* cpu_access */
+                          FALSE); /* do_not_flush */
+
+   llvmpipe_flush_texture(pipe,
+                          src->texture, src->face, src->level,
+                          0, /* flush_flags */
+                          TRUE, /* read_only */
+                          FALSE, /* cpu_access */
+                          FALSE); /* do_not_flush */
+
    util_surface_copy(pipe, FALSE,
                      dest, destx, desty,
                      src, srcx, srcy,
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c 
b/src/gallium/drivers/llvmpipe/lp_texture.c
index f3f0cd7..9a85a42 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -371,6 +371,16 @@ llvmpipe_transfer_map( struct pipe_context *pipe,
    lpt = llvmpipe_texture(transfer->texture);
    format = lpt->base.format;
 
+   /*
+    * Transfers, like other pipe operations, must happen in order, so flush the
+    * context if necessary.
+    */
+   llvmpipe_flush_texture(pipe,
+                          transfer->texture, transfer->face, transfer->level,
+                          0, /* flush_flags */
+                          !(transfer->usage & PIPE_TRANSFER_WRITE), /* 
read_only */
+                          TRUE, /* cpu_access */
+                          FALSE); /* do_not_flush */
 
    map = llvmpipe_texture_map(transfer->texture,
                               transfer->face, transfer->level, 
transfer->zslice);

_______________________________________________
mesa-commit mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to