[Mesa-dev] [PATCH 8/9] nouveau: Move contents of nv04_surface to nouveau_surface

Ian Romanick idr at freedesktop.org
Fri May 19 13:38:10 UTC 2017


From: Ian Romanick <ian.d.romanick at intel.com>

All of these functions are also used by the NV10 and NV20 drivers.  It
makes sense for them to be in the common file and have the common names
(next patch).

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
Cc: Ilia Mirkin <imirkin at alum.mit.edu>
---
 src/mesa/drivers/dri/nouveau/Makefile.sources  |   1 -
 src/mesa/drivers/dri/nouveau/nouveau_surface.c | 586 +++++++++++++++++++++++
 src/mesa/drivers/dri/nouveau/nouveau_surface.h |  17 +
 src/mesa/drivers/dri/nouveau/nv04_driver.h     |  18 -
 src/mesa/drivers/dri/nouveau/nv04_surface.c    | 615 -------------------------
 5 files changed, 603 insertions(+), 634 deletions(-)
 delete mode 100644 src/mesa/drivers/dri/nouveau/nv04_surface.c

diff --git a/src/mesa/drivers/dri/nouveau/Makefile.sources b/src/mesa/drivers/dri/nouveau/Makefile.sources
index 3eff3b8..0f4fba4 100644
--- a/src/mesa/drivers/dri/nouveau/Makefile.sources
+++ b/src/mesa/drivers/dri/nouveau/Makefile.sources
@@ -34,7 +34,6 @@ NOUVEAU_DRIVER_FILES = \
 	nv04_state_frag.c \
 	nv04_state_raster.c \
 	nv04_state_tex.c \
-	nv04_surface.c \
 	nv10_3d.xml.h \
 	nv10_context.c \
 	nv10_driver.h \
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_surface.c b/src/mesa/drivers/dri/nouveau/nouveau_surface.c
index ffac309..af5c924 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_surface.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_surface.c
@@ -27,6 +27,11 @@
 #include "nouveau_driver.h"
 #include "nouveau_context.h"
 #include "nouveau_util.h"
+#include "nv_object.xml.h"
+#include "nv_m2mf.xml.h"
+#include "nv01_2d.xml.h"
+#include "nv04_3d.xml.h"
+#include "nv04_driver.h"
 
 #include "main/formats.h"
 
@@ -90,3 +95,584 @@ nouveau_surface_ref(struct nouveau_surface *src,
 		nouveau_bo_ref(NULL, &dst->bo);
 	}
 }
