- This avoids problematic "reloc'ed while mapped" messages and
some associated corruption as well.

Signed-off-by: Maarten Maathuis <madman2...@gmail.com>
---
 src/gallium/drivers/nouveau/nouveau_screen.c   |   21 +++++++++++++++++++++
 src/gallium/drivers/nouveau/nouveau_screen.h   |    3 +++
 src/gallium/drivers/nouveau/nouveau_stateobj.h |   13 +++++++++++++
 src/gallium/drivers/nv50/nv50_screen.c         |   23 +++++++++++++++++++++++
 src/gallium/drivers/nv50/nv50_screen.h         |    2 ++
 src/gallium/drivers/nv50/nv50_state_validate.c |    3 +++
 6 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c 
b/src/gallium/drivers/nouveau/nouveau_screen.c
index 0437af3..7ebc94e 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -127,8 +127,18 @@ nouveau_screen_bo_map(struct pipe_screen *pscreen, struct 
pipe_buffer *pb,
                      unsigned usage)
 {
        struct nouveau_bo *bo = nouveau_bo(pb);
+       struct nouveau_screen *nscreen = nouveau_screen(pscreen);
        int ret;
 
+       if (nscreen->pre_pipebuffer_map_callback) {
+               ret = nscreen->pre_pipebuffer_map_callback(pscreen, pb, usage);
+               if (ret) {
+                       debug_printf("pre_pipebuffer_map_callback failed %d\n",
+                               ret);
+                       return NULL;
+               }
+       }
+
        ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage));
        if (ret) {
                debug_printf("map failed: %d\n", ret);
@@ -143,11 +153,22 @@ nouveau_screen_bo_map_range(struct pipe_screen *pscreen, 
struct pipe_buffer *pb,
                            unsigned offset, unsigned length, unsigned usage)
 {
        struct nouveau_bo *bo = nouveau_bo(pb);
+       struct nouveau_screen *nscreen = nouveau_screen(pscreen);
        uint32_t flags = nouveau_screen_map_flags(usage);
        int ret;
 
+       if (nscreen->pre_pipebuffer_map_callback) {
+               ret = nscreen->pre_pipebuffer_map_callback(pscreen, pb, usage);
+               if (ret) {
+                       debug_printf("pre_pipebuffer_map_callback failed %d\n",
+                               ret);
+                       return NULL;
+               }
+       }
+
        ret = nouveau_bo_map_range(bo, offset, length, flags);
        if (ret) {
+               nouveau_bo_unmap(bo);
                if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
                        debug_printf("map_range failed: %d\n", ret);
                return NULL;
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h 
b/src/gallium/drivers/nouveau/nouveau_screen.h
index ebfc67a..a7927d8 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.h
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -5,6 +5,9 @@ struct nouveau_screen {
        struct pipe_screen base;
        struct nouveau_device *device;
        struct nouveau_channel *channel;
+
+       int (*pre_pipebuffer_map_callback) (struct pipe_screen *pscreen,
+               struct pipe_buffer *pb, unsigned usage);
 };
 
 static inline struct nouveau_screen *
diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h 
b/src/gallium/drivers/nouveau/nouveau_stateobj.h
index 9aee9e4..b8c83db 100644
--- a/src/gallium/drivers/nouveau/nouveau_stateobj.h
+++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h
@@ -98,6 +98,19 @@ so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo,
        so_data(so, data);
 }
 
+/* Determine if this buffer object is referenced by this state object. */
+static INLINE bool
+so_bo_is_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo)
+{
+       int i;
+
+       for (i = 0; i < so->cur_reloc; i++)
+               if (so->reloc[i].bo == bo)
+                       return true;
+
+       return false;
+}
+
 static INLINE void
 so_dump(struct nouveau_stateobj *so)
 {
diff --git a/src/gallium/drivers/nv50/nv50_screen.c 
b/src/gallium/drivers/nv50/nv50_screen.c
index 7e039ea..1778a74 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -189,6 +189,28 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
        FREE(screen);
 }
 
+static int
+nv50_pre_pipebuffer_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
+       unsigned usage)
+{
+       struct nv50_screen *screen = nv50_screen(pscreen);
+       struct nv50_context *ctx = screen->cur_ctx;
+
+       if (!(pb->usage & PIPE_BUFFER_USAGE_VERTEX))
+               return 0;
+
+       /* Our vtxbuf got mapped, it can no longer be considered part of current
+        * state, remove it to avoid emitting reloc markers.
+        */
+       if (ctx && ctx->state.vtxbuf && so_bo_is_reloc(ctx->state.vtxbuf,
+                       nouveau_bo(pb))) {
+               so_ref(NULL, &ctx->state.vtxbuf);
+               ctx->dirty |= NV50_NEW_ARRAYS;
+       }
+
+       return 0;
+}
+
 struct pipe_screen *
 nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 {
@@ -216,6 +238,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct 
nouveau_device *dev)
        pscreen->get_param = nv50_screen_get_param;
        pscreen->get_paramf = nv50_screen_get_paramf;
        pscreen->is_format_supported = nv50_screen_is_format_supported;
+       screen->base.pre_pipebuffer_map_callback = nv50_pre_pipebuffer_map;
 
        nv50_screen_init_miptree_functions(pscreen);
        nv50_transfer_init_screen_functions(pscreen);
diff --git a/src/gallium/drivers/nv50/nv50_screen.h 
b/src/gallium/drivers/nv50/nv50_screen.h
index 61e24a5..a038a4e 100644
--- a/src/gallium/drivers/nv50/nv50_screen.h
+++ b/src/gallium/drivers/nv50/nv50_screen.h
@@ -2,6 +2,7 @@
 #define __NV50_SCREEN_H__
 
 #include "nouveau/nouveau_screen.h"
+#include "nv50_context.h"
 
 struct nv50_screen {
        struct nouveau_screen base;
@@ -9,6 +10,7 @@ struct nv50_screen {
        struct nouveau_winsys *nvws;
 
        unsigned cur_pctx;
+       struct nv50_context *cur_ctx;
 
        struct nouveau_grobj *tesla;
        struct nouveau_grobj *eng2d;
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c 
b/src/gallium/drivers/nv50/nv50_state_validate.c
index c8bdf9d..6827863 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -185,6 +185,9 @@ nv50_state_emit(struct nv50_context *nv50)
        struct nv50_screen *screen = nv50->screen;
        struct nouveau_channel *chan = screen->base.channel;
 
+       /* I don't want to copy headers from the winsys. */
+       screen->cur_ctx = nv50;
+
        if (nv50->pctx_id != screen->cur_pctx) {
                if (nv50->state.fb)
                        nv50->state.dirty |= NV50_NEW_FRAMEBUFFER;
-- 
1.6.6.rc4

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to