Same patch from before, without the debatable unmap change.
On Wed, Dec 30, 2009 at 10:36 PM, Maarten Maathuis <madman2...@gmail.com> wrote: > - 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