+
+static inline int
+swzsurf_format(mesa_format format)
+{
+	switch (format) {
+	case MESA_FORMAT_A_UNORM8:
+	case MESA_FORMAT_L_UNORM8:
+	case MESA_FORMAT_I_UNORM8:
+	case MESA_FORMAT_B2G3R3_UNORM:
+		return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8;
+
+	case MESA_FORMAT_B5G6R5_UNORM:
+	case MESA_FORMAT_R5G6B5_UNORM:
+	case MESA_FORMAT_B4G4R4A4_UNORM:
+	case MESA_FORMAT_A4R4G4B4_UNORM:
+	case MESA_FORMAT_B5G5R5A1_UNORM:
+	case MESA_FORMAT_A1B5G5R5_UNORM:
+	case MESA_FORMAT_A1R5G5B5_UNORM:
+	case MESA_FORMAT_L8A8_UNORM:
+	case MESA_FORMAT_A8L8_UNORM:
+	case MESA_FORMAT_YCBCR:
+	case MESA_FORMAT_YCBCR_REV:
+	case MESA_FORMAT_Z_UNORM16:
+		return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5;
+
+	case MESA_FORMAT_A8B8G8R8_UNORM:
+	case MESA_FORMAT_R8G8B8A8_UNORM:
+	case MESA_FORMAT_B8G8R8X8_UNORM:
+	case MESA_FORMAT_B8G8R8A8_UNORM:
+	case MESA_FORMAT_A8R8G8B8_UNORM:
+	case MESA_FORMAT_Z24_UNORM_S8_UINT:
+	case MESA_FORMAT_S8_UINT_Z24_UNORM:
+	case MESA_FORMAT_Z_UNORM32:
+		return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8;
+
+	default:
+		assert(0);
+	}
+}
+
+static inline int
+surf2d_format(mesa_format format)
+{
+	switch (format) {
+	case MESA_FORMAT_A_UNORM8:
+	case MESA_FORMAT_L_UNORM8:
+	case MESA_FORMAT_I_UNORM8:
+	case MESA_FORMAT_B2G3R3_UNORM:
+		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+
+	case MESA_FORMAT_B5G6R5_UNORM:
+	case MESA_FORMAT_R5G6B5_UNORM:
+	case MESA_FORMAT_B4G4R4A4_UNORM:
+	case MESA_FORMAT_A4R4G4B4_UNORM:
+	case MESA_FORMAT_B5G5R5A1_UNORM:
+	case MESA_FORMAT_A1B5G5R5_UNORM:
+	case MESA_FORMAT_A1R5G5B5_UNORM:
+	case MESA_FORMAT_L8A8_UNORM:
+	case MESA_FORMAT_A8L8_UNORM:
+	case MESA_FORMAT_YCBCR:
+	case MESA_FORMAT_YCBCR_REV:
+	case MESA_FORMAT_Z_UNORM16:
+		return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+
+	case MESA_FORMAT_A8B8G8R8_UNORM:
+	case MESA_FORMAT_R8G8B8A8_UNORM:
+	case MESA_FORMAT_B8G8R8X8_UNORM:
+	case MESA_FORMAT_B8G8R8A8_UNORM:
+	case MESA_FORMAT_A8R8G8B8_UNORM:
+	case MESA_FORMAT_Z24_UNORM_S8_UINT:
+	case MESA_FORMAT_S8_UINT_Z24_UNORM:
+	case MESA_FORMAT_Z_UNORM32:
+		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
+
+	default:
+		assert(0);
+	}
+}
+
+static inline int
+rect_format(mesa_format format)
+{
+	switch (format) {
+	case MESA_FORMAT_A_UNORM8:
+	case MESA_FORMAT_L_UNORM8:
+	case MESA_FORMAT_I_UNORM8:
+	case MESA_FORMAT_B2G3R3_UNORM:
+		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+
+	case MESA_FORMAT_B5G6R5_UNORM:
+	case MESA_FORMAT_R5G6B5_UNORM:
+	case MESA_FORMAT_B4G4R4A4_UNORM:
+	case MESA_FORMAT_A4R4G4B4_UNORM:
+	case MESA_FORMAT_B5G5R5A1_UNORM:
+	case MESA_FORMAT_A1B5G5R5_UNORM:
+	case MESA_FORMAT_A1R5G5B5_UNORM:
+	case MESA_FORMAT_L8A8_UNORM:
+	case MESA_FORMAT_A8L8_UNORM:
+	case MESA_FORMAT_YCBCR:
+	case MESA_FORMAT_YCBCR_REV:
+	case MESA_FORMAT_Z_UNORM16:
+		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
+
+	case MESA_FORMAT_A8B8G8R8_UNORM:
+	case MESA_FORMAT_R8G8B8A8_UNORM:
+	case MESA_FORMAT_B8G8R8X8_UNORM:
+	case MESA_FORMAT_B8G8R8A8_UNORM:
+	case MESA_FORMAT_A8R8G8B8_UNORM:
+	case MESA_FORMAT_Z24_UNORM_S8_UINT:
+	case MESA_FORMAT_S8_UINT_Z24_UNORM:
+	case MESA_FORMAT_Z_UNORM32:
+		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+
+	default:
+		assert(0);
+	}
+}
+
+static inline int
+sifm_format(mesa_format format)
+{
+	switch (format) {
+	case MESA_FORMAT_A_UNORM8:
+	case MESA_FORMAT_L_UNORM8:
+	case MESA_FORMAT_I_UNORM8:
+	case MESA_FORMAT_B2G3R3_UNORM:
+		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8;
+
+	case MESA_FORMAT_B5G6R5_UNORM:
+	case MESA_FORMAT_R5G6B5_UNORM:
+	case MESA_FORMAT_B4G4R4A4_UNORM:
+	case MESA_FORMAT_A4R4G4B4_UNORM:
+	case MESA_FORMAT_B5G5R5A1_UNORM:
+	case MESA_FORMAT_A1B5G5R5_UNORM:
+	case MESA_FORMAT_A1R5G5B5_UNORM:
+	case MESA_FORMAT_L8A8_UNORM:
+	case MESA_FORMAT_A8L8_UNORM:
+	case MESA_FORMAT_YCBCR:
+	case MESA_FORMAT_YCBCR_REV:
+	case MESA_FORMAT_Z_UNORM16:
+		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
+
+	case MESA_FORMAT_A8B8G8R8_UNORM:
+	case MESA_FORMAT_R8G8B8A8_UNORM:
+	case MESA_FORMAT_B8G8R8X8_UNORM:
+	case MESA_FORMAT_B8G8R8A8_UNORM:
+	case MESA_FORMAT_A8R8G8B8_UNORM:
+	case MESA_FORMAT_Z24_UNORM_S8_UINT:
+	case MESA_FORMAT_S8_UINT_Z24_UNORM:
+	case MESA_FORMAT_Z_UNORM32:
+		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
+
+	default:
+		assert(0);
+	}
+}
+
+static void
+nv04_surface_copy_swizzle(struct gl_context *ctx,
+			  struct nouveau_surface *dst,
+			  struct nouveau_surface *src,
+			  int dx, int dy, int sx, int sy,
+			  int w, int h)
+{
+	struct nouveau_pushbuf_refn refs[] = {
+		{ src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
+		{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
+	};
+	struct nouveau_pushbuf *push = context_push(ctx);
+	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
+	struct nouveau_object *swzsurf = hw->swzsurf;
+	struct nv04_fifo *fifo = hw->chan->data;
+	/* 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, y;
+
+        /* Swizzled surfaces must be POT  */
+	assert(_mesa_is_pow_two(dst->width) &&
+	       _mesa_is_pow_two(dst->height));
+
+	if (context_chipset(ctx) < 0x10) {
+		BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
+		PUSH_DATA (push, 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);
+
+			if (nouveau_pushbuf_space(push, 64, 4, 0) ||
+			    nouveau_pushbuf_refn (push, refs, 2))
+				return;
+
+			BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);
+			PUSH_DATA (push, fifo->vram);
+			BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);
+			PUSH_DATA (push, swzsurf_format(dst->format) |
+					 log2i(dst->width) << 16 |
+					 log2i(dst->height) << 24);
+			PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
+
+			BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
+			PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+			BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
+			PUSH_DATA (push, swzsurf->handle);
+
+			BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);
+			PUSH_DATA (push, sifm_format(src->format));
+			PUSH_DATA (push, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
+			PUSH_DATA (push, (y + dy) << 16 | (x + dx));
+			PUSH_DATA (push, sub_h << 16 | sub_w);
+			PUSH_DATA (push, (y + dy) << 16 | (x + dx));
+			PUSH_DATA (push, sub_h << 16 | sub_w);
+			PUSH_DATA (push, 1 << 20);
+			PUSH_DATA (push, 1 << 20);
+
+			BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
+			PUSH_DATA (push, align(sub_h, 2) << 16 | align(sub_w, 2));
+			PUSH_DATA (push, src->pitch  |
+					 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
+					 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
+			PUSH_RELOC(push, src->bo, src->offset + (y + sy) * src->pitch +
+					 (x + sx) * src->cpp, NOUVEAU_BO_LOW, 0, 0);
+			PUSH_DATA (push, 0);
+		}
+	}
+
+	if (context_chipset(ctx) < 0x10) {
+		BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
+		PUSH_DATA (push, hw->surf3d->handle);
+	}
+}
+
+static void
+nv04_surface_copy_m2mf(struct gl_context *ctx,
+		       struct nouveau_surface *dst,
+		       struct nouveau_surface *src,
+		       int dx, int dy, int sx, int sy,
+		       int w, int h)
+{
+	struct nouveau_pushbuf_refn refs[] = {
+		{ src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
+		{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
+	};
+	struct nouveau_pushbuf *push = context_push(ctx);
+	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
+	struct nv04_fifo *fifo = hw->chan->data;
+	unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp;
+	unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp;
+
+	while (h) {
+		int count = (h > 2047) ? 2047 : h;
+
+		if (nouveau_pushbuf_space(push, 16, 4, 0) ||
+		    nouveau_pushbuf_refn (push, refs, 2))
+			return;
+
+		BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
+		PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+		PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+		BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
+		PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
+		PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
+		PUSH_DATA (push, src->pitch);
+		PUSH_DATA (push, dst->pitch);
+		PUSH_DATA (push, w * src->cpp);
+		PUSH_DATA (push, count);
+		PUSH_DATA (push, 0x0101);
+		PUSH_DATA (push, 0);
+
+		src_offset += src->pitch * count;
+		dst_offset += dst->pitch * count;
+		h -= count;
+	}
+}
+
+typedef unsigned (*get_offset_t)(struct nouveau_surface *s,
+				 unsigned x, unsigned y);
+
+static unsigned
+get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y)
+{
+	return x * s->cpp + y * s->pitch;
+}
+
+static unsigned
+get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y)
+{
+	unsigned k = log2i(MIN2(s->width, s->height));
+
+	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 s->cpp * (((u | v) & ~(~0 << 2*k)) |
+			 (x & (~0 << k)) << k |
+			 (y & (~0 << k)) << k);
+}
+
+static void
+nv04_surface_copy_cpu(struct gl_context *ctx,
+		      struct nouveau_surface *dst,
+		      struct nouveau_surface *src,
+		      int dx, int dy, int sx, int sy,
+		      int w, int h)
+{
+	int x, y;
+	get_offset_t get_dst = (dst->layout == SWIZZLED ?
+				get_swizzled_offset : get_linear_offset);
+	get_offset_t get_src = (src->layout == SWIZZLED ?
+				get_swizzled_offset : get_linear_offset);
+	void *dp, *sp;
+
+	nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, context_client(ctx));
+	nouveau_bo_map(src->bo, NOUVEAU_BO_RD, context_client(ctx));
+
+	dp = dst->bo->map + dst->offset;
+	sp = src->bo->map + src->offset;
+
+	for (y = 0; y < h; y++) {
+		for (x = 0; x < w; x++) {
+			memcpy(dp + get_dst(dst, dx + x, dy + y),
+			       sp + get_src(src, sx + x, sy + y), dst->cpp);
+		}
+	}
+}
+
+void
+nv04_surface_copy(struct gl_context *ctx,
+		  struct nouveau_surface *dst,
+		  struct nouveau_surface *src,
+		  int dx, int dy, int sx, int sy,
+		  int w, int h)
+{
+	if (_mesa_is_format_compressed(src->format)) {
+		sx = get_format_blocksx(src->format, sx);
+		sy = get_format_blocksy(src->format, sy);
+		dx = get_format_blocksx(dst->format, dx);
+		dy = get_format_blocksy(dst->format, dy);
+		w = get_format_blocksx(src->format, w);
+		h = get_format_blocksy(src->format, h);
+	}
+
+	/* Linear texture copy. */
+	if ((src->layout == LINEAR && dst->layout == LINEAR) ||
+	    dst->width <= 2 || dst->height <= 1) {
+		nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
+		return;
+	}
+
+	/* Swizzle using sifm+swzsurf. */
+        if (src->layout == LINEAR && dst->layout == SWIZZLED &&
+	    dst->cpp != 1 && !(dst->offset & 63)) {
+		nv04_surface_copy_swizzle(ctx, dst, src, dx, dy, sx, sy, w, h);
+		return;
+	}
+
+	/* Fallback to CPU copy. */
+	nv04_surface_copy_cpu(ctx, dst, src, dx, dy, sx, sy, w, h);
+}
+
+void
+nv04_surface_fill(struct gl_context *ctx,
+		  struct nouveau_surface *dst,
+		  unsigned mask, unsigned value,
+		  int dx, int dy, int w, int h)
+{
+	struct nouveau_pushbuf_refn refs[] = {
+		{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
+	};
+	struct nouveau_pushbuf *push = context_push(ctx);
+	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
+	struct nv04_fifo *fifo = hw->chan->data;
+
+	if (nouveau_pushbuf_space(push, 64, 4, 0) ||
+	    nouveau_pushbuf_refn (push, refs, 1))
+		return;
+
+	BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);
+	PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+	PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+	BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
+	PUSH_DATA (push, surf2d_format(dst->format));
+	PUSH_DATA (push, (dst->pitch << 16) | dst->pitch);
+	PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
+	PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
+
+	BEGIN_NV04(push, NV01_PATT(COLOR_FORMAT), 1);
+	PUSH_DATA (push, rect_format(dst->format));
+	BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR1), 1);
+	PUSH_DATA (push, mask | ~0ll << (8 * dst->cpp));
+
+	BEGIN_NV04(push, NV04_GDI(COLOR_FORMAT), 1);
+	PUSH_DATA (push, rect_format(dst->format));
+	BEGIN_NV04(push, NV04_GDI(COLOR1_A), 1);
+	PUSH_DATA (push, value);
+	BEGIN_NV04(push, NV04_GDI(UNCLIPPED_RECTANGLE_POINT(0)), 2);
+	PUSH_DATA (push, (dx << 16) | dy);
+	PUSH_DATA (push, ( w << 16) |  h);
+}
+
+void
+nv04_surface_takedown(struct gl_context *ctx)
+{
+	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
+
+	nouveau_object_del(&hw->swzsurf);
+	nouveau_object_del(&hw->sifm);
+	nouveau_object_del(&hw->rect);
+	nouveau_object_del(&hw->rop);
+	nouveau_object_del(&hw->patt);
+	nouveau_object_del(&hw->surf2d);
+	nouveau_object_del(&hw->m2mf);
+	nouveau_object_del(&hw->ntfy);
+}
+
+GLboolean
+nv04_surface_init(struct gl_context *ctx)
+{
+	struct nouveau_pushbuf *push = context_push(ctx);
+	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
+	struct nouveau_object *chan = hw->chan;
+	unsigned handle = 0x88000000, class;
+	int ret;
+
+	/* Notifier object. */
+	ret = nouveau_object_new(chan, handle++, NOUVEAU_NOTIFIER_CLASS,
+				 &(struct nv04_notify) {
+					.length = 32,
+				 }, sizeof(struct nv04_notify), &hw->ntfy);
+	if (ret)
+		goto fail;
+
+	/* Memory to memory format. */
+	ret = nouveau_object_new(chan, handle++, NV03_M2MF_CLASS,
+				 NULL, 0, &hw->m2mf);
+	if (ret)
+		goto fail;
+
+	BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
+	PUSH_DATA (push, hw->m2mf->handle);
+	BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
+	PUSH_DATA (push, hw->ntfy->handle);
+
+	/* Context surfaces 2D. */
+	if (context_chipset(ctx) < 0x10)
+		class = NV04_SURFACE_2D_CLASS;
+	else
+		class = NV10_SURFACE_2D_CLASS;
+
+	ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->surf2d);
+	if (ret)
+		goto fail;
+
+	BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1);
+	PUSH_DATA (push, hw->surf2d->handle);
+
+	/* Raster op. */
+	ret = nouveau_object_new(chan, handle++, NV03_ROP_CLASS,
+				 NULL, 0, &hw->rop);
+	if (ret)
+		goto fail;
+
+	BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
+	PUSH_DATA (push, hw->rop->handle);
+	BEGIN_NV04(push, NV01_ROP(DMA_NOTIFY), 1);
+	PUSH_DATA (push, hw->ntfy->handle);
+
+	BEGIN_NV04(push, NV01_ROP(ROP), 1);
+	PUSH_DATA (push, 0xca); /* DPSDxax in the GDI speech. */
+
+	/* Image pattern. */
+	ret = nouveau_object_new(chan, handle++, NV04_PATTERN_CLASS,
+				 NULL, 0, &hw->patt);
+	if (ret)
+		goto fail;
+
+	BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
+	PUSH_DATA (push, hw->patt->handle);
+	BEGIN_NV04(push, NV01_PATT(DMA_NOTIFY), 1);
+	PUSH_DATA (push, hw->ntfy->handle);
+
+	BEGIN_NV04(push, NV01_PATT(MONOCHROME_FORMAT), 3);
+	PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
+	PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
+	PUSH_DATA (push, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
+
+	BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR0), 4);
+	PUSH_DATA (push, 0);
+	PUSH_DATA (push, 0);
+	PUSH_DATA (push, ~0);
+	PUSH_DATA (push, ~0);
+
+	/* GDI rectangle text. */
+	ret = nouveau_object_new(chan, handle++, NV04_GDI_CLASS,
+				 NULL, 0, &hw->rect);
+	if (ret)
+		goto fail;
+
+	BEGIN_NV04(push, NV01_SUBC(GDI, OBJECT), 1);
+	PUSH_DATA (push, hw->rect->handle);
+	BEGIN_NV04(push, NV04_GDI(DMA_NOTIFY), 1);
+	PUSH_DATA (push, hw->ntfy->handle);
+	BEGIN_NV04(push, NV04_GDI(SURFACE), 1);
+	PUSH_DATA (push, hw->surf2d->handle);
+	BEGIN_NV04(push, NV04_GDI(ROP), 1);
+	PUSH_DATA (push, hw->rop->handle);
+	BEGIN_NV04(push, NV04_GDI(PATTERN), 1);
+	PUSH_DATA (push, hw->patt->handle);
+
+	BEGIN_NV04(push, NV04_GDI(OPERATION), 1);
+	PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
+	BEGIN_NV04(push, NV04_GDI(MONOCHROME_FORMAT), 1);
+	PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
+
+	/* Swizzled surface. */
+	if (context_chipset(ctx) < 0x20)
+		class = NV04_SURFACE_SWZ_CLASS;
+	else if (context_chipset (ctx) < 0x30)
+		class = NV20_SURFACE_SWZ_CLASS;
+	else
+		class = NV30_SURFACE_SWZ_CLASS;
+
+	ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->swzsurf);
+	if (ret)
+		goto fail;
+
+	BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
+	PUSH_DATA (push, hw->swzsurf->handle);
+
+	/* Scaled image from memory. */
+	if  (context_chipset(ctx) < 0x10)
+		class = NV04_SIFM_CLASS;
+	else
+		class = NV10_SIFM_CLASS;
+
+	ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->sifm);
+	if (ret)
+		goto fail;
+
+	BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1);
+	PUSH_DATA (push, hw->sifm->handle);
+
+	if (context_chipset(ctx) >= 0x10) {
+		BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1);
+		PUSH_DATA (push, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+	}
+
+	return GL_TRUE;
+
+fail:
+	nv04_surface_takedown(ctx);
+	return GL_FALSE;
+}
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_surface.h b/src/mesa/drivers/dri/nouveau/nouveau_surface.h
index 3e80206..0a6fcb0 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_surface.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_surface.h
@@ -55,4 +55,21 @@ void
 nouveau_surface_ref(struct nouveau_surface *src,
 		    struct nouveau_surface *dst);
 
