[Nouveau] [PATCHv2] nv10/exa: Spring-cleaning

Francisco Jerez currojerez at riseup.net
Wed Nov 4 18:35:11 PST 2009


* Kill the A8+A8 hack. Recent enough X servers (>=1.7) fall back to
  ARGB glyphs for drivers not supporting A8 render targets.

* Kill all the global state. It doesn't matter a lot yet but it might
  if we get multicard working at some point.

* Other random clean-ups with no functional changes.

Some numbers from x11perf -aa10text -aa24text -comppixwin10 -comppixwin500:

* Before, with A glyphs:
   12000000 trep @   0.0025 msec (394000.0/sec): Char in 80-char aa line (Charter 10)
    3200000 trep @   0.0119 msec ( 84300.0/sec): Char in 30-char aa line (Charter 24)
    8000000 trep @   0.0036 msec (280000.0/sec): Composite 10x10 from pixmap to window
      60000 trep @   0.4813 msec (  2080.0/sec): Composite 500x500 from pixmap to window

* After, ARGB glyphs:
   20000000 trep @   0.0015 msec (649000.0/sec): Char in 80-char aa line (Charter 10)
    4800000 trep @   0.0057 msec (175000.0/sec): Char in 30-char aa line (Charter 24)
    8000000 trep @   0.0036 msec (280000.0/sec): Composite 10x10 from pixmap to window
      60000 trep @   0.4813 msec (  2080.0/sec): Composite 500x500 from pixmap to window

Signed-off-by: Francisco Jerez <currojerez at riseup.net>
---
 src/nv10_exa.c |  921 ++++++++++++++++++++++----------------------------------
 1 files changed, 361 insertions(+), 560 deletions(-)

diff --git a/src/nv10_exa.c b/src/nv10_exa.c
index fe86fd7..70f2fbc 100644
--- a/src/nv10_exa.c
+++ b/src/nv10_exa.c
@@ -2,6 +2,7 @@
  * Copyright 2007 Stephane Marchesin
  * Copyright 2007 Arthur Huillet
  * Copyright 2007 Peter Winters
+ * Copyright 2009 Francisco Jerez
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,24 +29,83 @@
 
 #include "nv_include.h"
 
-typedef struct nv10_exa_state {
-	Bool have_mask;
-	Bool is_a8_plus_a8;
-	struct {
-		PictTransformPtr transform;
-		float width;
-		float height;
-	} unit[2];
-} nv10_exa_state_t;
-static nv10_exa_state_t state;
+/* Texture/Render target formats. */
+static struct pict_format {
+	int exa;
+	int hw;
+} nv10_tex_format_pot[] = {
+	{ PICT_a8,       0x80  },
+	{ PICT_r5g6b5,	 0x280 },
+	{ PICT_x8r8g8b8, 0x300 },
+	{ PICT_a8r8g8b8, 0x300 },
+	{},
+
+}, nv10_tex_format_rect[] = {
+	{ PICT_a8,       0x980 },
+	{ PICT_r5g6b5,   0x880 },
+	{ PICT_x8r8g8b8, 0x900 },
+	{ PICT_a8r8g8b8, 0x900 },
+	{},
+
+}, nv20_tex_format_rect[] = {
+	{ PICT_a8,	 0xd80 },
+	{ PICT_r5g6b5,   0x880 },
+	{ PICT_x8r8g8b8, 0x900 },
+	{ PICT_a8r8g8b8, 0x900 },
+	{},
+
+}, nv10_rt_format[] = {
+	{ PICT_r5g6b5,	 0x103 },
+	{ PICT_x8r8g8b8, 0x108 },
+	{ PICT_a8r8g8b8, 0x108 },
+	{},
+};
+
+static int
+get_tex_format(PicturePtr pict)
+{
+	ScrnInfoPtr pScrn = xf86Screens[pict->pDrawable->pScreen->myNum];
+	NVPtr pNv = NVPTR(pScrn);
+
+	/* If repeat is set we're always handling a 1x1 texture with
+	 * ARGB/XRGB destination, in that case we change the format to
+	 * use the POT (swizzled) matching format.
+	 */
+	struct pict_format *format =
+		pict->repeat != RepeatNone ? nv10_tex_format_pot :
+		pNv->Architecture == NV_ARCH_20 ? nv20_tex_format_rect :
+		nv10_tex_format_rect;
+
+	for (; format->hw; format++) {
+		if (format->exa == pict->format)
+			return format->hw;
+	}
+
+	return 0;
+}
+
+static int
+get_rt_format(PicturePtr pict)
+{
+	struct pict_format *format = nv10_rt_format;
+
+	for (; format->hw; format++) {
+		if (format->exa == pict->format)
+			return format->hw;
+	}
+
+	return 0;
+}
 
+/* Blending functions. */
 #define SF(x) NV10TCL_BLEND_FUNC_SRC_##x
 #define DF(x) NV10TCL_BLEND_FUNC_DST_##x
 
