diff options
Diffstat (limited to 'src/gallium/drivers')
| -rw-r--r-- | src/gallium/drivers/nouveau/nouveau_winsys.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/nv04/Makefile | 1 | ||||
| -rw-r--r-- | src/gallium/drivers/nv04/nv04_screen.c | 13 | ||||
| -rw-r--r-- | src/gallium/drivers/nv04/nv04_screen.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/nv04/nv04_surface.c | 17 | ||||
| -rw-r--r-- | src/gallium/drivers/nv04/nv04_surface_2d.c | 449 | ||||
| -rw-r--r-- | src/gallium/drivers/nv04/nv04_surface_2d.h | 29 | ||||
| -rw-r--r-- | src/gallium/drivers/nv10/nv10_screen.c | 12 | ||||
| -rw-r--r-- | src/gallium/drivers/nv10/nv10_screen.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/nv10/nv10_surface.c | 17 | ||||
| -rw-r--r-- | src/gallium/drivers/nv20/nv20_screen.c | 12 | ||||
| -rw-r--r-- | src/gallium/drivers/nv20/nv20_screen.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/nv20/nv20_surface.c | 17 | ||||
| -rw-r--r-- | src/gallium/drivers/nv30/nv30_screen.c | 12 | ||||
| -rw-r--r-- | src/gallium/drivers/nv30/nv30_screen.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/nv30/nv30_surface.c | 20 | ||||
| -rw-r--r-- | src/gallium/drivers/nv40/nv40_screen.c | 12 | ||||
| -rw-r--r-- | src/gallium/drivers/nv40/nv40_screen.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/nv40/nv40_surface.c | 20 | 
19 files changed, 601 insertions, 42 deletions
| diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index 99f8e08201..b86c4b9338 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -50,7 +50,7 @@ struct nouveau_winsys {  	uint32_t  (*notifier_status)(struct nouveau_notifier *, int id);  	uint32_t  (*notifier_retval)(struct nouveau_notifier *, int id);  	int       (*notifier_wait)(struct nouveau_notifier *, int id, -				   int status, float timeout); +				   int status, double timeout);  	int (*surface_copy)(struct nouveau_winsys *, struct pipe_surface *,  			    unsigned, unsigned, struct pipe_surface *, diff --git a/src/gallium/drivers/nv04/Makefile b/src/gallium/drivers/nv04/Makefile index 5ea51a2f42..4ed62dae95 100644 --- a/src/gallium/drivers/nv04/Makefile +++ b/src/gallium/drivers/nv04/Makefile @@ -4,6 +4,7 @@ include $(TOP)/configs/current  LIBNAME = nv04  DRIVER_SOURCES = \ +	nv04_surface_2d.c \  	nv04_clear.c \  	nv04_context.c \  	nv04_fragprog.c \ diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c index e5e3d4772a..9ef38bc244 100644 --- a/src/gallium/drivers/nv04/nv04_screen.c +++ b/src/gallium/drivers/nv04/nv04_screen.c @@ -149,10 +149,19 @@ nv04_screen_destroy(struct pipe_screen *pscreen)  	nvws->notifier_free(&screen->sync);  	nvws->grobj_free(&screen->fahrenheit); +	nv04_surface_2d_takedown(&screen->eng2d);  	FREE(pscreen);  } +static struct pipe_buffer * +nv04_surface_buffer(struct pipe_surface *surf) +{ +	struct nv04_miptree *mt = (struct nv04_miptree *)surf->texture; + +	return mt->buffer; +} +  struct pipe_screen *  nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  { @@ -181,6 +190,10 @@ nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  		return NULL;  	} +	/* 2D engine setup */ +	screen->eng2d = nv04_surface_2d_init(nvws); +	screen->eng2d->buf = nv04_surface_buffer; +  	/* 3D object */  	ret = nvws->grobj_alloc(nvws, fahrenheit_class, &screen->fahrenheit);  	if (ret) { diff --git a/src/gallium/drivers/nv04/nv04_screen.h b/src/gallium/drivers/nv04/nv04_screen.h index 99a49cdf7a..540aec907b 100644 --- a/src/gallium/drivers/nv04/nv04_screen.h +++ b/src/gallium/drivers/nv04/nv04_screen.h @@ -2,6 +2,7 @@  #define __NV04_SCREEN_H__  #include "pipe/p_screen.h" +#include "nv04_surface_2d.h"  struct nv04_screen {  	struct pipe_screen pipe; @@ -10,6 +11,7 @@ struct nv04_screen {  	unsigned chipset;  	/* HW graphics objects */ +	struct nv04_surface_2d *eng2d;  	struct nouveau_grobj *fahrenheit;  	struct nouveau_grobj *context_surfaces_3d;  	struct nouveau_notifier *sync; diff --git a/src/gallium/drivers/nv04/nv04_surface.c b/src/gallium/drivers/nv04/nv04_surface.c index 0d0983f9d4..1d11f53f2a 100644 --- a/src/gallium/drivers/nv04/nv04_surface.c +++ b/src/gallium/drivers/nv04/nv04_surface.c @@ -39,10 +39,17 @@ nv04_surface_copy(struct pipe_context *pipe, boolean do_flip,  		  unsigned width, unsigned height)  {  	struct nv04_context *nv04 = nv04_context(pipe); -	struct nouveau_winsys *nvws = nv04->nvws; +	struct nv04_surface_2d *eng2d = nv04->screen->eng2d; -	nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, -			   width, height); +	if (do_flip) { +		desty += height; +		while (height--) { +			eng2d->copy(eng2d, dest, destx, desty--, src, +				    srcx, srcy++, width, 1); +		} +	} + +	eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);  }  static void @@ -51,9 +58,9 @@ nv04_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,  		  unsigned height, unsigned value)  {  	struct nv04_context *nv04 = nv04_context(pipe); -	struct nouveau_winsys *nvws = nv04->nvws; +	struct nv04_surface_2d *eng2d = nv04->screen->eng2d; -	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +	eng2d->fill(eng2d, dest, destx, desty, width, height, value);  }  void diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nv04/nv04_surface_2d.c new file mode 100644 index 0000000000..7529583151 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_surface_2d.c @@ -0,0 +1,449 @@ +#include "pipe/p_context.h" +#include "pipe/p_format.h" +#include "util/u_memory.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_util.h" +#include "nv04_surface_2d.h" + +static INLINE int +nv04_surface_format(enum pipe_format format) +{ +	switch (format) { +	case PIPE_FORMAT_A8_UNORM: +		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8; +	case PIPE_FORMAT_R16_SNORM: +	case PIPE_FORMAT_R5G6B5_UNORM: +		return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5; +	case PIPE_FORMAT_X8R8G8B8_UNORM: +	case PIPE_FORMAT_A8R8G8B8_UNORM: +		return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8; +	case PIPE_FORMAT_Z24S8_UNORM: +		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32; +	default: +		return -1; +	} +} + +static INLINE int +nv04_rect_format(enum pipe_format format) +{ +	switch (format) { +	case PIPE_FORMAT_A8_UNORM: +		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8; +	case PIPE_FORMAT_R5G6B5_UNORM: +		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5; +	case PIPE_FORMAT_A8R8G8B8_UNORM: +	case PIPE_FORMAT_Z24S8_UNORM: +		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8; +	default: +		return -1; +	} +} + +static INLINE int +nv04_scaled_image_format(enum pipe_format format) +{ +	switch (format) { +	case PIPE_FORMAT_A1R5G5B5_UNORM: +		return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5; +	case PIPE_FORMAT_A8R8G8B8_UNORM: +		return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8; +	case PIPE_FORMAT_X8R8G8B8_UNORM: +		return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8; +	case PIPE_FORMAT_R5G6B5_UNORM: +	case PIPE_FORMAT_R16_SNORM: +		return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5; +	default: +		return -1; +	} +} + +static INLINE unsigned +nv04_swizzle_bits(unsigned x, unsigned y) +{ +	unsigned u = (x & 0x001) << 0 | +	             (x & 0x002) << 1 | +	             (x & 0x004) << 2 | +	             (x & 0x008) << 3 | +	             (x & 0x010) << 4 | +	             (x & 0x020) << 5 | +	             (x & 0x040) << 6 | +	             (x & 0x080) << 7 | +	             (x & 0x100) << 8 | +	             (x & 0x200) << 9 | +	             (x & 0x400) << 10 | +	             (x & 0x800) << 11; + +	unsigned v = (y & 0x001) << 1 | +	             (y & 0x002) << 2 | +	             (y & 0x004) << 3 | +	             (y & 0x008) << 4 | +	             (y & 0x010) << 5 | +	             (y & 0x020) << 6 | +	             (y & 0x040) << 7 | +	             (y & 0x080) << 8 | +	             (y & 0x100) << 9 | +	             (y & 0x200) << 10 | +	             (y & 0x400) << 11 | +	             (y & 0x800) << 12; +	return v | u; +} + +static int +nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, +			  struct pipe_surface *dst, int dx, int dy, +			  struct pipe_surface *src, int sx, int sy, +			  int w, int h) +{ +	struct nouveau_channel *chan = ctx->nvws->channel; +	struct nouveau_grobj *swzsurf = ctx->swzsurf; +	struct nouveau_grobj *sifm = ctx->sifm; +	struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); +	struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); +	const unsigned max_w = 1024; +	const unsigned max_h = 1024; +	const unsigned sub_w = w > max_w ? max_w : w; +	const unsigned sub_h = h > max_h ? max_h : h; +	unsigned cx = 0; +	unsigned cy = 0; + +	/* POT or GTFO */ +	assert(!(w & (w - 1)) && !(h & (h - 1))); + +	BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1); +	OUT_RELOCo(chan, dst_bo, +	                 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1); +	OUT_RING  (chan, nv04_surface_format(dst->format) | +	                 log2i(w) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT | +	                 log2i(h) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT); + +	BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1); +	OUT_RELOCo(chan, src_bo, +	                 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); +	BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1); +	OUT_RING  (chan, swzsurf->handle); + +	for (cy = 0; cy < h; cy += sub_h) { +	  for (cx = 0; cx < w; cx += sub_w) { +	    BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1); +	    OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(cx, cy) * +			     dst->block.size, NOUVEAU_BO_GART | +			     NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	    BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9); +	    OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE); +	    OUT_RING  (chan, nv04_scaled_image_format(src->format)); +	    OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY); +	    OUT_RING  (chan, 0); +	    OUT_RING  (chan, sub_h << 16 | sub_w); +	    OUT_RING  (chan, 0); +	    OUT_RING  (chan, sub_h << 16 | sub_w); +	    OUT_RING  (chan, 1 << 20); +	    OUT_RING  (chan, 1 << 20); + +	    BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4); +	    OUT_RING  (chan, sub_h << 16 | sub_w); +	    OUT_RING  (chan, src->stride | +	                     NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | +	                     NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); +	    OUT_RELOCl(chan, src_bo, src->offset + cy * src->stride + +			     cx * src->block.size, NOUVEAU_BO_GART | +			     NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); +	    OUT_RING  (chan, 0); +	  } +	} + +	return 0; +} + +static int +nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx, +		       struct pipe_surface *dst, int dx, int dy, +		       struct pipe_surface *src, int sx, int sy, int w, int h) +{ +	struct nouveau_channel *chan = ctx->nvws->channel; +	struct nouveau_grobj *m2mf = ctx->m2mf; +	struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); +	struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); +	unsigned dst_offset, src_offset; + +	dst_offset = dst->offset + (dy * dst->stride) + (dx * dst->block.size); +	src_offset = src->offset + (sy * src->stride) + (sx * src->block.size); + +	WAIT_RING (chan, 3 + ((h / 2047) + 1) * 9); +	BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); +	OUT_RELOCo(chan, src_bo, +		   NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); +	OUT_RELOCo(chan, dst_bo, +		   NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	while (h) { +		int count = (h > 2047) ? 2047 : h; + +		BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); +		OUT_RELOCl(chan, src_bo, src_offset, +			   NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); +		OUT_RELOCl(chan, dst_bo, dst_offset, +			   NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR); +		OUT_RING  (chan, src->stride); +		OUT_RING  (chan, dst->stride); +		OUT_RING  (chan, w * src->block.size); +		OUT_RING  (chan, count); +		OUT_RING  (chan, 0x0101); +		OUT_RING  (chan, 0); + +		h -= count; +		src_offset += src->stride * count; +		dst_offset += dst->stride * count; +	} + +	return 0; +} + +static int +nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst, +		       int dx, int dy, struct pipe_surface *src, int sx, int sy, +		       int w, int h) +{ +	struct nouveau_channel *chan = ctx->nvws->channel; +	struct nouveau_grobj *surf2d = ctx->surf2d; +	struct nouveau_grobj *blit = ctx->blit; +	struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); +	struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); +	int format; + +	format = nv04_surface_format(dst->format); +	if (format < 0) +		return 1; + +	WAIT_RING (chan, 12); +	BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2); +	OUT_RELOCo(chan, src_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); +	OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4); +	OUT_RING  (chan, format); +	OUT_RING  (chan, (dst->stride << 16) | src->stride); +	OUT_RELOCl(chan, src_bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); +	OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	BEGIN_RING(chan, blit, 0x0300, 3); +	OUT_RING  (chan, (sy << 16) | sx); +	OUT_RING  (chan, (dy << 16) | dx); +	OUT_RING  (chan, ( h << 16) |  w); + +	return 0; +} + +static void +nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst, +		  int dx, int dy, struct pipe_surface *src, int sx, int sy, +		  int w, int h) +{ +	int src_linear = src->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR; +	int dst_linear = dst->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR; + +	assert(src->format == dst->format); + +	/* Setup transfer to swizzle the texture to vram if needed */ +	/* FIXME/TODO: check proper limits of this operation */ +	if (src_linear ^ dst_linear) { +		nv04_surface_copy_swizzle(ctx, dst, dx, dy, src, sx, sy, w, h); +		return; +	} + +	/* 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)) { +		nv04_surface_copy_m2mf(ctx, dst, dx, dy, src, sx, sy, w, h); +		return; +	} + +	nv04_surface_copy_blit(ctx, dst, dx, dy, src, sx, sy, w, h); +} + +static void +nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst, +		  int dx, int dy, int w, int h, unsigned value) +{ +	struct nouveau_channel *chan = ctx->nvws->channel; +	struct nouveau_grobj *surf2d = ctx->surf2d; +	struct nouveau_grobj *rect = ctx->rect; +	struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); +	int cs2d_format, gdirect_format; + +	cs2d_format = nv04_surface_format(dst->format); +	assert(cs2d_format >= 0); + +	gdirect_format = nv04_surface_format(dst->format); +	assert(gdirect_format >= 0); + +	WAIT_RING (chan, 16); +	BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2); +	OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4); +	OUT_RING  (chan, cs2d_format); +	OUT_RING  (chan, (dst->stride << 16) | dst->stride); +	OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); +	OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + +	BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1); +	OUT_RING  (chan, gdirect_format); +	BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1); +	OUT_RING  (chan, value); +	BEGIN_RING(chan, rect, +		   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2); +	OUT_RING  (chan, (dx << 16) | dy); +	OUT_RING  (chan, ( w << 16) |  h); +} + +void +nv04_surface_2d_takedown(struct nv04_surface_2d **pctx) +{ +	struct nv04_surface_2d *ctx; + +	if (!pctx || !*pctx) +		return; +	ctx = *pctx; +	*pctx = NULL; + +	nouveau_notifier_free(&ctx->ntfy); +	nouveau_grobj_free(&ctx->m2mf); +	nouveau_grobj_free(&ctx->surf2d); +	nouveau_grobj_free(&ctx->swzsurf); +	nouveau_grobj_free(&ctx->rect); +	nouveau_grobj_free(&ctx->blit); +	nouveau_grobj_free(&ctx->sifm); + +	FREE(ctx); +} + +struct nv04_surface_2d * +nv04_surface_2d_init(struct nouveau_winsys *nvws) +{ +	struct nv04_surface_2d *ctx = CALLOC_STRUCT(nv04_surface_2d); +	struct nouveau_channel *chan = nvws->channel; +	unsigned handle = 0x88000000, class; +	int ret; + +	if (!ctx) +		return NULL; + +	ret = nouveau_notifier_alloc(chan, handle++, 1, &ctx->ntfy); +	if (ret) { +		nv04_surface_2d_takedown(&ctx); +		return NULL; +	} + +	ret = nouveau_grobj_alloc(chan, handle++, 0x0039, &ctx->m2mf); +	if (ret) { +		nv04_surface_2d_takedown(&ctx); +		return NULL; +	} + +	BEGIN_RING(chan, ctx->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); +	OUT_RING  (chan, ctx->ntfy->handle); + +	if (chan->device->chipset < 0x10) +		class = NV04_CONTEXT_SURFACES_2D; +	else +		class = NV10_CONTEXT_SURFACES_2D; + +	ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->surf2d); +	if (ret) { +		nv04_surface_2d_takedown(&ctx); +		return NULL; +	} + +	BEGIN_RING(chan, ctx->surf2d, +			 NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2); +	OUT_RING  (chan, chan->vram->handle); +	OUT_RING  (chan, chan->vram->handle); + +	if (chan->device->chipset < 0x10) +		class = NV04_IMAGE_BLIT; +	else +		class = NV12_IMAGE_BLIT; + +	ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->blit); +	if (ret) { +		nv04_surface_2d_takedown(&ctx); +		return NULL; +	} + +	BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1); +	OUT_RING  (chan, ctx->ntfy->handle); +	BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_SURFACE, 1); +	OUT_RING  (chan, ctx->surf2d->handle); +	BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_OPERATION, 1); +	OUT_RING  (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY); + +	ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT, +				  &ctx->rect); +	if (ret) { +		nv04_surface_2d_takedown(&ctx); +		return NULL; +	} + +	BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1); +	OUT_RING  (chan, ctx->ntfy->handle); +	BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1); +	OUT_RING  (chan, ctx->ntfy->handle); +	BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1); +	OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY); +	BEGIN_RING(chan, ctx->rect, +			 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1); +	OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE); + +	switch (chan->device->chipset & 0xf0) { +	case 0x00: +	case 0x10: +		class = NV04_SWIZZLED_SURFACE; +		break; +	case 0x20: +		class = NV20_SWIZZLED_SURFACE; +		break; +	case 0x30: +		class = NV30_SWIZZLED_SURFACE; +		break; +	case 0x40: +	case 0x60: +		class = NV40_SWIZZLED_SURFACE; +		break; +	default: +		/* Famous last words: this really can't happen.. */ +		assert(0); +		break; +	} + +	ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->swzsurf); +	if (ret) { +		nv04_surface_2d_takedown(&ctx); +		return NULL; +	} + +	if (chan->device->chipset < 0x10) { +		class = NV04_SCALED_IMAGE_FROM_MEMORY; +	} else +	if (chan->device->chipset < 0x40) { +		class = NV10_SCALED_IMAGE_FROM_MEMORY; +	} else { +		class = NV40_SCALED_IMAGE_FROM_MEMORY; +	} + +	ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->sifm); +	if (ret) { +		nv04_surface_2d_takedown(&ctx); +		return NULL; +	} + +	ctx->nvws = nvws; +	ctx->copy = nv04_surface_copy; +	ctx->fill = nv04_surface_fill; +	return ctx; +} + + diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.h b/src/gallium/drivers/nv04/nv04_surface_2d.h new file mode 100644 index 0000000000..21b8f86960 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_surface_2d.h @@ -0,0 +1,29 @@ +#ifndef __NV04_SURFACE_2D_H__ +#define __NV04_SURFACE_2D_H__ + +struct nv04_surface_2d { +	struct nouveau_winsys *nvws; +	struct nouveau_notifier *ntfy; +	struct nouveau_grobj *surf2d; +	struct nouveau_grobj *swzsurf; +	struct nouveau_grobj *m2mf; +	struct nouveau_grobj *rect; +	struct nouveau_grobj *blit; +	struct nouveau_grobj *sifm; + +	struct pipe_buffer *(*buf)(struct pipe_surface *); + +	void (*copy)(struct nv04_surface_2d *, struct pipe_surface *dst, +		     int dx, int dy, struct pipe_surface *src, int sx, int sy, +		     int w, int h); +	void (*fill)(struct nv04_surface_2d *, struct pipe_surface *dst, +		     int dx, int dy, int w, int h, unsigned value); +}; + +struct nv04_surface_2d * +nv04_surface_2d_init(struct nouveau_winsys *nvws); + +void +nv04_surface_2d_takedown(struct nv04_surface_2d **); + +#endif diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c index 2f945a193c..f417b06c94 100644 --- a/src/gallium/drivers/nv10/nv10_screen.c +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -152,6 +152,14 @@ nv10_screen_destroy(struct pipe_screen *pscreen)  	FREE(pscreen);  } +static struct pipe_buffer * +nv10_surface_buffer(struct pipe_surface *surf) +{ +	struct nv10_miptree *mt = (struct nv10_miptree *)surf->texture; + +	return mt->buffer; +} +  struct pipe_screen *  nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  { @@ -164,6 +172,10 @@ nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  		return NULL;  	screen->nvws = nvws; +	/* 2D engine setup */ +	screen->eng2d = nv04_surface_2d_init(nvws); +	screen->eng2d->buf = nv10_surface_buffer; +  	/* 3D object */  	if (chipset>=0x20)  		celsius_class=NV11TCL; diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h index 3f8750a13f..60102a369a 100644 --- a/src/gallium/drivers/nv10/nv10_screen.h +++ b/src/gallium/drivers/nv10/nv10_screen.h @@ -2,6 +2,7 @@  #define __NV10_SCREEN_H__  #include "pipe/p_screen.h" +#include "nv04/nv04_surface_2d.h"  struct nv10_screen {  	struct pipe_screen pipe; @@ -9,6 +10,7 @@ struct nv10_screen {  	struct nouveau_winsys *nvws;  	/* HW graphics objects */ +	struct nv04_surface_2d *eng2d;  	struct nouveau_grobj *celsius;  	struct nouveau_notifier *sync;  }; diff --git a/src/gallium/drivers/nv10/nv10_surface.c b/src/gallium/drivers/nv10/nv10_surface.c index 78fd7b42da..1093dfd62e 100644 --- a/src/gallium/drivers/nv10/nv10_surface.c +++ b/src/gallium/drivers/nv10/nv10_surface.c @@ -39,10 +39,17 @@ nv10_surface_copy(struct pipe_context *pipe, boolean do_flip,  		  unsigned width, unsigned height)  {  	struct nv10_context *nv10 = nv10_context(pipe); -	struct nouveau_winsys *nvws = nv10->nvws; +	struct nv04_surface_2d *eng2d = nv10->screen->eng2d; -	nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, -			   width, height); +	if (do_flip) { +		desty += height; +		while (height--) { +			eng2d->copy(eng2d, dest, destx, desty--, src, +				    srcx, srcy++, width, 1); +		} +	} + +	eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);  }  static void @@ -51,9 +58,9 @@ nv10_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,  		  unsigned height, unsigned value)  {  	struct nv10_context *nv10 = nv10_context(pipe); -	struct nouveau_winsys *nvws = nv10->nvws; +	struct nv04_surface_2d *eng2d = nv10->screen->eng2d; -	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +	eng2d->fill(eng2d, dest, destx, desty, width, height, value);  }  void diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c index c9171fa178..5f2b7b4f71 100644 --- a/src/gallium/drivers/nv20/nv20_screen.c +++ b/src/gallium/drivers/nv20/nv20_screen.c @@ -152,6 +152,14 @@ nv20_screen_destroy(struct pipe_screen *pscreen)  	FREE(pscreen);  } +static struct pipe_buffer * +nv20_surface_buffer(struct pipe_surface *surf) +{ +	struct nv20_miptree *mt = (struct nv20_miptree *)surf->texture; + +	return mt->buffer; +} +  struct pipe_screen *  nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  { @@ -164,6 +172,10 @@ nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  		return NULL;  	screen->nvws = nvws; +	/* 2D engine setup */ +	screen->eng2d = nv04_surface_2d_init(nvws); +	screen->eng2d->buf = nv20_surface_buffer; +  	/* 3D object */  	if (chipset >= 0x25)  		kelvin_class = NV25TCL; diff --git a/src/gallium/drivers/nv20/nv20_screen.h b/src/gallium/drivers/nv20/nv20_screen.h index 8f2f2e341d..bf2f2c0d9f 100644 --- a/src/gallium/drivers/nv20/nv20_screen.h +++ b/src/gallium/drivers/nv20/nv20_screen.h @@ -2,6 +2,7 @@  #define __NV20_SCREEN_H__  #include "pipe/p_screen.h" +#include "nv04/nv04_surface_2d.h"  struct nv20_screen {  	struct pipe_screen pipe; @@ -9,6 +10,7 @@ struct nv20_screen {  	struct nouveau_winsys *nvws;  	/* HW graphics objects */ +	struct nv04_surface_2d *eng2d;  	struct nouveau_grobj *kelvin;  	struct nouveau_notifier *sync;  }; diff --git a/src/gallium/drivers/nv20/nv20_surface.c b/src/gallium/drivers/nv20/nv20_surface.c index 9b4c028eae..a79974ce5e 100644 --- a/src/gallium/drivers/nv20/nv20_surface.c +++ b/src/gallium/drivers/nv20/nv20_surface.c @@ -39,10 +39,17 @@ nv20_surface_copy(struct pipe_context *pipe, boolean do_flip,  		  unsigned width, unsigned height)  {  	struct nv20_context *nv20 = nv20_context(pipe); -	struct nouveau_winsys *nvws = nv20->nvws; +	struct nv04_surface_2d *eng2d = nv20->screen->eng2d; -	nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, -			   width, height); +	if (do_flip) { +		desty += height; +		while (height--) { +			eng2d->copy(eng2d, dest, destx, desty--, src, +				    srcx, srcy++, width, 1); +		} +	} + +	eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);  }  static void @@ -51,9 +58,9 @@ nv20_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,  		  unsigned height, unsigned value)  {  	struct nv20_context *nv20 = nv20_context(pipe); -	struct nouveau_winsys *nvws = nv20->nvws; +	struct nv04_surface_2d *eng2d = nv20->screen->eng2d; -	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +	eng2d->fill(eng2d, dest, destx, desty, width, height, value);  }  void diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 9738436dc4..2bc83f815b 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -220,6 +220,14 @@ nv30_screen_destroy(struct pipe_screen *pscreen)  	FREE(pscreen);  } +static struct pipe_buffer * +nv30_surface_buffer(struct pipe_surface *surf) +{ +	struct nv30_miptree *mt = (struct nv30_miptree *)surf->texture; + +	return mt->buffer; +} +  struct pipe_screen *  nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  { @@ -233,6 +241,10 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  		return NULL;  	screen->nvws = nvws; +	/* 2D engine setup */ +	screen->eng2d = nv04_surface_2d_init(nvws); +	screen->eng2d->buf = nv30_surface_buffer; +  	/* 3D object */  	switch (chipset & 0xf0) {  	case 0x30: diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h index b7ddc2a959..b11e470f94 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -2,6 +2,7 @@  #define __NV30_SCREEN_H__  #include "pipe/p_screen.h" +#include "nv04/nv04_surface_2d.h"  struct nv30_screen {  	struct pipe_screen pipe; @@ -11,6 +12,7 @@ struct nv30_screen {  	unsigned cur_pctx;  	/* HW graphics objects */ +	struct nv04_surface_2d *eng2d;  	struct nouveau_grobj *rankine;  	struct nouveau_notifier *sync; diff --git a/src/gallium/drivers/nv30/nv30_surface.c b/src/gallium/drivers/nv30/nv30_surface.c index 806131dcc9..b46b6123cf 100644 --- a/src/gallium/drivers/nv30/nv30_surface.c +++ b/src/gallium/drivers/nv30/nv30_surface.c @@ -30,7 +30,6 @@  #include "pipe/p_defines.h"  #include "pipe/internal/p_winsys_screen.h"  #include "pipe/p_inlines.h" -  #include "util/u_tile.h"  static void @@ -40,22 +39,17 @@ nv30_surface_copy(struct pipe_context *pipe, boolean do_flip,  		  unsigned width, unsigned height)  {  	struct nv30_context *nv30 = nv30_context(pipe); -	struct nouveau_winsys *nvws = nv30->nvws; +	struct nv04_surface_2d *eng2d = nv30->screen->eng2d;  	if (do_flip) { -		/*XXX: This dodgyness will do for now for correctness.  But, -		 *     need to investigate whether the 2D engine is able to -		 *     manage a flip (perhaps SIFM?), if not, use the 3D engine -		 */  		desty += height;  		while (height--) { -			nvws->surface_copy(nvws, dest, destx, desty--, src, -					   srcx, srcy++, width, 1); +			eng2d->copy(eng2d, dest, destx, desty--, src, +				    srcx, srcy++, width, 1);  		} -	} else { -		nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, -				   width, height);  	} + +	eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);  }  static void @@ -64,9 +58,9 @@ nv30_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,  		  unsigned height, unsigned value)  {  	struct nv30_context *nv30 = nv30_context(pipe); -	struct nouveau_winsys *nvws = nv30->nvws; +	struct nv04_surface_2d *eng2d = nv30->screen->eng2d; -	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +	eng2d->fill(eng2d, dest, destx, desty, width, height, value);  }  void diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 41d342d27d..a2b124d228 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -230,6 +230,14 @@ nv40_screen_destroy(struct pipe_screen *pscreen)  	FREE(pscreen);  } +static struct pipe_buffer * +nv40_surface_buffer(struct pipe_surface *surf) +{ +	struct nv40_miptree *mt = (struct nv40_miptree *)surf->texture; + +	return mt->buffer; +} +  struct pipe_screen *  nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  { @@ -243,6 +251,10 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)  		return NULL;  	screen->nvws = nvws; +	/* 2D engine setup */ +	screen->eng2d = nv04_surface_2d_init(nvws); +	screen->eng2d->buf = nv40_surface_buffer; +  	/* 3D object */  	switch (chipset & 0xf0) {  	case 0x40: diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index c04a1275a0..4500aa0e5c 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -2,6 +2,7 @@  #define __NV40_SCREEN_H__  #include "pipe/p_screen.h" +#include "nv04/nv04_surface_2d.h"  struct nv40_screen {  	struct pipe_screen pipe; @@ -11,6 +12,7 @@ struct nv40_screen {  	unsigned cur_pctx;  	/* HW graphics objects */ +	struct nv04_surface_2d *eng2d;  	struct nouveau_grobj *curie;  	struct nouveau_notifier *sync; diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c index aa51d04051..68bbfce448 100644 --- a/src/gallium/drivers/nv40/nv40_surface.c +++ b/src/gallium/drivers/nv40/nv40_surface.c @@ -30,7 +30,6 @@  #include "pipe/p_defines.h"  #include "pipe/internal/p_winsys_screen.h"  #include "pipe/p_inlines.h" -  #include "util/u_tile.h"  static void @@ -40,22 +39,17 @@ nv40_surface_copy(struct pipe_context *pipe, boolean do_flip,  		  unsigned width, unsigned height)  {  	struct nv40_context *nv40 = nv40_context(pipe); -	struct nouveau_winsys *nvws = nv40->nvws; +	struct nv04_surface_2d *eng2d = nv40->screen->eng2d;  	if (do_flip) { -		/*XXX: This dodgyness will do for now for correctness.  But, -		 *     need to investigate whether the 2D engine is able to -		 *     manage a flip (perhaps SIFM?), if not, use the 3D engine -		 */  		desty += height;  		while (height--) { -			nvws->surface_copy(nvws, dest, destx, desty--, src, -					   srcx, srcy++, width, 1); +			eng2d->copy(eng2d, dest, destx, desty--, src, +				    srcx, srcy++, width, 1);  		} -	} else { -		nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, -				   width, height);  	} + +	eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);  }  static void @@ -64,9 +58,9 @@ nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,  		  unsigned height, unsigned value)  {  	struct nv40_context *nv40 = nv40_context(pipe); -	struct nouveau_winsys *nvws = nv40->nvws; +	struct nv04_surface_2d *eng2d = nv40->screen->eng2d; -	nvws->surface_fill(nvws, dest, destx, desty, width, height, value); +	eng2d->fill(eng2d, dest, destx, desty, width, height, value);  }  void | 