+GLboolean
+nv04_surface_init(struct gl_context *ctx);
+
+void
+nv04_surface_takedown(struct gl_context *ctx);
+
+void
+nv04_surface_copy(struct gl_context *ctx,
+		  struct nouveau_surface *dst, struct nouveau_surface *src,
+		  int dx, int dy, int sx, int sy, int w, int h);
+
+void
+nv04_surface_fill(struct gl_context *ctx,
+		  struct nouveau_surface *dst,
+		  unsigned mask, unsigned value,
+		  int dx, int dy, int w, int h);
+
 #endif
diff --git a/src/mesa/drivers/dri/nouveau/nv04_driver.h b/src/mesa/drivers/dri/nouveau/nv04_driver.h
index 554914d..1648e92 100644
--- a/src/mesa/drivers/dri/nouveau/nv04_driver.h
+++ b/src/mesa/drivers/dri/nouveau/nv04_driver.h
@@ -44,24 +44,6 @@ nv04_render_init(struct gl_context *ctx);
 void
 nv04_render_destroy(struct gl_context *ctx);
 
-/* nv04_surface.c */
-GLboolean
-nv04_surface_init(struct gl_context *ctx);
-
-void
-nv04_surface_takedown(struct gl_context *ctx);
-
-void
-nv04_surface_copy(struct gl_context *ctx,
-		  struct nouveau_surface *dst, struct nouveau_surface *src,
-		  int dx, int dy, int sx, int sy, int w, int h);
-
-void
-nv04_surface_fill(struct gl_context *ctx,
-		  struct nouveau_surface *dst,
-		  unsigned mask, unsigned value,
-		  int dx, int dy, int w, int h);
-
 /* nv04_state_fb.c */
 void
 nv04_emit_framebuffer(struct gl_context *ctx, int emit);