-static struct nv10_pictop {
+static struct pict_op {
 	int src;
 	int dst;
-} NV10PictOp [] = {
+
+} nv10_pict_op[] = {
 	{ SF(ZERO),		   DF(ZERO) },		      /* Clear */
 	{ SF(ONE),		   DF(ZERO) },		      /* Src */
 	{ SF(ZERO),		   DF(ONE) },		      /* Dst */
@@ -61,131 +121,91 @@ static struct nv10_pictop {
 	{ SF(ONE),		   DF(ONE) },		      /* Add */
 };
 
-static inline bool needs_src_alpha(int op)
+static inline Bool
+needs_src_alpha(int op)
 {
-	return NV10PictOp[op].dst == DF(ONE_MINUS_SRC_ALPHA)
-		|| NV10PictOp[op].dst == DF(SRC_ALPHA);
+	return nv10_pict_op[op].dst == DF(ONE_MINUS_SRC_ALPHA)
+		|| nv10_pict_op[op].dst == DF(SRC_ALPHA);
 }
 
-static inline bool needs_src(int op)
+static inline Bool
+needs_src(int op)
 {
-	return NV10PictOp[op].src != DF(ZERO);
+	return nv10_pict_op[op].src != DF(ZERO);
 }
 
-static inline bool effective_component_alpha(PicturePtr mask)
+static inline Bool
+effective_component_alpha(PicturePtr mask)
 {
 	return mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format);
 }
 
-static int NV10TexFormat(int ExaFormat)
-{
-	struct {int exa;int hw;} tex_format[] =
-	{
-		{PICT_a8r8g8b8,	0x900},
-		{PICT_x8r8g8b8,	0x900},
-		{PICT_r5g6b5, 0x880}, /*this one was only tested with rendercheck*/
-		/*{PICT_a1r5g5b5,	NV10TCL_TX_FORMAT_FORMAT_R5G5B5A1},
-		{PICT_a4r4g4b4,	NV10TCL_TX_FORMAT_FORMAT_R4G4B4A4},*/
-		{PICT_a8,	0x980}, /*this is a NV1x only format, corresponding NV2x is 0xD80, we hack it in below*/
-	};
-
-	int i;
-	for (i = 0; i < sizeof(tex_format) / sizeof(tex_format[0]); i++) {
-		if (tex_format[i].exa == ExaFormat)
-			return tex_format[i].hw;
-	}
-
-	return 0;
-}
-
-static int NV10DstFormat(int ExaFormat)
-{
-	struct {int exa;int hw;} dst_format[] =
-	{
-		{PICT_a8r8g8b8,	0x108},
-		{PICT_x8r8g8b8, 0x108},
-		{PICT_r5g6b5,	0x103}
-	};
-
-	int i;
-	for (i = 0; i < sizeof(dst_format) / sizeof(dst_format[0]); i++) {
-		if (dst_format[i].exa == ExaFormat)
-			return dst_format[i].hw;
-	}
-
-	return 0;
-}
-
-static Bool NV10CheckTexture(PicturePtr Picture)
+static Bool
+check_texture(PicturePtr pict)
 {
 	int w, h;
 
-	if (!Picture->pDrawable)
+	if (!pict->pDrawable)
 		NOUVEAU_FALLBACK("Solid and gradient pictures unsupported\n");
 
-	w = Picture->pDrawable->width;
-	h = Picture->pDrawable->height;
+	w = pict->pDrawable->width;
+	h = pict->pDrawable->height;
 
-	if ((w > 2046) || (h > 2046))
+	if (w > 2046 || h > 2046)
 		NOUVEAU_FALLBACK("picture too large, %dx%d\n", w, h);
 
-	if (!NV10TexFormat(Picture->format))
+	if (!get_tex_format(pict))
 		return FALSE;
-	if (Picture->filter != PictFilterNearest && Picture->filter != PictFilterBilinear)
+
+	if (pict->filter != PictFilterNearest &&
+	    pict->filter != PictFilterBilinear)
 		return FALSE;
-	/* we cannot repeat on NV10 because NPOT textures do not support this. unfortunately. */
-	if (Picture->repeat != RepeatNone)
+
+	/* We cannot repeat on NV10 because NPOT textures do not
+	 * support this. unfortunately. */
+	if (pict->repeat != RepeatNone)
 		/* we can repeat 1x1 textures */
 		if (!(w == 1 && h == 1))
 			return FALSE;
+
 	return TRUE;
 }
 
-static Bool NV10CheckBuffer(PicturePtr Picture)
+static Bool
+check_render_target(PicturePtr pict)
 {
-	int w = Picture->pDrawable->width;
-	int h = Picture->pDrawable->height;
+	int w = pict->pDrawable->width;
+	int h = pict->pDrawable->height;
 
-	if ((w > 4096) || (h > 4096))
-		return FALSE;
-	if (!NV10DstFormat(Picture->format))
+	if (w > 4096 || h > 4096)
 		return FALSE;
-	return TRUE;
-}
 
-static Bool NV10CheckPictOp(int op)
-{
-	if (op >= PictOpSaturate) {
-		/*we do no saturate, disjoint, conjoint, though we could do e.g. DisjointClear which really is Clear */
+	if (!get_rt_format(pict))
 		return FALSE;
-	}
+
 	return TRUE;
 }
 
-/* Check if the current operation is a doable A8 + A8 */
-/* A8 destination is a special case, because we do it by having the card think 
-it's ARGB. For now we support PictOpAdd which is the only important op for this dst format, 
-and without transformation or funny things.*/
-static Bool NV10Check_A8plusA8_Feasability(PicturePtr src, PicturePtr msk, PicturePtr dst, int op)
+static Bool
+check_pict_op(int op)
 {
-#if X_BYTE_ORDER == X_BIG_ENDIAN
-	return FALSE;
-#endif
-	if ((!msk) && (src->format == PICT_a8) && (dst->format == PICT_a8) && (!src->transform) &&
-	    (op == PictOpAdd) && (src->repeat == RepeatNone)) {
-		return TRUE;
-	}
-	return FALSE;
+	/* We do no saturate, disjoint, conjoint, though we
+	 * could do e.g. DisjointClear which really is
+	 * Clear. */
+	return op < PictOpSaturate;
 }
 
 #if 0
-static void NV10EXAFallbackInfo(char *reason, int op, PicturePtr pSrcPicture,
-				PicturePtr pMaskPicture, PicturePtr pDstPicture)
+static void
+print_fallback_info(char *reason, int op, PicturePtr src, PicturePtr mask,
+		    PicturePtr dst)
 {
 	char out2[4096];
 	char *out = out2;
+
 	sprintf(out, "%s  ", reason);
-	out = out + strlen(out);
+	out += strlen(out);
+
 	switch (op) {
 	case PictOpClear:
 		sprintf(out, "PictOpClear ");
@@ -208,8 +228,9 @@ static void NV10EXAFallbackInfo(char *reason, int op, PicturePtr pSrcPicture,
 	default:
 		sprintf(out, "PictOp%d ", op);
 	}
-	out = out + strlen(out);
-	switch (pSrcPicture->format) {
+	out += strlen(out);
+
+	switch (src->format) {
 	case PICT_a8r8g8b8:
 		sprintf(out, "A8R8G8B8 ");
 		break;
@@ -229,16 +250,18 @@ static void NV10EXAFallbackInfo(char *reason, int op, PicturePtr pSrcPicture,
 		sprintf(out, "A1 ");
 		break;
 	default:
-		sprintf(out, "%x ", pSrcPicture->format);
+		sprintf(out, "%x ", src->format);
 	}
 	out += strlen(out);
-	sprintf(out, "(%dx%d) ", pSrcPicture->pDrawable->width, pSrcPicture->pDrawable->height);
-	if (pSrcPicture->repeat != RepeatNone)
+
+	sprintf(out, "(%dx%d) ", src->pDrawable->width,
+		src->pDrawable->height);
+	if (src->repeat != RepeatNone)
 		strcat(out, "R ");
 	strcat(out, "-> ");
 	out += strlen(out);
 
-	switch (pDstPicture->format) {
+	switch (dst->format) {
 	case PICT_a8r8g8b8:
 		sprintf(out, "A8R8G8B8 ");
 		break;
@@ -258,17 +281,20 @@ static void NV10EXAFallbackInfo(char *reason, int op, PicturePtr pSrcPicture,
 		sprintf(out, "A1  ");
 		break;
 	default:
-		sprintf(out, "%x  ", pDstPicture->format);
+		sprintf(out, "%x  ", dst->format);
 	}
 	out += strlen(out);
-	sprintf(out, "(%dx%d) ", pDstPicture->pDrawable->width, pDstPicture->pDrawable->height);
-	if (pDstPicture->repeat != RepeatNone)
+
+	sprintf(out, "(%dx%d) ", dst->pDrawable->width,
+		dst->pDrawable->height);
+	if (dst->repeat != RepeatNone)
 		strcat(out, "R ");
 	out += strlen(out);
-	if (!pMaskPicture)
+
+	if (!mask)
 		sprintf(out, "& NONE");
 	else {
-		switch (pMaskPicture->format) {
+		switch (mask->format) {
 		case PICT_a8r8g8b8:
 			sprintf(out, "& A8R8G8B8 ");
 			break;
@@ -285,116 +311,98 @@ static void NV10EXAFallbackInfo(char *reason, int op, PicturePtr pSrcPicture,
 			sprintf(out, "& A1  ");
 			break;
 		default:
-			sprintf(out, "& %x  ", pMaskPicture->format);
+			sprintf(out, "& %x  ", mask->format);
 		}
 		out += strlen(out);
-		sprintf(out, "(%dx%d) ", pMaskPicture->pDrawable->width, pMaskPicture->pDrawable->height);
-		if (pMaskPicture->repeat != RepeatNone)
+
+		sprintf(out, "(%dx%d) ", mask->pDrawable->width,
+			mask->pDrawable->height);
+		if (mask->repeat != RepeatNone)
 			strcat(out, "R ");
-		if (pMaskPicture->componentAlpha)
+		if (mask->componentAlpha)
 			strcat(out, "C ");
 		out += strlen(out);
 	}
 	strcat(out, "\n");
+
 	xf86DrvMsg(0, X_INFO, "%s", out2);
 }
 #else
-#define NV10EXAFallbackInfo(X,Y,Z,S,T) do { ; } while (0)
+#define print_fallback_info(...)
 #endif
 
-Bool NV10EXACheckComposite(int op,
-			PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture,
-			PicturePtr pDstPicture)
+Bool
+NV10EXACheckComposite(int op, PicturePtr src, PicturePtr mask, PicturePtr dst)
 {
-
-	if (NV10Check_A8plusA8_Feasability(pSrcPicture, pMaskPicture, pDstPicture, op)) {
-		NV10EXAFallbackInfo("Hackelerating", op, pSrcPicture, pMaskPicture, pDstPicture);
-		return TRUE;
-	}
-
-	if (!NV10CheckPictOp(op)) {
-		NV10EXAFallbackInfo("pictop", op, pSrcPicture, pMaskPicture, pDstPicture);
+	if (!check_pict_op(op)) {
+		print_fallback_info("pictop", op, src, mask, dst);
 		return FALSE;
 	}
-	if (!NV10CheckBuffer(pDstPicture)) {
-		NV10EXAFallbackInfo("dst", op, pSrcPicture, pMaskPicture, pDstPicture);
+
+	if (!check_render_target(dst)) {
+		print_fallback_info("dst", op, src, mask, dst);
 		return FALSE;
 	}
 
-	if (!NV10CheckTexture(pSrcPicture)) {
-		NV10EXAFallbackInfo("src", op, pSrcPicture, pMaskPicture, pDstPicture);
+	if (!check_texture(src)) {
+		print_fallback_info("src", op, src, mask, dst);
 		return FALSE;
 	}
 
-	if (pMaskPicture) {
-		if (!NV10CheckTexture(pMaskPicture)) {
-			NV10EXAFallbackInfo("mask", op, pSrcPicture,
-					    pMaskPicture, pDstPicture);
+	if (mask) {
+		if (!check_texture(mask)) {
+			print_fallback_info("mask", op, src,
+					    mask, dst);
 			return FALSE;
 		}
 
-		if (effective_component_alpha(pMaskPicture) &&
+		if (effective_component_alpha(mask) &&
 		    needs_src(op) && needs_src_alpha(op)) {
-			NV10EXAFallbackInfo("ca-mask", op, pSrcPicture,
-					    pMaskPicture, pDstPicture);
+			print_fallback_info("ca-mask", op, src,
+					    mask, dst);
 			return FALSE;
 		}
 	}
 
-	NV10EXAFallbackInfo("Accelerating", op, pSrcPicture, pMaskPicture, pDstPicture);
+	print_fallback_info("Accelerating", op, src, mask, dst);
 	return TRUE;
 }
 
-static Bool NV10SetTexture(NVPtr pNv, int unit, PicturePtr Pict, PixmapPtr pixmap)
+static Bool
+setup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap)
 {
 	struct nouveau_channel *chan = pNv->chan;
 	struct nouveau_grobj *celsius = pNv->Nv3D;
 	struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);
 	unsigned delta = nouveau_pixmap_offset(pixmap);
-	int log2w = log2i(Pict->pDrawable->width);
-	int log2h = log2i(Pict->pDrawable->height);
-	int w;
+	long w = pict->pDrawable->width,
+	     h = pict->pDrawable->height;
 	unsigned int txfmt =
-			(NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE) |
-			(NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE) |
-			(log2w<<20) |
-			(log2h<<16) |
-			(1<<12) | /* lod == 1 */
-			0x51 /* UNK */;
+		NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE |
+		NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE |
+		log2i(w) << 20 | log2i(h) << 16 |
+		1 << 12 | /* lod == 1 */
+		get_tex_format(pict) |
+		0x51 /* UNK */;
 
 	BEGIN_RING(chan, celsius, NV10TCL_TX_OFFSET(unit), 1);
 	if (OUT_RELOCl(chan, bo, delta, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD))
 		return FALSE;
 
-	/* if repeat is set we're always handling a 1x1 texture with ARGB/XRGB destination, 
-	in that case we change the format	to use the POT (swizzled) matching format */
-	if (Pict->repeat != RepeatNone)
-	{
-		if (Pict->format == PICT_a8)
-			txfmt |= 0x80; /* A8 */
-		else if (Pict->format == PICT_r5g6b5 )
-			txfmt |= 0x280; /* R5G6B5 */
-		else
-			txfmt |= 0x300; /* ARGB format */
-	} else {
-		if (pNv->Architecture == NV_ARCH_20 && Pict->format == PICT_a8)
-			txfmt |= 0xd80;
-		else
-			txfmt |= NV10TexFormat(Pict->format);
-		w = Pict->pDrawable->width;
-		/* NPOT_SIZE expects an even number for width, we can round up uneven
-		* numbers here because EXA always gives 64 byte aligned pixmaps
-		* and for all formats we support 64 bytes represents an even number
-		* of pixels
-		*/
+	if (pict->repeat == RepeatNone) {
+		/* NPOT_SIZE expects an even number for width, we can
+		 * round up uneven numbers here because EXA always
+		 * gives 64 byte aligned pixmaps and for all formats
+		 * we support 64 bytes represents an even number of
+		 * pixels
+		 */
 		w = (w + 1) &~ 1;
 
 		BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_PITCH(unit), 1);
 		OUT_RING  (chan, exaGetPixmapPitch(pixmap) << 16);
 
 		BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_SIZE(unit), 1);
-		OUT_RING  (chan, (w<<16) | Pict->pDrawable->height);
+		OUT_RING  (chan, w << 16 | h);
 	}
 
 	BEGIN_RING(chan, celsius, NV10TCL_TX_FORMAT(unit), 1 );
@@ -404,218 +412,135 @@ static Bool NV10SetTexture(NVPtr pNv, int unit, PicturePtr Pict, PixmapPtr pixma
 	OUT_RING  (chan, NV10TCL_TX_ENABLE_ENABLE);
 
 	BEGIN_RING(chan, celsius, NV10TCL_TX_FILTER(unit), 1);
-	if (Pict->filter == PictFilterNearest)
-		OUT_RING  (chan, (NV10TCL_TX_FILTER_MAGNIFY_NEAREST) |
-				(NV10TCL_TX_FILTER_MINIFY_NEAREST));
+	if (pict->filter == PictFilterNearest)
+		OUT_RING(chan, (NV10TCL_TX_FILTER_MAGNIFY_NEAREST |
+				NV10TCL_TX_FILTER_MINIFY_NEAREST));
 	else
-		OUT_RING  (chan, (NV10TCL_TX_FILTER_MAGNIFY_LINEAR) |
-				(NV10TCL_TX_FILTER_MINIFY_LINEAR));
+		OUT_RING(chan, (NV10TCL_TX_FILTER_MAGNIFY_LINEAR |
+				NV10TCL_TX_FILTER_MINIFY_LINEAR));
 
-	state.unit[unit].width		= (float)pixmap->drawable.width;
-	state.unit[unit].height		= (float)pixmap->drawable.height;
-	state.unit[unit].transform	= Pict->transform;
 	return TRUE;
 }
 
-static Bool NV10SetBuffer(NVPtr pNv, PicturePtr Pict, PixmapPtr pixmap)
+static Bool
+setup_render_target(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap)
 {
 	struct nouveau_channel *chan = pNv->chan;
 	struct nouveau_grobj *celsius = pNv->Nv3D;
 	struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);
 	unsigned delta = nouveau_pixmap_offset(pixmap);
-	int i;
-	int x = 0;
-	int y = 0;
-	int w = 2048;
-	int h = 2048;
-
-	BEGIN_RING(chan, celsius, NV10TCL_RT_FORMAT, 4);
-	if (state.is_a8_plus_a8) {
-		/*A8 + A8 hack */
-		OUT_RING  (chan, NV10DstFormat(PICT_a8r8g8b8));
-	} else {
-		OUT_RING  (chan, NV10DstFormat(Pict->format));
-	}
 
-	OUT_RING  (chan, ((uint32_t)exaGetPixmapPitch(pixmap) << 16) |(uint32_t)exaGetPixmapPitch(pixmap));
+	BEGIN_RING(chan, celsius, NV10TCL_RT_FORMAT, 2);
+	OUT_RING  (chan, get_rt_format(pict));
+	OUT_RING  (chan, (exaGetPixmapPitch(pixmap) << 16 |
+			  exaGetPixmapPitch(pixmap)));
+
+	BEGIN_RING(chan, celsius, NV10TCL_COLOR_OFFSET, 1);
 	if (OUT_RELOCl(chan, bo, delta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
 		return FALSE;
-	OUT_RING  (chan, 0);
 
-	BEGIN_RING(chan, celsius, NV10TCL_RT_HORIZ, 2);
-	OUT_RING  (chan, (w<<16)|x);
-	OUT_RING  (chan, (h<<16)|y);
-	BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_MODE, 1); /* clip_mode */
-	OUT_RING  (chan, 0);
-	BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
-	OUT_RING  (chan, ((w-1+x)<<16)|x|0x08000800);
-	BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
-	OUT_RING  (chan, ((h-1+y)<<16)|y|0x08000800);
+	return TRUE;
+}
 
-	BEGIN_RING(chan, celsius, NV10TCL_PROJECTION_MATRIX(0), 16);
-	for(i=0;i<16;i++)
-		if (i/4==i%4)
-			OUT_RINGf (chan, 1.0f);
-		else
-			OUT_RINGf (chan, 0.0f);
+/*
+ * This can be a bit difficult to understand at first glance.  Reg
+ * combiners are described here:
+ * http://icps.u-strasbg.fr/~marchesin/perso/extensions/NV/register_combiners.html
+ *
+ * Single texturing setup, without honoring vertex colors (non default
+ * setup) is: Alpha RC 0 : a_0 * 1 + 0 * 0 RGB RC 0 : rgb_0 * 1 + 0 *
+ * 0 RC 1s are unused Final combiner uses default setup
+ *
+ * Default setup uses vertex rgb/alpha in place of 1s above, but we
+ * don't need that in 2D.
+ *
+ * Multi texturing setup, where we do TEX0 in TEX1 (masking) is:
+ * Alpha RC 0 : a_0 * a_1 + 0 * 0
+ * RGB RC0 : rgb_0 * a_1 + 0 * 0
+ * RC 1s are unused
+ * Final combiner uses default setup
+ */
 
-	BEGIN_RING(chan, celsius, NV10TCL_DEPTH_RANGE_NEAR, 2);
-	OUT_RING  (chan, 0);
-#if SCREEN_BPP == 32
-	OUT_RINGf (chan, 16777216.0);
-#else
-	OUT_RINGf (chan, 65536.0);
-#endif
-	BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_SCALE_X, 4);
-	OUT_RINGf (chan, -2048.0);
-	OUT_RINGf (chan, -2048.0);
-	OUT_RINGf (chan, 0);
-	OUT_RING  (chan, 0);
+/* Bind the combiner variable <input> to a constant 1. */
+#define RC_IN_ONE(input)						\
+	(NV10TCL_RC_IN_RGB_##input##_INPUT_ZERO |			\
+	 NV10TCL_RC_IN_RGB_##input##_COMPONENT_USAGE_ALPHA |		\
+	 NV10TCL_RC_IN_RGB_##input##_MAPPING_UNSIGNED_INVERT_NV)
 
-	return TRUE;
-}
+/* Bind the combiner variable <input> to the specified channel from
+ * the texture unit <unit>. */
+#define RC_IN_TEX(input, chan, unit)					\
+	(NV10TCL_RC_IN_RGB_##input##_INPUT_TEXTURE##unit##_ARB |	\
+	 NV10TCL_RC_IN_RGB_##input##_COMPONENT_USAGE_##chan)
 
-#define RC_IN_ONE(chan, input)						\
-	(NV10TCL_RC_IN_##chan##_##input##_INPUT_ZERO			\
-	 | NV10TCL_RC_IN_##chan##_##input##_COMPONENT_USAGE_##chan	\
-	 | NV10TCL_RC_IN_##chan##_##input##_MAPPING_UNSIGNED_INVERT_NV)
+/* Bind the combiner variable <input> to the specified channel from
+ * the constant color <unit>. */
+#define RC_IN_COLOR(input, chan, unit)					\
+	(NV10TCL_RC_IN_RGB_##input##_INPUT_CONSTANT_COLOR##unit##_NV | \
+	 NV10TCL_RC_IN_RGB_##input##_COMPONENT_USAGE_##chan)
 
-static void NV10SetRegCombs(NVPtr pNv, PicturePtr src, PicturePtr mask)
+static void
+setup_combiners(NVPtr pNv, PicturePtr src, PicturePtr mask)
 {
 	struct nouveau_channel *chan = pNv->chan;
 	struct nouveau_grobj *celsius = pNv->Nv3D;
-	unsigned int rc0_in_alpha = 0, rc0_in_rgb = 0;
-
-/*This can be a bit difficult to understand at first glance.
-Reg combiners are described here:
-http://icps.u-strasbg.fr/~marchesin/perso/extensions/NV/register_combiners.html
-	
-Single texturing setup, without honoring vertex colors (non default setup) is:
-Alpha RC 0 : a_0  * 1 + 0 * 0
-RGB RC 0 : rgb_0 * 1 + 0 * 0
-RC 1s are unused
-Final combiner uses default setup
-	
-Default setup uses vertex rgb/alpha in place of 1s above, but we don't need that in 2D.
-	
-Multi texturing setup, where we do TEX0 in TEX1 (masking) is:
-Alpha RC 0 : a_0 * a_1 + 0 * 0
-RGB RC0 : rgb_0 * a_1 + 0 * 0
-RC 1s are unused
-Final combiner uses default setup
-	
-*/
+	uint32_t rc_in_alpha = 0, rc_in_rgb = 0;
+
 	if (PICT_FORMAT_A(src->format))
-		rc0_in_alpha |= NV10TCL_RC_IN_ALPHA_A_INPUT_TEXTURE0_ARB
-			| NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA;
+		rc_in_alpha |= RC_IN_TEX(A, ALPHA, 0);
 	else
-		rc0_in_alpha |= RC_IN_ONE(ALPHA, A);
+		rc_in_alpha |= RC_IN_ONE(A);
 
 	if (mask && PICT_FORMAT_A(mask->format))
-		rc0_in_alpha |= NV10TCL_RC_IN_RGB_B_INPUT_TEXTURE1_ARB
-			| NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_ALPHA;
+		rc_in_alpha |= RC_IN_TEX(B, ALPHA, 1);
 	else
-		rc0_in_alpha |= RC_IN_ONE(ALPHA, B);
+		rc_in_alpha |= RC_IN_ONE(B);
 
 	if (effective_component_alpha(mask)) {
-		rc0_in_rgb |= NV10TCL_RC_IN_RGB_B_INPUT_TEXTURE1_ARB
-			| NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_RGB;
-
 		if (!needs_src_alpha(pNv->alu)) {
-			/*
-			 * The alpha channels won't be used for blending. Drop
+			/* The alpha channels won't be used for blending. Drop
 			 * them, as our pixels only have 4 components...
 			 * output_i = src_i * mask_i
 			 */
 			if (PICT_FORMAT_RGB(src->format))
-				rc0_in_rgb |= NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE0_ARB
-					| NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_RGB;
-
+				rc_in_rgb |= RC_IN_TEX(A, RGB, 0);
 		} else {
-			/*
-			 * The RGB channels won't be used for blending. Drop
+			/* The RGB channels won't be used for blending. Drop
 			 * them.
 			 * output_i = src_alpha * mask_i
 			 */
 			if (PICT_FORMAT_A(src->format))
-				rc0_in_rgb |= NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE0_ARB
-					| NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA;
+				rc_in_rgb |= RC_IN_TEX(A, ALPHA, 0);
 			else
-				rc0_in_rgb |= RC_IN_ONE(RGB, A);
+				rc_in_rgb |= RC_IN_ONE(A);
 		}
 
+		rc_in_rgb |= RC_IN_TEX(B, RGB, 1);
+
 	} else {
 		if (PICT_FORMAT_RGB(src->format))
-			rc0_in_rgb |= NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE0_ARB
-				| NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_RGB;
+			rc_in_rgb |= RC_IN_TEX(A, RGB, 0);
 
 		if (mask && PICT_FORMAT_A(mask->format))
-			rc0_in_rgb |= NV10TCL_RC_IN_RGB_B_INPUT_TEXTURE1_ARB
-				| NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_ALPHA;
+			rc_in_rgb |= RC_IN_TEX(B, ALPHA, 1);
 		else
-			rc0_in_rgb |= RC_IN_ONE(RGB, B);
+			rc_in_rgb |= RC_IN_ONE(B);
 	}
 
 	BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(0), 1);
-	OUT_RING  (chan, rc0_in_alpha);
+	OUT_RING  (chan, rc_in_alpha);
 	BEGIN_RING(chan, celsius, NV10TCL_RC_IN_RGB(0), 1);
-	OUT_RING  (chan, rc0_in_rgb);
+	OUT_RING  (chan, rc_in_rgb);
 }
 
-static void NV10SetRegCombs_A8plusA8(NVPtr pNv, int pass, int mask_out_bytes)
-{
-	struct nouveau_channel *chan = pNv->chan;
-	struct nouveau_grobj *celsius = pNv->Nv3D;
-	unsigned int rc0_in_alpha = 0, rc0_in_rgb = 0;
-	unsigned int color0 = 0, color1 = 0;
-
-	if (pass == 1) {
-		if (~mask_out_bytes & 1)
-			rc0_in_alpha |= NV10TCL_RC_IN_ALPHA_A_INPUT_TEXTURE1_ARB
-				| NV10TCL_RC_IN_ALPHA_A_COMPONENT_USAGE_ALPHA
-				| RC_IN_ONE(ALPHA, B);
-
-		if (~mask_out_bytes & 2)
-			rc0_in_rgb |= NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE0_ARB
-				| NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA
-				| NV10TCL_RC_IN_RGB_B_INPUT_CONSTANT_COLOR0_NV
-				| NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_RGB;
-
-		color0 = 0x00ff0000; /*R = 1 G = 0 B = 0*/
-	} else {
-		if (~mask_out_bytes & 8)
-			rc0_in_rgb |= NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE0_ARB
-				| NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA
-				| NV10TCL_RC_IN_RGB_B_INPUT_CONSTANT_COLOR0_NV
-				| NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_RGB;
-
-		color0 = 0x000000ff;
-
-		if (~mask_out_bytes & 4)
-			rc0_in_rgb |= NV10TCL_RC_IN_RGB_C_INPUT_TEXTURE1_ARB
-				| NV10TCL_RC_IN_RGB_C_COMPONENT_USAGE_ALPHA
-				| NV10TCL_RC_IN_RGB_D_INPUT_CONSTANT_COLOR1_NV
-				| NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE_RGB;
-
-		color1 = 0x0000ff00; /*R = 0, G = 1, B = 0*/
-	}
-
-	BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(0), 1);
-	OUT_RING  (chan, rc0_in_alpha);
-	BEGIN_RING(chan, celsius, NV10TCL_RC_IN_RGB(0), 1);
-	OUT_RING  (chan, rc0_in_rgb);
-	BEGIN_RING(chan, celsius, NV10TCL_RC_COLOR(0), 2);
-	OUT_RING  (chan, color0);
-	OUT_RING  (chan, color1);
-}
-
-static void NV10SetPictOp(NVPtr pNv, int op)
+static void
+setup_blend_function(NVPtr pNv)
 {
 	struct nouveau_channel *chan = pNv->chan;
 	struct nouveau_grobj *celsius = pNv->Nv3D;
-	struct nv10_pictop *nv10_op = &NV10PictOp[op];
-	int src_factor = nv10_op->src;
-	int dst_factor = nv10_op->dst;
+	struct pict_op *op = &nv10_pict_op[pNv->alu];
+	int src_factor = op->src;
+	int dst_factor = op->dst;
 
 	if (src_factor == SF(ONE_MINUS_DST_ALPHA) &&
 	    !PICT_FORMAT_A(pNv->pdpict->format))
@@ -649,294 +574,150 @@ NV10StateCompositeReemit(struct nouveau_channel *chan)
 				pNv->pspix, pNv->pmpix, pNv->pdpix);
 }
 
-Bool NV10EXAPrepareComposite(int op,
-			     PicturePtr pSrcPicture,
-			     PicturePtr pMaskPicture,
-			     PicturePtr pDstPicture,
-			     PixmapPtr  pSrc,
-			     PixmapPtr  pMask,
-			     PixmapPtr  pDst)
+Bool
+NV10EXAPrepareComposite(int op,
+			PicturePtr pict_src,
+			PicturePtr pict_mask,
+			PicturePtr pict_dst,
+			PixmapPtr src,
+			PixmapPtr mask,
+			PixmapPtr dst)
 {
-	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+	ScrnInfoPtr pScrn = xf86Screens[dst->drawable.pScreen->myNum];
 	NVPtr pNv = NVPTR(pScrn);
 	struct nouveau_channel *chan = pNv->chan;
 
 	if (MARK_RING(chan, 128, 3))
 		return FALSE;
 
-	state.is_a8_plus_a8 = FALSE;
-	state.have_mask=(pMaskPicture!=NULL);
-
 	pNv->alu = op;
-	pNv->pspict = pSrcPicture;
-	pNv->pmpict = pMaskPicture;
-	pNv->pdpict = pDstPicture;
-	pNv->pspix = pSrc;
-	pNv->pmpix = pMask;
-	pNv->pdpix = pDst;
-	chan->flush_notify = NV10StateCompositeReemit;
-
-	if (NV10Check_A8plusA8_Feasability(pSrcPicture, pMaskPicture, pDstPicture, op)) {
-		state.is_a8_plus_a8 = TRUE;
-		if (!NV10SetBuffer(pNv, pDstPicture, pDst) ||
-		    !NV10SetTexture(pNv, 0, pSrcPicture, pSrc) ||
-		    !NV10SetTexture(pNv, 1, pSrcPicture, pSrc)) {
-			MARK_UNDO(chan);
-			return FALSE;
-		}
-		NV10SetPictOp(pNv, op);
-		return TRUE;
-	}
+	pNv->pspict = pict_src;
+	pNv->pmpict = pict_mask;
+	pNv->pdpict = pict_dst;
+	pNv->pspix = src;
+	pNv->pmpix = mask;
+	pNv->pdpix = dst;
 
 	/* Set dst format */
-	if (!NV10SetBuffer(pNv, pDstPicture, pDst)) {
-		MARK_UNDO(chan);
-		return FALSE;
-	}
+	if (!setup_render_target(pNv, pict_dst, dst))
+		goto fail;
 
 	/* Set src format */
-	if (!NV10SetTexture(pNv, 0, pSrcPicture, pSrc)) {
-		MARK_UNDO(chan);
-		return FALSE;
-	}
+	if (!setup_texture(pNv, 0, pict_src, src))
+		goto fail;
 
 	/* Set mask format */
-	if (pMaskPicture) {
-		if (!NV10SetTexture(pNv, 1, pMaskPicture, pMask)) {
-			MARK_UNDO(chan);
-			return FALSE;
-		}
-	}
+	if (mask &&
+	    !setup_texture(pNv, 1, pict_mask, mask))
+		goto fail;
 
-	NV10SetRegCombs(pNv, pSrcPicture, pMaskPicture);
+	/* Set the register combiners up. */
+	setup_combiners(pNv, pict_src, pict_mask);
 
 	/* Set PictOp */
-	NV10SetPictOp(pNv, op);
+	setup_blend_function(pNv);
+
+	chan->flush_notify = NV10StateCompositeReemit;
 
 	return TRUE;
-}
 
-static inline void NV10Vertex(NVPtr pNv, float vx, float vy, float tx, float ty)
-{
-	struct nouveau_channel *chan = pNv->chan;
-	struct nouveau_grobj *celsius = pNv->Nv3D;
+fail:
+	MARK_UNDO(chan);
 
-	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX0_2F_S, 2);
-	OUT_RINGf (chan, tx);
-	OUT_RINGf (chan, ty);
-	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_POS_3F_X, 3);
-	OUT_RINGf (chan, vx);
-	OUT_RINGf (chan, vy);
-	OUT_RINGf (chan, 0.f);
+	return FALSE;
 }
 
-static inline void NV10MVertex(NVPtr pNv, float vx, float vy, float t0x, float t0y, float t1x, float t1y)
+#define QUAD(x, y, w, h)					\
+	{{{ IntToxFixed(x),     IntToxFixed(y),     xFixed1 }},	\
+	 {{ IntToxFixed(x + w), IntToxFixed(y),     xFixed1 }},	\
+	 {{ IntToxFixed(x + w), IntToxFixed(y + h), xFixed1 }},	\
+	 {{ IntToxFixed(x),     IntToxFixed(y + h), xFixed1 }}}
+
+#define MAP(f, p, v, ...) do {						\
+		int __i;						\
+		for (__i = 0; __i < sizeof(v)/sizeof((v)[0]); __i++)	\
+			f(p, __i, v, ## __VA_ARGS__);			\
+	} while (0);
+
+#define xFixedToFloat(v) \
+	((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
+
+#define OUT_RINGi(chan, v, i)				\
+	OUT_RINGf(chan, xFixedToFloat((v).vector[i]))
+
+static inline void
+emit_vertex(NVPtr pNv, int i, PictVector pos[],
+	    PictVector tex0[], PictVector tex1[])
 {
 	struct nouveau_channel *chan = pNv->chan;
 	struct nouveau_grobj *celsius = pNv->Nv3D;
 
 	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX0_2F_S, 2);
-	OUT_RINGf (chan, t0x);
-	OUT_RINGf (chan, t0y);
-	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX1_2F_S, 2);
-	OUT_RINGf (chan, t1x);
-	OUT_RINGf (chan, t1y);
+	OUT_RINGi (chan, tex0[i], 0);
+	OUT_RINGi (chan, tex0[i], 1);
+
+	if (tex1) {
+		BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX1_2F_S, 2);
+		OUT_RINGi (chan, tex1[i], 0);
+		OUT_RINGi (chan, tex1[i], 1);
+	}
+
 	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_POS_3F_X, 3);
-	OUT_RINGf (chan, vx);
-	OUT_RINGf (chan, vy);
-	OUT_RINGf (chan, 0.f);
+	OUT_RINGi (chan, pos[i], 0);
+	OUT_RINGi (chan, pos[i], 1);
+	OUT_RINGf (chan, 0);
 }
 
-#define xFixedToFloat(v) \
-	((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
-
-static void
-NV10EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy,
-					  float *x_ret, float *y_ret)
+static inline void
+transform_vertex(PictTransformPtr t, int i, PictVector vs[])
 {
-	PictVector v;
-
-	if (t) {
-		v.vector[0] = IntToxFixed(x);
-		v.vector[1] = IntToxFixed(y);
-		v.vector[2] = xFixed1;
-		PictureTransformPoint(t, &v);
-		*x_ret = xFixedToFloat(v.vector[0]);
-		*y_ret = xFixedToFloat(v.vector[1]);
-	} else {
-		*x_ret = (float)x;
-		*y_ret = (float)y;
-	}
+	if  (t)
+		PictureTransformPoint(t, &vs[i]);
 }
 
-
-void NV10EXAComposite(PixmapPtr pDst,
-			int	  srcX,
-			int	  srcY,
-			int	  maskX,
-			int	  maskY,
-			int	  dstX,
-			int	  dstY,
-			int	  width,
-			int	  height)
+void
+NV10EXAComposite(PixmapPtr pix_dst,
+		 int srcX, int srcY,
+		 int maskX, int maskY,
+		 int dstX, int dstY,
+		 int width, int height)
 {
-	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+	ScrnInfoPtr pScrn = xf86Screens[pix_dst->drawable.pScreen->myNum];
 	NVPtr pNv = NVPTR(pScrn);
 	struct nouveau_channel *chan = pNv->chan;
 	struct nouveau_grobj *celsius = pNv->Nv3D;
-	float sX0, sX1, sX2, sY0, sY1, sY2, sX3, sY3;
-	float mX0, mX1, mX2, mY0, mY1, mY2, mX3, mY3;
+	PicturePtr mask = pNv->pmpict,
+		src = pNv->pspict;
+	PictVector dstq[4] = QUAD(dstX, dstY, width, height),
+		maskq[4] = QUAD(maskX, maskY, width, height),
+		srcq[4] = QUAD(srcX, srcY, width, height);
+
+	MAP(transform_vertex, src->transform, srcq);
+	if (mask)
+		MAP(transform_vertex, mask->transform, maskq);
 
 	WAIT_RING (chan, 64);
 	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
 	OUT_RING  (chan, NV10TCL_VERTEX_BEGIN_END_QUADS);
 
-	NV10EXATransformCoord(state.unit[0].transform, srcX, srcY,
-			      state.unit[0].width,
-			      state.unit[0].height, &sX0, &sY0);
-	NV10EXATransformCoord(state.unit[0].transform,
-			      srcX + width, srcY,
-			      state.unit[0].width,
-			      state.unit[0].height, &sX1, &sY1);
-	NV10EXATransformCoord(state.unit[0].transform,
-			      srcX + width, srcY + height,
-			      state.unit[0].width,
-			      state.unit[0].height, &sX2, &sY2);
-	NV10EXATransformCoord(state.unit[0].transform,
-			      srcX, srcY + height,
-			      state.unit[0].width,
-			      state.unit[0].height, &sX3, &sY3);
-
-	if (state.is_a8_plus_a8) {
-		/*We do A8 + A8 in 2-pass : setup the source texture as A8 twice, 
-			with different tex coords, do B and G on first pass
-		Then setup again and do R and A on second pass
-		*/
-		int part_pos_dX = 0;
-		int part_pos_sX = 0;
-		int mask_out_bytes = 0;
-
-		part_pos_dX = (dstX & ~3) >> 2;	/*we start at the 4byte boundary to the left of the image */
-		part_pos_sX = sX0 + (dstX & ~3) - dstX;
-
-		/*xf86DrvMsg(0, X_INFO, "drawing - srcX %f dstX %d w %d\n", sX0, dstX, width);*/
-		for (; part_pos_dX <= (((dstX + width) & ~3) >> 2); part_pos_sX += 4, part_pos_dX++) {
-			mask_out_bytes = 0;
-			if (part_pos_dX == (dstX & ~3) >> 2) {
-				/*we're slightly on the left of the image, bytes to mask out */
-				/*xf86DrvMsg(0, X_INFO, "on left border...\n");*/
-				switch (dstX - (dstX & ~3)) {	/*mask out the extra pixels on the left */
-				case 4:
-					mask_out_bytes |= 1 << 0;
-				case 3:
-					mask_out_bytes |= 1 << 1;
-				case 2:
-					mask_out_bytes |= 1 << 2;
-				case 1:
-					mask_out_bytes |= 1 << 3;
-				case 0:
-					break;
-				}
-
-				/*mask out extra pixels on the right, in case the picture never touches an alignment marker */
-				switch (width + (dstX & 3)) {
-				case 0:
-					mask_out_bytes |= 1 << 3;
-				case 1:
-					mask_out_bytes |= 1 << 2;
-				case 2:
-					mask_out_bytes |= 1 << 1;
-				case 3:
-					mask_out_bytes |= 1 << 0;
-				default:
-					break;
-				}
-			} else if (part_pos_dX == (((dstX + width) & ~3) >> 2)) {
-				/*xf86DrvMsg(0, X_INFO, "on right border...\n"); */
-				switch (4 - ((dstX + width) & 3)) {
-				case 4:
-					mask_out_bytes |= 1 << 3;
-				case 3:
-					mask_out_bytes |= 1 << 2;
-				case 2:
-					mask_out_bytes |= 1 << 1;
-				case 1:
-					mask_out_bytes |= 1 << 0;
-				case 0:
-					break;
-				}
-			}
-
-			/*Pass number 0*/
-			
-			NV10SetRegCombs_A8plusA8(pNv, 0, mask_out_bytes);
-			BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
-			OUT_RING  (chan, NV10TCL_VERTEX_BEGIN_END_QUADS);		
-					
-			NV10MVertex(pNv , part_pos_dX	, dstY              , part_pos_sX, sY0, part_pos_sX + 1, sY0);
-			NV10MVertex(pNv , part_pos_dX + 1, dstY              , part_pos_sX, sY0, part_pos_sX + 1, sY0);
-			NV10MVertex(pNv , part_pos_dX + 1, dstY + height, part_pos_sX,  sY2, part_pos_sX + 1, sY2);
-			NV10MVertex(pNv , part_pos_dX	, dstY + height, part_pos_sX, sY2, part_pos_sX + 1, sY2);
-			
-			BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
-			OUT_RING  (chan, NV10TCL_VERTEX_BEGIN_END_STOP);
-			
-			/*Pass number 1*/
-
-			NV10SetRegCombs_A8plusA8(pNv, 1, mask_out_bytes);
-			BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
-			OUT_RING  (chan, NV10TCL_VERTEX_BEGIN_END_QUADS);		
-					
-			NV10MVertex(pNv , part_pos_dX, dstY              , part_pos_sX + 2, sY0, part_pos_sX + 3, sY0);
-			NV10MVertex(pNv , part_pos_dX + 1 , dstY              , part_pos_sX + 2, sY0, part_pos_sX + 3, sY0);
-			NV10MVertex(pNv , part_pos_dX + 1 , dstY + height, part_pos_sX + 2, sY2, part_pos_sX + 3, sY2);
-			NV10MVertex(pNv , part_pos_dX, dstY + height, part_pos_sX + 2, sY2, part_pos_sX + 3, sY2);
-
-			BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
-			OUT_RING  (chan, NV10TCL_VERTEX_BEGIN_END_STOP);
-			
-			}
-	} else if (state.have_mask) {
-		NV10EXATransformCoord(state.unit[1].transform, maskX, maskY,
-				      state.unit[1].width,
-				      state.unit[1].height, &mX0, &mY0);
-		NV10EXATransformCoord(state.unit[1].transform,
-				      maskX + width, maskY,
-				      state.unit[1].width,
-				      state.unit[1].height, &mX1, &mY1);
-		NV10EXATransformCoord(state.unit[1].transform,
-				      maskX + width, maskY + height,
-				      state.unit[1].width,
-				      state.unit[1].height, &mX2, &mY2);
-		NV10EXATransformCoord(state.unit[1].transform,
-				      maskX, maskY + height,
-				      state.unit[1].width,
-				      state.unit[1].height, &mX3, &mY3);
-		NV10MVertex(pNv , dstX         ,          dstY,sX0 , sY0 , mX0 , mY0);
-		NV10MVertex(pNv , dstX + width ,          dstY,sX1 , sY1 , mX1 , mY1);
-		NV10MVertex(pNv , dstX + width , dstY + height,sX2 , sY2 , mX2 , mY2);
-		NV10MVertex(pNv , dstX         , dstY + height,sX3 , sY3 , mX3 , mY3);
-	} else {
-		NV10Vertex(pNv , dstX         ,          dstY , sX0 , sY0);
-		NV10Vertex(pNv , dstX + width ,          dstY , sX1 , sY1);
-		NV10Vertex(pNv , dstX + width , dstY + height , sX2 , sY2);
-		NV10Vertex(pNv , dstX         , dstY + height , sX3 , sY3);
-	}
+	MAP(emit_vertex, pNv, dstq, srcq, mask ? maskq : NULL);
 
 	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
 	OUT_RING  (chan, NV10TCL_VERTEX_BEGIN_END_STOP);
 }
 
-void NV10EXADoneComposite(PixmapPtr pDst)
+void
+NV10EXADoneComposite(PixmapPtr dst)
 {
-	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+	ScrnInfoPtr pScrn = xf86Screens[dst->drawable.pScreen->myNum];
 	NVPtr pNv = NVPTR(pScrn);
 	struct nouveau_channel *chan = pNv->chan;
 
 	chan->flush_notify = NULL;
 }
 
-Bool NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
+Bool
+NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
 {
 	NVPtr pNv = NVPTR(pScrn);
 	struct nouveau_channel *chan = pNv->chan;
@@ -978,13 +759,19 @@ Bool NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
 	OUT_RING  (chan, 0);
 
 	BEGIN_RING(chan, celsius, NV10TCL_RT_HORIZ, 2);
+	OUT_RING  (chan, 2048 << 16 | 0);
+	OUT_RING  (chan, 2048 << 16 | 0);
+
+	BEGIN_RING(chan, celsius, NV10TCL_ZETA_OFFSET, 1);
 	OUT_RING  (chan, 0);
+
+	BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_MODE, 1);
 	OUT_RING  (chan, 0);
 
 	BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
-	OUT_RING  (chan, (0x7ff<<16)|0x800);
+	OUT_RING  (chan, 0x7ff << 16 | 0x800800);
 	BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
-	OUT_RING  (chan, (0x7ff<<16)|0x800);
+	OUT_RING  (chan, 0x7ff << 16 | 0x800800);
 
 	for (i = 1; i < 8; i++) {
 		BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1);
@@ -1113,9 +900,9 @@ Bool NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
 	BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1);
 	OUT_RING  (chan, 0);
 	BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_S(0), 8);
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < 8; i++)
 		OUT_RING  (chan, 0);
-	}
+
 	BEGIN_RING(chan, celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3);
 	OUT_RING  (chan, 0x3fc00000);	/* -1.50 */
 	OUT_RING  (chan, 0xbdb8aa0a);	/* -0.09 */
@@ -1135,6 +922,20 @@ Bool NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
 	BEGIN_RING(chan, celsius, NV10TCL_COLOR_MASK, 1);
 	OUT_RING  (chan, 0x01010101);
 
+	BEGIN_RING(chan, celsius, NV10TCL_PROJECTION_MATRIX(0), 16);
+	for(i = 0; i < 16; i++)
+		OUT_RINGf(chan, i/4 == i%4 ? 1.0 : 0.0);
+
+	BEGIN_RING(chan, celsius, NV10TCL_DEPTH_RANGE_NEAR, 2);
+	OUT_RING  (chan, 0);
+	OUT_RINGf (chan, 65536.0);
+
+	BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_SCALE_X, 4);
+	OUT_RINGf (chan, -2048.0);
+	OUT_RINGf (chan, -2048.0);
+	OUT_RINGf (chan, 0);
+	OUT_RING  (chan, 0);
+
 	/* Set vertex component */
 	BEGIN_RING(chan, celsius, NV10TCL_VERTEX_COL_4F_R, 4);
 	OUT_RINGf (chan, 1.0);
-- 
1.6.4.4



More information about the Nouveau mailing list