diff options
| -rw-r--r-- | src/gallium/drivers/nvfx/Makefile | 1 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nv04_surface_2d.c | 533 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nv04_surface_2d.h | 41 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nvfx_context.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nvfx_miptree.c | 16 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nvfx_resource.h | 5 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nvfx_screen.c | 6 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nvfx_screen.h | 10 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nvfx_state_fb.c | 6 | ||||
| -rw-r--r-- | src/gallium/drivers/nvfx/nvfx_surface.c | 346 | 
10 files changed, 340 insertions, 626 deletions
diff --git a/src/gallium/drivers/nvfx/Makefile b/src/gallium/drivers/nvfx/Makefile index 6536343e44..2834f8984c 100644 --- a/src/gallium/drivers/nvfx/Makefile +++ b/src/gallium/drivers/nvfx/Makefile @@ -4,7 +4,6 @@ include $(TOP)/configs/current  LIBNAME = nvfx  C_SOURCES = \ -	nv04_surface_2d.c \  	nv04_2d.c \  	nvfx_buffer.c \  	nvfx_context.c \ diff --git a/src/gallium/drivers/nvfx/nv04_surface_2d.c b/src/gallium/drivers/nvfx/nv04_surface_2d.c deleted file mode 100644 index cd0f4ce4c9..0000000000 --- a/src/gallium/drivers/nvfx/nv04_surface_2d.c +++ /dev/null @@ -1,533 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_format.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_util.h" -#include "nouveau/nouveau_screen.h" -#include "nv04_surface_2d.h" -#include "nvfx_resource.h" - -static INLINE int -nv04_surface_format(enum pipe_format format) -{ -	switch (format) { -	case PIPE_FORMAT_A8_UNORM: -	case PIPE_FORMAT_L8_UNORM: -	case PIPE_FORMAT_I8_UNORM: -		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8; -	case PIPE_FORMAT_R16_SNORM: -	case PIPE_FORMAT_B5G6R5_UNORM: -	case PIPE_FORMAT_Z16_UNORM: -	case PIPE_FORMAT_L8A8_UNORM: -		return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5; -	case PIPE_FORMAT_B8G8R8X8_UNORM: -	case PIPE_FORMAT_B8G8R8A8_UNORM: -		return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8; -	case PIPE_FORMAT_S8_USCALED_Z24_UNORM: -	case PIPE_FORMAT_X8Z24_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_B5G6R5_UNORM: -	case PIPE_FORMAT_L8A8_UNORM: -	case PIPE_FORMAT_Z16_UNORM: -		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5; -	case PIPE_FORMAT_B8G8R8X8_UNORM: -	case PIPE_FORMAT_B8G8R8A8_UNORM: -	case PIPE_FORMAT_S8_USCALED_Z24_UNORM: -	case PIPE_FORMAT_X8Z24_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_A8_UNORM: -	case PIPE_FORMAT_L8_UNORM: -	case PIPE_FORMAT_I8_UNORM: -		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8; -	case PIPE_FORMAT_B5G5R5A1_UNORM: -		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5; -	case PIPE_FORMAT_B8G8R8A8_UNORM: -		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8; -	case PIPE_FORMAT_B8G8R8X8_UNORM: -		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8; -	case PIPE_FORMAT_B5G6R5_UNORM: -	case PIPE_FORMAT_R16_SNORM: -	case PIPE_FORMAT_L8A8_UNORM: -		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5; -	default: -		return -1; -	} -} - -static INLINE unsigned -nv04_swizzle_bits_square(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; -} - -/* rectangular swizzled textures are linear concatenations of swizzled square tiles */ -static INLINE unsigned -nv04_swizzle_bits(unsigned x, unsigned y, unsigned w, unsigned h) -{ -	unsigned s = MIN2(w, h); -	unsigned m = s - 1; -	return (((x | y) & ~m) * s) | nv04_swizzle_bits_square(x & m, y & m); -} - -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->swzsurf->channel; -	struct nouveau_grobj *swzsurf = ctx->swzsurf; -	struct nouveau_grobj *sifm = ctx->sifm; -	struct nouveau_bo *src_bo = ctx->buf(src); -	struct nouveau_bo *dst_bo = ctx->buf(dst); -	const unsigned src_pitch = ((struct nv04_surface *)src)->pitch; -        /* Max width & height may not be the same on all HW, but must be POT */ -	const unsigned max_w = 1024; -	const unsigned max_h = 1024; -	unsigned sub_w = w > max_w ? max_w : w; -	unsigned sub_h = h > max_h ? max_h : h; -	unsigned x; -	unsigned y; - -        /* Swizzled surfaces must be POT  */ -	assert(util_is_pot(dst->width) && util_is_pot(dst->height)); - -        /* If area is too large to copy in one shot we must copy it in POT chunks to meet alignment requirements */ -	assert(sub_w == w || util_is_pot(sub_w)); -	assert(sub_h == h || util_is_pot(sub_h)); - -	MARK_RING (chan, 8 + ((w+sub_w)/sub_w)*((h+sub_h)/sub_h)*17, 2 + -			 ((w+sub_w)/sub_w)*((h+sub_h)/sub_h)*2); - -	BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1); -	OUT_RELOCo(chan, dst_bo, -	                 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - -	BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1); -	OUT_RING  (chan, nv04_surface_format(dst->format) | -	                 log2i(dst->width) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT | -	                 log2i(dst->height) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT); - -	BEGIN_RING(chan, sifm, NV03_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 (y = 0; y < h; y += sub_h) { -	  sub_h = MIN2(sub_h, h - y); - -	  for (x = 0; x < w; x += sub_w) { -	    sub_w = MIN2(sub_w, w - x); - -	    assert(!(dst->offset & 63)); - -	    BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1); -	    OUT_RELOCl(chan, dst_bo, dst->offset, -                             NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - -	    BEGIN_RING(chan, sifm, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9); -	    OUT_RING  (chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE); -	    OUT_RING  (chan, nv04_scaled_image_format(src->format)); -	    OUT_RING  (chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY); -	    OUT_RING  (chan, (x + dx) | ((y + dy) << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT)); -	    OUT_RING  (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT | sub_w); -	    OUT_RING  (chan, (x + dx) | ((y + dy) << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_SHIFT)); -	    OUT_RING  (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_SHIFT | sub_w); -	    OUT_RING  (chan, 1 << 20); -	    OUT_RING  (chan, 1 << 20); - -	    BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4); -	    OUT_RING  (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_H_SHIFT | sub_w); -	    OUT_RING  (chan, src_pitch | -			     NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | -			     NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); -	    OUT_RELOCl(chan, src_bo, src->offset + (sy+y) * src_pitch + (sx+x) * util_format_get_blocksize(src->texture->format), -                             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->m2mf->channel; -	struct nouveau_grobj *m2mf = ctx->m2mf; -	struct nouveau_bo *src_bo = ctx->buf(src); -	struct nouveau_bo *dst_bo = ctx->buf(dst); -	unsigned src_pitch = ((struct nv04_surface *)src)->pitch; -	unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; -	unsigned dst_offset = dst->offset + dy * dst_pitch + -	                      dx * util_format_get_blocksize(dst->texture->format); -	unsigned src_offset = src->offset + sy * src_pitch + -	                      sx * util_format_get_blocksize(src->texture->format); - -	MARK_RING (chan, 3 + ((h / 2047) + 1) * 9, 2 + ((h / 2047) + 1) * 2); -	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_pitch); -		OUT_RING  (chan, dst_pitch); -		OUT_RING  (chan, w * util_format_get_blocksize(src->texture->format)); -		OUT_RING  (chan, count); -		OUT_RING  (chan, 0x0101); -		OUT_RING  (chan, 0); - -		h -= count; -		src_offset += src_pitch * count; -		dst_offset += dst_pitch * 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->surf2d->channel; -	struct nouveau_grobj *surf2d = ctx->surf2d; -	struct nouveau_grobj *blit = ctx->blit; -	struct nouveau_bo *src_bo = ctx->buf(src); -	struct nouveau_bo *dst_bo = ctx->buf(dst); -	unsigned src_pitch = ((struct nv04_surface *)src)->pitch; -	unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; -	int format; - -	format = nv04_surface_format(dst->format); -	if (format < 0) -		return 1; - -	MARK_RING (chan, 12, 4); -	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_pitch << 16) | src_pitch); -	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->flags & NVFX_RESOURCE_FLAG_LINEAR; -	int dst_linear = dst->texture->flags & NVFX_RESOURCE_FLAG_LINEAR; - -	assert(src->format == dst->format); - -	/* Setup transfer to swizzle the texture to vram if needed */ -        if (src_linear && !dst_linear && w > 1 && h > 1) { -           nv04_surface_copy_swizzle(ctx, dst, dx, dy, src, sx, sy, w, h); -           return; -        } - -        /* Use M2MF instead of the blitter since it always works -         * Any possible performance drop is likely to be not very significant -         * and dwarfed anyway by the current buffer management problems -         */ -        nv04_surface_copy_m2mf(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->surf2d->channel; -	struct nouveau_grobj *surf2d = ctx->surf2d; -	struct nouveau_grobj *rect = ctx->rect; -	struct nouveau_bo *dst_bo = ctx->buf(dst); -	unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; -	int cs2d_format, gdirect_format; - -	cs2d_format = nv04_surface_format(dst->format); -	assert(cs2d_format >= 0); - -	gdirect_format = nv04_rect_format(dst->format); -	assert(gdirect_format >= 0); - -	MARK_RING (chan, 16, 4); -	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_pitch << 16) | dst_pitch); -	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_screen *screen) -{ -	struct nv04_surface_2d *ctx = CALLOC_STRUCT(nv04_surface_2d); -	struct nouveau_channel *chan = screen->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, NV01_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, NV01_IMAGE_BLIT_OPERATION, 1); -	OUT_RING  (chan, NV01_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->surf2d->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; -	} - -	switch (chan->device->chipset & 0xf0) { -	case 0x10: -	case 0x20: -		class = NV10_SCALED_IMAGE_FROM_MEMORY; -		break; -	case 0x30: -		class = NV30_SCALED_IMAGE_FROM_MEMORY; -		break; -	case 0x40: -	case 0x60: -		class = NV40_SCALED_IMAGE_FROM_MEMORY; -		break; -	default: -		class = NV04_SCALED_IMAGE_FROM_MEMORY; -		break; -	} - -	ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->sifm); -	if (ret) { -		nv04_surface_2d_takedown(&ctx); -		return NULL; -	} - -	ctx->copy = nv04_surface_copy; -	ctx->fill = nv04_surface_fill; -	return ctx; -} - -struct nv04_surface* -nv04_surface_wrap_for_render(struct pipe_screen *pscreen, -			     struct nv04_surface_2d* eng2d, struct nv04_surface* ns) -{ -	struct pipe_resource templ; -	struct pipe_resource* temp_tex; -	struct nv04_surface* temp_ns; -	int temp_flags; - -	temp_flags = ns->base.usage; - -	ns->base.usage = 0; - -	memset(&templ, 0, sizeof(templ)); -	templ.format = ns->base.texture->format; -	templ.target = PIPE_TEXTURE_2D; -	templ.width0 = ns->base.width; -	templ.height0 = ns->base.height; -	templ.depth0 = 1; -	templ.last_level = 0; - -	// TODO: this is probably wrong and we should specifically handle multisampling somehow once it is implemented -	templ.nr_samples = ns->base.texture->nr_samples; - -	templ.bind = ns->base.texture->bind | PIPE_BIND_RENDER_TARGET; - -	temp_tex = pscreen->resource_create(pscreen, &templ); -	temp_ns = (struct nv04_surface*)pscreen->get_tex_surface(pscreen, temp_tex, 0, 0, 0, temp_flags); -	temp_ns->backing = ns; - -	if(1) /* hmm */ -		eng2d->copy(eng2d, &temp_ns->backing->base, -			    0, 0, &ns->base, -			    0, 0, ns->base.width, ns->base.height); - -	return temp_ns; -} diff --git a/src/gallium/drivers/nvfx/nv04_surface_2d.h b/src/gallium/drivers/nvfx/nv04_surface_2d.h deleted file mode 100644 index b9020dbe96..0000000000 --- a/src/gallium/drivers/nvfx/nv04_surface_2d.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __NV04_SURFACE_2D_H__ -#define __NV04_SURFACE_2D_H__ - -#include "pipe/p_state.h" - -struct nouveau_screen; - -struct nv04_surface { -	struct pipe_surface base; -	unsigned pitch; -	struct nv04_surface* backing; -}; - -struct nv04_surface_2d { -	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 nouveau_bo *(*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_screen *screen); - -void -nv04_surface_2d_takedown(struct nv04_surface_2d **); - -struct nv04_surface* -nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d* eng2d, struct nv04_surface* ns); - -#endif diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h index 89f94c10bd..278be94d52 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.h +++ b/src/gallium/drivers/nvfx/nvfx_context.h @@ -13,6 +13,7 @@  #include "util/u_inlines.h"  #include "draw/draw_vertex.h" +#include "util/u_blitter.h"  #include "nouveau/nouveau_winsys.h"  #include "nouveau/nouveau_gldefs.h" @@ -88,6 +89,7 @@ struct nvfx_context {  	unsigned is_nv4x; /* either 0 or ~0 */  	struct draw_context *draw; +	struct blitter_context* blitter;  	/* HW state derived from pipe states */  	struct nvfx_state state; diff --git a/src/gallium/drivers/nvfx/nvfx_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c index 27bfa24b28..b8ec726624 100644 --- a/src/gallium/drivers/nvfx/nvfx_miptree.c +++ b/src/gallium/drivers/nvfx/nvfx_miptree.c @@ -8,8 +8,7 @@  #include "state_tracker/drm_driver.h"  #include "nouveau/nouveau_winsys.h"  #include "nouveau/nouveau_screen.h" -#include "nv04_surface_2d.h" -#include "nvfx_context.h" +#include "nvfx_screen.h"  #include "nvfx_resource.h"  #include "nvfx_transfer.h" @@ -231,9 +230,9 @@ nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,  			 unsigned face, unsigned level, unsigned zslice,  			 unsigned flags)  { -	struct nv04_surface *ns; +	struct nvfx_surface *ns; -	ns = CALLOC_STRUCT(nv04_surface); +	ns = CALLOC_STRUCT(nvfx_surface);  	if (!ns)  		return NULL;  	pipe_resource_reference(&ns->base.texture, pt); @@ -254,15 +253,6 @@ nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,  void  nvfx_miptree_surface_del(struct pipe_surface *ps)  { -	struct nv04_surface* ns = (struct nv04_surface*)ps; -	if(ns->backing) -	{ -		struct nvfx_screen* screen = (struct nvfx_screen*)ps->texture->screen; -		if(1 /*ns->backing->base.usage & PIPE_BIND_BLIT_DESTINATION*/) -			screen->eng2d->copy(screen->eng2d, &ns->backing->base, 0, 0, ps, 0, 0, ns->base.width, ns->base.height); -		nvfx_miptree_surface_del(&ns->backing->base); -	} -  	pipe_resource_reference(&ps->texture, NULL);  	FREE(ps);  } diff --git a/src/gallium/drivers/nvfx/nvfx_resource.h b/src/gallium/drivers/nvfx/nvfx_resource.h index 0e24ec2f1f..42d04ebb37 100644 --- a/src/gallium/drivers/nvfx/nvfx_resource.h +++ b/src/gallium/drivers/nvfx/nvfx_resource.h @@ -46,6 +46,11 @@ struct nvfx_miptree {          unsigned level_offset[NVFX_MAX_TEXTURE_LEVELS];  }; +struct nvfx_surface { +	struct pipe_surface base; +	unsigned pitch; +}; +  static INLINE   struct nvfx_resource *nvfx_resource(struct pipe_resource *resource)  { diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index d354bd166a..a1b7c218f1 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -233,7 +233,6 @@ nvfx_screen_surface_format_supported(struct pipe_screen *pscreen,  	return FALSE;  } -  static void  nvfx_screen_destroy(struct pipe_screen *pscreen)  { @@ -245,7 +244,7 @@ nvfx_screen_destroy(struct pipe_screen *pscreen)  	nouveau_notifier_free(&screen->query);  	nouveau_notifier_free(&screen->sync);  	nouveau_grobj_free(&screen->eng3d); -	nv04_surface_2d_takedown(&screen->eng2d); +	nvfx_screen_surface_takedown(pscreen);  	nouveau_screen_fini(&screen->base); @@ -451,8 +450,7 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)  	}  	/* 2D engine setup */ -	screen->eng2d = nv04_surface_2d_init(&screen->base); -	screen->eng2d->buf = nvfx_surface_buffer; +	nvfx_screen_surface_init(pscreen);  	/* Notifier for sync purposes */  	ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); diff --git a/src/gallium/drivers/nvfx/nvfx_screen.h b/src/gallium/drivers/nvfx/nvfx_screen.h index 5e1c3945ae..4dedbe9cb4 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.h +++ b/src/gallium/drivers/nvfx/nvfx_screen.h @@ -3,9 +3,9 @@  #include "util/u_double_list.h"  #include "nouveau/nouveau_screen.h" -#include "nv04_surface_2d.h" +#include "nvfx_context.h" -struct nvfx_context; +struct nv04_2d_context;  struct nvfx_screen {  	struct nouveau_screen base; @@ -20,7 +20,6 @@ struct nvfx_screen {  	unsigned index_buffer_reloc_flags;  	/* HW graphics objects */ -	struct nv04_surface_2d *eng2d;  	struct nouveau_grobj *eng3d;  	struct nouveau_notifier *sync; @@ -32,6 +31,8 @@ struct nvfx_screen {  	/* Vtxprog resources */  	struct nouveau_resource *vp_exec_heap;  	struct nouveau_resource *vp_data_heap; + +	struct nv04_2d_context* eng2d;  };  static INLINE struct nvfx_screen * @@ -40,4 +41,7 @@ nvfx_screen(struct pipe_screen *screen)  	return (struct nvfx_screen *)screen;  } +int nvfx_screen_surface_init(struct pipe_screen *pscreen); +void nvfx_screen_surface_takedown(struct pipe_screen *pscreen); +  #endif diff --git a/src/gallium/drivers/nvfx/nvfx_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c index 657e315f06..e111d11627 100644 --- a/src/gallium/drivers/nvfx/nvfx_state_fb.c +++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c @@ -2,8 +2,6 @@  #include "nvfx_resource.h"  #include "nouveau/nouveau_util.h" - -  void  nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)  { @@ -31,7 +29,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)  		rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i);  		nvfx->hw_rt[i].bo = ((struct nvfx_miptree*)fb->cbufs[i]->texture)->base.bo;  		nvfx->hw_rt[i].offset = fb->cbufs[i]->offset; -		nvfx->hw_rt[i].pitch = ((struct nv04_surface *)fb->cbufs[i])->pitch; +		nvfx->hw_rt[i].pitch = ((struct nvfx_surface *)fb->cbufs[i])->pitch;  	}  	for(; i < 4; ++i)  		nvfx->hw_rt[i].bo = 0; @@ -44,7 +42,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)  		zeta_format = fb->zsbuf->format;  		nvfx->hw_zeta.bo = ((struct nvfx_miptree*)fb->zsbuf->texture)->base.bo;  		nvfx->hw_zeta.offset = fb->zsbuf->offset; -		nvfx->hw_zeta.pitch = ((struct nv04_surface *)fb->zsbuf)->pitch; +		nvfx->hw_zeta.pitch = ((struct nvfx_surface *)fb->zsbuf)->pitch;  	}  	else  		nvfx->hw_zeta.bo = 0; diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c index a605d2b754..a97f342c64 100644 --- a/src/gallium/drivers/nvfx/nvfx_surface.c +++ b/src/gallium/drivers/nvfx/nvfx_surface.c @@ -26,33 +26,319 @@   *   **************************************************************************/ +#include "pipe/p_context.h" +#include "pipe/p_format.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_pack_color.h" +#include "util/u_rect.h" +#include "util/u_blitter.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_util.h" +#include "nouveau/nouveau_screen.h"  #include "nvfx_context.h" +#include "nvfx_screen.h"  #include "nvfx_resource.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" -#include "util/u_pack_color.h" +#include "nv04_2d.h" + +#include <nouveau/nouveau_bo.h> + +static INLINE void +nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format) +{ +	unsigned bits = util_format_get_blocksizebits(format); +	switch(bits) +	{ +	case 8: +		rgn->bpps = 0; +		break; +	case 16: +		rgn->bpps = 1; +		break; +	case 32: +		rgn->bpps = 2; +		break; +	default: +		assert(util_is_pot(bits)); +		int shift = log2i(bits) - 3; +		assert(shift >= 2); +		rgn->bpps = 2; +		shift -= 2; + +		rgn->x = util_format_get_nblocksx(format, rgn->x) << shift; +		rgn->y = util_format_get_nblocksy(format, rgn->y); +	} +} + +static INLINE void +nvfx_region_fixup_swizzled(struct nv04_region* rgn, unsigned zslice, unsigned width, unsigned height, unsigned depth) +{ +	// TODO: move this code to surface creation? +	if((depth <= 1) && (height <= 1 || width <= 2)) +		rgn->pitch = width << rgn->bpps; +	else if(depth > 1 && height <= 2 && width <= 2) +	{ +		rgn->pitch = width << rgn->bpps; +		rgn->offset += (zslice * width * height) << rgn->bpps; +	} +	else +	{ +		rgn->pitch = 0; +		rgn->z = zslice; +		rgn->w = width; +		rgn->h = height; +		rgn->d = depth; +	} +} + +static INLINE void +nvfx_region_init_for_surface(struct nv04_region* rgn, struct nvfx_surface* surf, unsigned x, unsigned y) +{ +	rgn->bo = ((struct nvfx_resource*)surf->base.texture)->bo; +	rgn->offset = surf->base.offset; +	rgn->pitch = surf->pitch; +	rgn->x = x; +	rgn->y = y; +	rgn->z = 0; + +	nvfx_region_set_format(rgn, surf->base.format); +	if(!(surf->base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR)) +		nvfx_region_fixup_swizzled(rgn, surf->base.zslice, surf->base.width, surf->base.height, u_minify(surf->base.texture->depth0, surf->base.level)); +} + +static INLINE void +nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource* pt, struct pipe_subresource sub, unsigned x, unsigned y, unsigned z) +{ +	rgn->bo = ((struct nvfx_resource*)pt)->bo; +	rgn->offset = nvfx_subresource_offset(pt, sub.face, sub.level, z); +	rgn->pitch = nvfx_subresource_pitch(pt, sub.level); +	rgn->x = x; +	rgn->y = y; +	rgn->z = 0; + +	nvfx_region_set_format(rgn, pt->format); +	if(!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR)) +		nvfx_region_fixup_swizzled(rgn, z, u_minify(pt->width0, sub.level), u_minify(pt->height0, sub.level), u_minify(pt->depth0, sub.level)); +} + +// TODO: actually test this for all formats, it's probably wrong for some... + +static INLINE int +nvfx_surface_format(enum pipe_format format) +{ +	switch(util_format_get_blocksize(format)) { +	case 1: +		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8; +	case 2: +		//return NV04_CONTEXT_SURFACES_2D_FORMAT_Y16; +		return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5; +	case 4: +		//if(format == PIPE_FORMAT_B8G8R8X8_UNORM || format == PIPE_FORMAT_B8G8R8A8_UNORM) +			return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8; +		//else +		//	return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32; +	default: +		return -1; +	} +} + +static INLINE int +nv04_scaled_image_format(enum pipe_format format) +{ +	switch(util_format_get_blocksize(format)) { +	case 1: +		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8; +	case 2: +		//if(format == PIPE_FORMAT_B5G5R5A1_UNORM) +		//	return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5; +		//else +			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5; +	case 4: +		if(format == PIPE_FORMAT_B8G8R8X8_UNORM) +			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8; +		else +			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8; +	default: +		return -1; +	} +} + +static struct blitter_context* +nvfx_get_blitter(struct pipe_context* pipe, int copy) +{ +	struct nvfx_context* nvfx = nvfx_context(pipe); + +	struct blitter_context* blitter = nvfx->blitter; +	if(!blitter) +		nvfx->blitter = blitter = util_blitter_create(pipe); + +	util_blitter_save_blend(blitter, nvfx->blend); +	util_blitter_save_depth_stencil_alpha(blitter, nvfx->zsa); +	util_blitter_save_stencil_ref(blitter, &nvfx->stencil_ref); +	util_blitter_save_rasterizer(blitter, nvfx->rasterizer); +	util_blitter_save_fragment_shader(blitter, nvfx->fragprog); +	util_blitter_save_vertex_shader(blitter, nvfx->vertprog); +	util_blitter_save_viewport(blitter, &nvfx->viewport); +	util_blitter_save_framebuffer(blitter, &nvfx->framebuffer); +	util_blitter_save_clip(blitter, &nvfx->clip); +	util_blitter_save_vertex_elements(blitter, nvfx->vtxelt); +	util_blitter_save_vertex_buffers(blitter, nvfx->vtxbuf_nr, nvfx->vtxbuf); + +	if(copy) +	{ +		util_blitter_save_fragment_sampler_states(blitter, nvfx->nr_samplers, (void**)nvfx->tex_sampler); +		util_blitter_save_fragment_sampler_views(blitter, nvfx->nr_textures, nvfx->fragment_sampler_views); +	} + +	return blitter; +} + +static unsigned +nvfx_region_clone(struct nv04_2d_context* ctx, struct nv04_region* rgn, unsigned w, unsigned h, boolean for_read) +{ +	unsigned begin = nv04_region_begin(rgn, w, h); +	unsigned end = nv04_region_end(rgn, w, h); +	unsigned size = end - begin; +	struct nouveau_bo* bo = 0; +	nouveau_bo_new(rgn->bo->device, NOUVEAU_BO_MAP | NOUVEAU_BO_GART, 256, size, &bo); + +	if(for_read || (size > ((w * h) << rgn->bpps))) +		nv04_memcpy(ctx, bo, 0, rgn->bo, rgn->offset + begin, size); + +	rgn->bo = bo; +	rgn->offset = -begin; +	return begin; +}  static void -nvfx_surface_copy(struct pipe_context *pipe, -		  struct pipe_resource *dest, struct pipe_subresource subdst, -		  unsigned destx, unsigned desty, unsigned destz, -		  struct pipe_resource *src, struct pipe_subresource subsrc, +nvfx_resource_copy_region(struct pipe_context *pipe, +		  struct pipe_resource *dstr, struct pipe_subresource subdst, +		  unsigned dstx, unsigned dsty, unsigned dstz, +		  struct pipe_resource *srcr, struct pipe_subresource subsrc,  		  unsigned srcx, unsigned srcy, unsigned srcz, -		  unsigned width, unsigned height) +		  unsigned w, unsigned h)  { -	struct nvfx_context *nvfx = nvfx_context(pipe); -	struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; -	struct pipe_surface *ps_dst, *ps_src; +	struct nv04_2d_context *ctx = nvfx_screen(pipe->screen)->eng2d; +	struct nv04_region dst, src; + +	if(!w || !h) +		return; + +	static int copy_threshold = -1; +	if(copy_threshold < 0) +	{ +		copy_threshold = debug_get_num_option("NOUVEAU_COPY_THRESHOLD", 0); +		if(copy_threshold < 0) +			copy_threshold = 0; +	} -	ps_src = nvfx_miptree_surface_new(pipe->screen, src, subsrc.face, -					  subsrc.level, srcz, 0 /* bind flags */); -	ps_dst = nvfx_miptree_surface_new(pipe->screen, dest, subdst.face, -					  subdst.level, destz, 0 /* bindflags */); +	int dst_to_gpu = dstr->usage != PIPE_USAGE_DYNAMIC && dstr->usage != PIPE_USAGE_STAGING; +	int src_on_gpu = nvfx_resource_on_gpu(srcr); -	eng2d->copy(eng2d, ps_dst, destx, desty, ps_src, srcx, srcy, width, height); +	nvfx_region_init_for_subresource(&dst, dstr, subdst, dstx, dsty, dstz); +	nvfx_region_init_for_subresource(&src, srcr, subsrc, srcx, srcy, srcz); +	w = util_format_get_stride(dstr->format, w) >> dst.bpps; +	h = util_format_get_nblocksy(dstr->format, h); -	nvfx_miptree_surface_del(ps_src); -	nvfx_miptree_surface_del(ps_dst); +	int ret; +	boolean small = (w * h <= copy_threshold); +	if((!dst_to_gpu || !src_on_gpu) && small) +		ret = -1; /* use the CPU */ +	else +		ret = nv04_region_copy_2d(ctx, &dst, &src, w, h, +			dstr->target == PIPE_BUFFER ? -1 : nvfx_surface_format(dstr->format), +			dstr->target == PIPE_BUFFER ? -1 : nv04_scaled_image_format(dstr->format), +			dst_to_gpu, src_on_gpu); +	if(!ret) +	{} +	else if(ret > 0 && dstr->bind & PIPE_BIND_RENDER_TARGET && srcr->bind & PIPE_BIND_SAMPLER_VIEW) +	{ +		struct blitter_context* blitter = nvfx_get_blitter(pipe, 1); +		util_blitter_copy_region(blitter, dstr, subdst, dstx, dsty, dstz, srcr, subsrc, srcx, srcy, srcz, w, h, TRUE); +	} +	else +	{ +		struct nv04_region dstt = dst; +		struct nv04_region srct = src; +		unsigned dstbegin = 0; + +		if(!small) +		{ +			if(src_on_gpu) +				nvfx_region_clone(ctx, &srct, w, h, TRUE); + +			if(dst_to_gpu) +				dstbegin = nvfx_region_clone(ctx, &dstt, w, h, FALSE); +		} + +		nv04_region_copy_cpu(&dstt, &srct, w, h); + +		if(srct.bo != src.bo) +			nouveau_screen_bo_release(pipe->screen, srct.bo); + +		if(dstt.bo != dst.bo) +		{ +			nv04_memcpy(ctx, dst.bo, dst.offset + dstbegin, dstt.bo, 0, dstt.bo->size); +			nouveau_screen_bo_release(pipe->screen, dstt.bo); +		} +	} +} + +static int +nvfx_surface_fill(struct pipe_context* pipe, struct pipe_surface *dsts, +		  unsigned dx, unsigned dy, unsigned w, unsigned h, unsigned value) +{ +	struct nv04_2d_context *ctx = nvfx_screen(pipe->screen)->eng2d; +	struct nv04_region dst; +	/* Always try to use the GPU right now, if possible +	 * If the user wanted the surface data on the CPU, he would have cleared with memset */ + +	// we don't care about interior pixel order since we set all them to the same value +	nvfx_region_init_for_surface(&dst, (struct nvfx_surface*)dsts, dx, dy); +	w = util_format_get_stride(dsts->format, w) >> dst.bpps; +	h = util_format_get_nblocksy(dsts->format, h); + +	int ret = nv04_region_fill_2d(ctx, &dst, w, h, value); +	if(ret > 0 && dsts->texture->bind & PIPE_BIND_RENDER_TARGET) +		return 1; +	else if(ret) +	{ +		struct nv04_region dstt = dst; +		unsigned dstbegin = 0; + +		if(nvfx_resource_on_gpu(dsts->texture)) +			dstbegin = nvfx_region_clone(ctx, &dstt, w, h, FALSE); + +		nv04_region_fill_cpu(&dstt, w, h, value); + +		if(dstt.bo != dst.bo) +		{ +			nv04_memcpy(ctx, dst.bo, dst.offset + dstbegin, dstt.bo, 0, dstt.bo->size); +			nouveau_screen_bo_release(pipe->screen, dstt.bo); +		} +	} + +	return 0; +} + + +void +nvfx_screen_surface_takedown(struct pipe_screen *pscreen) +{ +	nv04_2d_context_takedown(nvfx_screen(pscreen)->eng2d); +	nvfx_screen(pscreen)->eng2d = 0; +} + +int +nvfx_screen_surface_init(struct pipe_screen *pscreen) +{ +	struct nv04_2d_context* ctx = nv04_2d_context_init(nouveau_screen(pscreen)->channel); +	if(!ctx) +		return -1; +	nvfx_screen(pscreen)->eng2d = ctx; +	return 0;  }  static void @@ -62,12 +348,16 @@ nvfx_clear_render_target(struct pipe_context *pipe,  			 unsigned dstx, unsigned dsty,  			 unsigned width, unsigned height)  { -	struct nvfx_context *nvfx = nvfx_context(pipe); -	struct nv04_surface_2d *eng2d = nvfx->screen->eng2d;  	union util_color uc;  	util_pack_color(rgba, dst->format, &uc); -	eng2d->fill(eng2d, dst, dstx, dsty, width, height, uc.ui); +	if(util_format_get_blocksizebits(dst->format) > 32 +		|| nvfx_surface_fill(pipe, dst, dstx, dsty, width, height, uc.ui)) +	{ +		// TODO: probably should use hardware clear here instead if possible +		struct blitter_context* blitter = nvfx_get_blitter(pipe, 0); +		util_blitter_clear_render_target(blitter, dst, rgba, dstx, dsty, width, height); +	}  }  static void @@ -79,18 +369,20 @@ nvfx_clear_depth_stencil(struct pipe_context *pipe,  			 unsigned dstx, unsigned dsty,  			 unsigned width, unsigned height)  { -	struct nvfx_context *nvfx = nvfx_context(pipe); -	struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; - -	eng2d->fill(eng2d, dst, dstx, dsty, width, height, -		    util_pack_z_stencil(dst->format, depth, stencil)); +	if(util_format_get_blocksizebits(dst->format) > 32 +		|| nvfx_surface_fill(pipe, dst, dstx, dsty, width, height, util_pack_z_stencil(dst->format, depth, stencil))) +	{ +		// TODO: probably should use hardware clear here instead if possible +		struct blitter_context* blitter = nvfx_get_blitter(pipe, 0); +		util_blitter_clear_depth_stencil(blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height); +	}  }  void  nvfx_init_surface_functions(struct nvfx_context *nvfx)  { -	nvfx->pipe.resource_copy_region = nvfx_surface_copy; +	nvfx->pipe.resource_copy_region = nvfx_resource_copy_region;  	nvfx->pipe.clear_render_target = nvfx_clear_render_target;  	nvfx->pipe.clear_depth_stencil = nvfx_clear_depth_stencil;  }  | 
