diff options
Diffstat (limited to 'src/gallium')
| -rw-r--r-- | src/gallium/drivers/nouveau/nouveau_screen.c | 21 | ||||
| -rw-r--r-- | src/gallium/drivers/nouveau/nouveau_screen.h | 3 | ||||
| -rw-r--r-- | src/gallium/drivers/nouveau/nouveau_stateobj.h | 13 | ||||
| -rw-r--r-- | src/gallium/drivers/nv50/nv50_screen.c | 23 | ||||
| -rw-r--r-- | src/gallium/drivers/nv50/nv50_screen.h | 2 | ||||
| -rw-r--r-- | 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 0437af3725..7ebc94ed6c 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 ebfc67ad1c..a7927d88df 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 9aee9e4956..77ff7dcf20 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 boolean +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 7e039ea82e..1778a74517 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 61e24a5b57..a038a4e3c2 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 c8bdf9dc27..682786345e 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; | 
