diff options
| author | Ben Skeggs <skeggsb@gmail.com> | 2007-11-18 23:08:33 +1100 | 
|---|---|---|
| committer | Ben Skeggs <skeggsb@gmail.com> | 2007-11-18 23:08:33 +1100 | 
| commit | c7c6253169798658547ec6fc6eb9cdefc68b58d3 (patch) | |
| tree | a48439df7ab3ef3effd146e29a542d5d3dde11c4 /src/mesa | |
| parent | f940603037844b91ffed84c390bef0ee57ffe8cc (diff) | |
nouveau: m2mf fallback path for region copies.
Diffstat (limited to 'src/mesa')
| -rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h | 1 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nv04_region.c | 55 | 
2 files changed, 56 insertions, 0 deletions
| diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h index cd04b08eca..f2557af935 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h @@ -52,6 +52,7 @@ struct nouveau_context {  	struct nouveau_grobj    *NvCtxSurf2D;  	struct nouveau_grobj    *NvImageBlit;  	struct nouveau_grobj    *NvGdiRect; +	struct nouveau_grobj    *NvM2MF;  	uint32_t                 next_handle;  	uint32_t                 next_sequence; diff --git a/src/mesa/drivers/dri/nouveau_winsys/nv04_region.c b/src/mesa/drivers/dri/nouveau_winsys/nv04_region.c index cbe70983f5..f41e45c73a 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nv04_region.c +++ b/src/mesa/drivers/dri/nouveau_winsys/nv04_region.c @@ -34,6 +34,40 @@ nv04_region_display(void)  }  static int +nv04_region_copy_m2mf(struct nouveau_context *nv, struct pipe_region *dst, +		      unsigned dst_offset, struct pipe_region *src, +		      unsigned src_offset, unsigned line_len, unsigned height) +{ +	BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); +	OUT_RELOCo(src->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | +		   NOUVEAU_BO_RD); +	OUT_RELOCo(dst->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | +		   NOUVEAU_BO_WR); + +	while (height) { +		int count = (height > 2047) ? 2047 : height; + +		BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); +		OUT_RELOCl(src->buffer, src_offset, NOUVEAU_BO_VRAM | +			   NOUVEAU_BO_GART | NOUVEAU_BO_RD); +		OUT_RELOCl(dst->buffer, dst_offset, NOUVEAU_BO_VRAM | +			   NOUVEAU_BO_GART | NOUVEAU_BO_WR); +		OUT_RING  (src->pitch * src->cpp); +		OUT_RING  (dst->pitch * dst->cpp); +		OUT_RING  (line_len); +		OUT_RING  (count); +		OUT_RING  (0x0101); +		OUT_RING  (0); + +		height -= count; +		src_offset += src->pitch * count; +		dst_offset += dst->pitch * count; +	} + +	return 0; +} + +static int  nv04_region_copy(struct nouveau_context *nv, struct pipe_region *dst,  		 unsigned dst_offset, unsigned dx, unsigned dy,  		 struct pipe_region *src, unsigned src_offset, @@ -44,6 +78,19 @@ nv04_region_copy(struct nouveau_context *nv, struct pipe_region *dst,  	if (src->cpp != dst->cpp)  		return 1; +	NOUVEAU_ERR("preg\n"); + +	/* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback +	 * to NV_MEMORY_TO_MEMORY_FORMAT in this case. +	 */ +	if ((src_offset & 63) || (dst_offset & 63)) { +		dst_offset += (dy * dst->pitch + dx) * dst->cpp; +		src_offset += (sy * src->pitch + sx) * src->cpp; +		return nv04_region_copy_m2mf(nv, dst, dst_offset, src, +					     src_offset, w * src->cpp, h); + +	} +  	if ((format = nv04_surface_format(dst->cpp)) < 0) {  		NOUVEAU_ERR("Bad cpp = %d\n", dst->cpp);  		return 1; @@ -119,6 +166,14 @@ nouveau_region_init_nv04(struct nouveau_context *nv)  {  	int ret; +	if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, 0x39, +				       &nv->NvM2MF))) { +		NOUVEAU_ERR("Error creating m2mf object: %d\n", ret); +		return 1; +	} +	BEGIN_RING(NvM2MF, 0x0180, 1); +	OUT_RING  (nv->sync_notifier->handle); +  	if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, 0x62,  				       &nv->NvCtxSurf2D))) {  		NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret); | 