diff --git a/src/mesa/drivers/dri/nouveau/nv04_surface.c b/src/mesa/drivers/dri/nouveau/nv04_surface.c
deleted file mode 100644
index b1f0ea0..0000000
--- a/src/mesa/drivers/dri/nouveau/nv04_surface.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Copyright (C) 2007-2010 The Nouveau Project.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "nouveau_driver.h"
-#include "nv_object.xml.h"
-#include "nv_m2mf.xml.h"
-#include "nv01_2d.xml.h"
-#include "nv04_3d.xml.h"
-#include "nouveau_context.h"
-#include "nouveau_util.h"
-#include "nv04_driver.h"
-
-static inline int
-swzsurf_format(mesa_format format)
-{
-	switch (format) {
-	case MESA_FORMAT_A_UNORM8:
-	case MESA_FORMAT_L_UNORM8:
-	case MESA_FORMAT_I_UNORM8:
-	case MESA_FORMAT_B2G3R3_UNORM:
-		return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8;
-
-	case MESA_FORMAT_B5G6R5_UNORM:
-	case MESA_FORMAT_R5G6B5_UNORM:
-	case MESA_FORMAT_B4G4R4A4_UNORM:
-	case MESA_FORMAT_A4R4G4B4_UNORM:
-	case MESA_FORMAT_B5G5R5A1_UNORM:
-	case MESA_FORMAT_A1B5G5R5_UNORM:
-	case MESA_FORMAT_A1R5G5B5_UNORM:
-	case MESA_FORMAT_L8A8_UNORM:
-	case MESA_FORMAT_A8L8_UNORM:
-	case MESA_FORMAT_YCBCR:
-	case MESA_FORMAT_YCBCR_REV:
-	case MESA_FORMAT_Z_UNORM16:
-		return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5;
-
-	case MESA_FORMAT_A8B8G8R8_UNORM:
-	case MESA_FORMAT_R8G8B8A8_UNORM:
-	case MESA_FORMAT_B8G8R8X8_UNORM:
-	case MESA_FORMAT_B8G8R8A8_UNORM:
-	case MESA_FORMAT_A8R8G8B8_UNORM:
-	case MESA_FORMAT_Z24_UNORM_S8_UINT:
-	case MESA_FORMAT_S8_UINT_Z24_UNORM:
-	case MESA_FORMAT_Z_UNORM32:
-		return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8;
-
-	default:
-		assert(0);
-	}
-}
-
-static inline int
-surf2d_format(mesa_format format)
-{
-	switch (format) {
-	case MESA_FORMAT_A_UNORM8:
-	case MESA_FORMAT_L_UNORM8:
-	case MESA_FORMAT_I_UNORM8:
-	case MESA_FORMAT_B2G3R3_UNORM:
-		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
-
-	case MESA_FORMAT_B5G6R5_UNORM:
-	case MESA_FORMAT_R5G6B5_UNORM:
-	case MESA_FORMAT_B4G4R4A4_UNORM:
-	case MESA_FORMAT_A4R4G4B4_UNORM:
-	case MESA_FORMAT_B5G5R5A1_UNORM:
-	case MESA_FORMAT_A1B5G5R5_UNORM:
-	case MESA_FORMAT_A1R5G5B5_UNORM:
-	case MESA_FORMAT_L8A8_UNORM:
-	case MESA_FORMAT_A8L8_UNORM:
-	case MESA_FORMAT_YCBCR:
-	case MESA_FORMAT_YCBCR_REV:
-	case MESA_FORMAT_Z_UNORM16:
-		return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
-
-	case MESA_FORMAT_A8B8G8R8_UNORM:
-	case MESA_FORMAT_R8G8B8A8_UNORM:
-	case MESA_FORMAT_B8G8R8X8_UNORM:
-	case MESA_FORMAT_B8G8R8A8_UNORM:
-	case MESA_FORMAT_A8R8G8B8_UNORM:
-	case MESA_FORMAT_Z24_UNORM_S8_UINT:
-	case MESA_FORMAT_S8_UINT_Z24_UNORM:
-	case MESA_FORMAT_Z_UNORM32:
-		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
-
-	default:
-		assert(0);
-	}
-}
-
-static inline int
-rect_format(mesa_format format)
-{
-	switch (format) {
-	case MESA_FORMAT_A_UNORM8:
-	case MESA_FORMAT_L_UNORM8:
-	case MESA_FORMAT_I_UNORM8:
-	case MESA_FORMAT_B2G3R3_UNORM:
-		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
-
-	case MESA_FORMAT_B5G6R5_UNORM:
-	case MESA_FORMAT_R5G6B5_UNORM:
-	case MESA_FORMAT_B4G4R4A4_UNORM:
-	case MESA_FORMAT_A4R4G4B4_UNORM:
-	case MESA_FORMAT_B5G5R5A1_UNORM:
-	case MESA_FORMAT_A1B5G5R5_UNORM:
-	case MESA_FORMAT_A1R5G5B5_UNORM:
-	case MESA_FORMAT_L8A8_UNORM:
-	case MESA_FORMAT_A8L8_UNORM:
-	case MESA_FORMAT_YCBCR:
-	case MESA_FORMAT_YCBCR_REV:
-	case MESA_FORMAT_Z_UNORM16:
-		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
-
-	case MESA_FORMAT_A8B8G8R8_UNORM:
-	case MESA_FORMAT_R8G8B8A8_UNORM:
-	case MESA_FORMAT_B8G8R8X8_UNORM:
-	case MESA_FORMAT_B8G8R8A8_UNORM:
-	case MESA_FORMAT_A8R8G8B8_UNORM:
-	case MESA_FORMAT_Z24_UNORM_S8_UINT:
-	case MESA_FORMAT_S8_UINT_Z24_UNORM:
-	case MESA_FORMAT_Z_UNORM32:
-		return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
-
-	default:
-		assert(0);
-	}
-}
-
-static inline int
-sifm_format(mesa_format format)
-{
-	switch (format) {
-	case MESA_FORMAT_A_UNORM8:
-	case MESA_FORMAT_L_UNORM8:
-	case MESA_FORMAT_I_UNORM8:
-	case MESA_FORMAT_B2G3R3_UNORM:
-		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8;
-
-	case MESA_FORMAT_B5G6R5_UNORM:
-	case MESA_FORMAT_R5G6B5_UNORM:
-	case MESA_FORMAT_B4G4R4A4_UNORM:
-	case MESA_FORMAT_A4R4G4B4_UNORM:
-	case MESA_FORMAT_B5G5R5A1_UNORM:
-	case MESA_FORMAT_A1B5G5R5_UNORM:
-	case MESA_FORMAT_A1R5G5B5_UNORM:
-	case MESA_FORMAT_L8A8_UNORM:
-	case MESA_FORMAT_A8L8_UNORM:
-	case MESA_FORMAT_YCBCR:
-	case MESA_FORMAT_YCBCR_REV:
-	case MESA_FORMAT_Z_UNORM16:
-		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
-
-	case MESA_FORMAT_A8B8G8R8_UNORM:
-	case MESA_FORMAT_R8G8B8A8_UNORM:
-	case MESA_FORMAT_B8G8R8X8_UNORM:
-	case MESA_FORMAT_B8G8R8A8_UNORM:
-	case MESA_FORMAT_A8R8G8B8_UNORM:
-	case MESA_FORMAT_Z24_UNORM_S8_UINT:
-	case MESA_FORMAT_S8_UINT_Z24_UNORM:
-	case MESA_FORMAT_Z_UNORM32:
-		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
-
-	default:
-		assert(0);
-	}
-}
-
-static void
-nv04_surface_copy_swizzle(struct gl_context *ctx,
-			  struct nouveau_surface *dst,
-			  struct nouveau_surface *src,
-			  int dx, int dy, int sx, int sy,
-			  int w, int h)
-{
-	struct nouveau_pushbuf_refn refs[] = {
-		{ src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
-		{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
-	};
-	struct nouveau_pushbuf *push = context_push(ctx);
-	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
-	struct nouveau_object *swzsurf = hw->swzsurf;
-	struct nv04_fifo *fifo = hw->chan->data;
-	/* 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, y;
-
-        /* Swizzled surfaces must be POT  */
-	assert(_mesa_is_pow_two(dst->width) &&
-	       _mesa_is_pow_two(dst->height));
-
-	if (context_chipset(ctx) < 0x10) {
-		BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
-		PUSH_DATA (push, 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);
-
-			if (nouveau_pushbuf_space(push, 64, 4, 0) ||
-			    nouveau_pushbuf_refn (push, refs, 2))
-				return;
-
-			BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);
-			PUSH_DATA (push, fifo->vram);
-			BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);
-			PUSH_DATA (push, swzsurf_format(dst->format) |
-					 log2i(dst->width) << 16 |
-					 log2i(dst->height) << 24);
-			PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
-
-			BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
-			PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
-			BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
-			PUSH_DATA (push, swzsurf->handle);
-
-			BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);
-			PUSH_DATA (push, sifm_format(src->format));
-			PUSH_DATA (push, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
-			PUSH_DATA (push, (y + dy) << 16 | (x + dx));
-			PUSH_DATA (push, sub_h << 16 | sub_w);
-			PUSH_DATA (push, (y + dy) << 16 | (x + dx));
-			PUSH_DATA (push, sub_h << 16 | sub_w);
-			PUSH_DATA (push, 1 << 20);
-			PUSH_DATA (push, 1 << 20);
-
-			BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
-			PUSH_DATA (push, align(sub_h, 2) << 16 | align(sub_w, 2));
-			PUSH_DATA (push, src->pitch  |
-					 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
-					 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
-			PUSH_RELOC(push, src->bo, src->offset + (y + sy) * src->pitch +
-					 (x + sx) * src->cpp, NOUVEAU_BO_LOW, 0, 0);
-			PUSH_DATA (push, 0);
-		}
-	}
-
-	if (context_chipset(ctx) < 0x10) {
-		BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
-		PUSH_DATA (push, hw->surf3d->handle);
-	}
-}
-
-static void
-nv04_surface_copy_m2mf(struct gl_context *ctx,
-		       struct nouveau_surface *dst,
-		       struct nouveau_surface *src,
-		       int dx, int dy, int sx, int sy,
-		       int w, int h)
-{
-	struct nouveau_pushbuf_refn refs[] = {
-		{ src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
-		{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
-	};
-	struct nouveau_pushbuf *push = context_push(ctx);
-	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
-	struct nv04_fifo *fifo = hw->chan->data;
-	unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp;
-	unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp;
-
-	while (h) {
-		int count = (h > 2047) ? 2047 : h;
-
-		if (nouveau_pushbuf_space(push, 16, 4, 0) ||
-		    nouveau_pushbuf_refn (push, refs, 2))
-			return;
-
-		BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
-		PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
-		PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
-		BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
-		PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
-		PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
-		PUSH_DATA (push, src->pitch);
-		PUSH_DATA (push, dst->pitch);
-		PUSH_DATA (push, w * src->cpp);
-		PUSH_DATA (push, count);
-		PUSH_DATA (push, 0x0101);
-		PUSH_DATA (push, 0);
-
-		src_offset += src->pitch * count;
-		dst_offset += dst->pitch * count;
-		h -= count;
-	}
-}
-
-typedef unsigned (*get_offset_t)(struct nouveau_surface *s,
-				 unsigned x, unsigned y);
-
-static unsigned
-get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y)
-{
-	return x * s->cpp + y * s->pitch;
-}
-
-static unsigned
-get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y)
-{
-	unsigned k = log2i(MIN2(s->width, s->height));
-
-	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 s->cpp * (((u | v) & ~(~0 << 2*k)) |
-			 (x & (~0 << k)) << k |
-			 (y & (~0 << k)) << k);
-}
-
-static void
-nv04_surface_copy_cpu(struct gl_context *ctx,
-		      struct nouveau_surface *dst,
-		      struct nouveau_surface *src,
-		      int dx, int dy, int sx, int sy,
-		      int w, int h)
-{
-	int x, y;
-	get_offset_t get_dst = (dst->layout == SWIZZLED ?
-				get_swizzled_offset : get_linear_offset);
-	get_offset_t get_src = (src->layout == SWIZZLED ?
-				get_swizzled_offset : get_linear_offset);
-	void *dp, *sp;
-
-	nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, context_client(ctx));
-	nouveau_bo_map(src->bo, NOUVEAU_BO_RD, context_client(ctx));
-
-	dp = dst->bo->map + dst->offset;
-	sp = src->bo->map + src->offset;
-
-	for (y = 0; y < h; y++) {
-		for (x = 0; x < w; x++) {
-			memcpy(dp + get_dst(dst, dx + x, dy + y),
-			       sp + get_src(src, sx + x, sy + y), dst->cpp);
-		}
-	}
-}
-
-void
-nv04_surface_copy(struct gl_context *ctx,
-		  struct nouveau_surface *dst,
-		  struct nouveau_surface *src,
-		  int dx, int dy, int sx, int sy,
-		  int w, int h)
-{
-	if (_mesa_is_format_compressed(src->format)) {
-		sx = get_format_blocksx(src->format, sx);
-		sy = get_format_blocksy(src->format, sy);
-		dx = get_format_blocksx(dst->format, dx);
-		dy = get_format_blocksy(dst->format, dy);
-		w = get_format_blocksx(src->format, w);
-		h = get_format_blocksy(src->format, h);
-	}
-
-	/* Linear texture copy. */
-	if ((src->layout == LINEAR && dst->layout == LINEAR) ||
-	    dst->width <= 2 || dst->height <= 1) {
-		nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
-		return;
-	}
-
-	/* Swizzle using sifm+swzsurf. */
-        if (src->layout == LINEAR && dst->layout == SWIZZLED &&
-	    dst->cpp != 1 && !(dst->offset & 63)) {
-		nv04_surface_copy_swizzle(ctx, dst, src, dx, dy, sx, sy, w, h);
-		return;
-	}
-
-	/* Fallback to CPU copy. */
-	nv04_surface_copy_cpu(ctx, dst, src, dx, dy, sx, sy, w, h);
-}
-
-void
-nv04_surface_fill(struct gl_context *ctx,
-		  struct nouveau_surface *dst,
-		  unsigned mask, unsigned value,
-		  int dx, int dy, int w, int h)
-{
-	struct nouveau_pushbuf_refn refs[] = {
-		{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
-	};
-	struct nouveau_pushbuf *push = context_push(ctx);
-	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
-	struct nv04_fifo *fifo = hw->chan->data;
-
-	if (nouveau_pushbuf_space(push, 64, 4, 0) ||
-	    nouveau_pushbuf_refn (push, refs, 1))
-		return;
-
-	BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);
-	PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
-	PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
-	BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
-	PUSH_DATA (push, surf2d_format(dst->format));
-	PUSH_DATA (push, (dst->pitch << 16) | dst->pitch);
-	PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
-	PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
-
-	BEGIN_NV04(push, NV01_PATT(COLOR_FORMAT), 1);
-	PUSH_DATA (push, rect_format(dst->format));
-	BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR1), 1);
-	PUSH_DATA (push, mask | ~0ll << (8 * dst->cpp));
-
-	BEGIN_NV04(push, NV04_GDI(COLOR_FORMAT), 1);
-	PUSH_DATA (push, rect_format(dst->format));
-	BEGIN_NV04(push, NV04_GDI(COLOR1_A), 1);
-	PUSH_DATA (push, value);
-	BEGIN_NV04(push, NV04_GDI(UNCLIPPED_RECTANGLE_POINT(0)), 2);
-	PUSH_DATA (push, (dx << 16) | dy);
-	PUSH_DATA (push, ( w << 16) |  h);
-}
-
-void
-nv04_surface_takedown(struct gl_context *ctx)
-{
-	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
-
-	nouveau_object_del(&hw->swzsurf);
-	nouveau_object_del(&hw->sifm);
-	nouveau_object_del(&hw->rect);
-	nouveau_object_del(&hw->rop);
-	nouveau_object_del(&hw->patt);
-	nouveau_object_del(&hw->surf2d);
-	nouveau_object_del(&hw->m2mf);
-	nouveau_object_del(&hw->ntfy);
-}
-
-GLboolean
-nv04_surface_init(struct gl_context *ctx)
-{
-	struct nouveau_pushbuf *push = context_push(ctx);
-	struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
-	struct nouveau_object *chan = hw->chan;
-	unsigned handle = 0x88000000, class;
-	int ret;
-
-	/* Notifier object. */
-	ret = nouveau_object_new(chan, handle++, NOUVEAU_NOTIFIER_CLASS,
-				 &(struct nv04_notify) {
-					.length = 32,
-				 }, sizeof(struct nv04_notify), &hw->ntfy);
-	if (ret)
-		goto fail;
-
-	/* Memory to memory format. */
-	ret = nouveau_object_new(chan, handle++, NV03_M2MF_CLASS,
-				 NULL, 0, &hw->m2mf);
-	if (ret)
-		goto fail;
-
-	BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
-	PUSH_DATA (push, hw->m2mf->handle);
-	BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
-	PUSH_DATA (push, hw->ntfy->handle);
-
-	/* Context surfaces 2D. */
-	if (context_chipset(ctx) < 0x10)
-		class = NV04_SURFACE_2D_CLASS;
-	else
-		class = NV10_SURFACE_2D_CLASS;
-
-	ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->surf2d);
-	if (ret)
-		goto fail;
-
-	BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1);
-	PUSH_DATA (push, hw->surf2d->handle);
-
-	/* Raster op. */
-	ret = nouveau_object_new(chan, handle++, NV03_ROP_CLASS,
-				 NULL, 0, &hw->rop);
-	if (ret)
-		goto fail;
-
-	BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
-	PUSH_DATA (push, hw->rop->handle);
-	BEGIN_NV04(push, NV01_ROP(DMA_NOTIFY), 1);
-	PUSH_DATA (push, hw->ntfy->handle);
-
-	BEGIN_NV04(push, NV01_ROP(ROP), 1);
-	PUSH_DATA (push, 0xca); /* DPSDxax in the GDI speech. */
-
-	/* Image pattern. */
-	ret = nouveau_object_new(chan, handle++, NV04_PATTERN_CLASS,
-				 NULL, 0, &hw->patt);
-	if (ret)
-		goto fail;
-
-	BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
-	PUSH_DATA (push, hw->patt->handle);
-	BEGIN_NV04(push, NV01_PATT(DMA_NOTIFY), 1);
-	PUSH_DATA (push, hw->ntfy->handle);
-
-	BEGIN_NV04(push, NV01_PATT(MONOCHROME_FORMAT), 3);
-	PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
-	PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
-	PUSH_DATA (push, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
-
-	BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR0), 4);
-	PUSH_DATA (push, 0);
-	PUSH_DATA (push, 0);
-	PUSH_DATA (push, ~0);
-	PUSH_DATA (push, ~0);
-
-	/* GDI rectangle text. */
-	ret = nouveau_object_new(chan, handle++, NV04_GDI_CLASS,
-				 NULL, 0, &hw->rect);
-	if (ret)
-		goto fail;
-
-	BEGIN_NV04(push, NV01_SUBC(GDI, OBJECT), 1);
-	PUSH_DATA (push, hw->rect->handle);
-	BEGIN_NV04(push, NV04_GDI(DMA_NOTIFY), 1);
-	PUSH_DATA (push, hw->ntfy->handle);
-	BEGIN_NV04(push, NV04_GDI(SURFACE), 1);
-	PUSH_DATA (push, hw->surf2d->handle);
-	BEGIN_NV04(push, NV04_GDI(ROP), 1);
-	PUSH_DATA (push, hw->rop->handle);
-	BEGIN_NV04(push, NV04_GDI(PATTERN), 1);
-	PUSH_DATA (push, hw->patt->handle);
-
-	BEGIN_NV04(push, NV04_GDI(OPERATION), 1);
-	PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
-	BEGIN_NV04(push, NV04_GDI(MONOCHROME_FORMAT), 1);
-	PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
-
-	/* Swizzled surface. */
-	if (context_chipset(ctx) < 0x20)
-		class = NV04_SURFACE_SWZ_CLASS;
-	else if (context_chipset (ctx) < 0x30)
-		class = NV20_SURFACE_SWZ_CLASS;
-	else
-		class = NV30_SURFACE_SWZ_CLASS;
-
-	ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->swzsurf);
-	if (ret)
-		goto fail;
-
-	BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
-	PUSH_DATA (push, hw->swzsurf->handle);
-
-	/* Scaled image from memory. */
-	if  (context_chipset(ctx) < 0x10)
-		class = NV04_SIFM_CLASS;
-	else
-		class = NV10_SIFM_CLASS;
-
-	ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->sifm);
-	if (ret)
-		goto fail;
-
-	BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1);
-	PUSH_DATA (push, hw->sifm->handle);
-
-	if (context_chipset(ctx) >= 0x10) {
-		BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1);
-		PUSH_DATA (push, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
-	}
-
-	return GL_TRUE;
-
-fail:
-	nv04_surface_takedown(ctx);
-	return GL_FALSE;
-}
-- 
2.7.4



More information about the mesa-dev mailing list