xf86-video-intel: Branch 'exa' - src/i830_accel.c src/i830_exa.c src/i830_exa_render.c src/i830_reg.h src/i915_exa_render.c src/i915_reg.h src/Makefile.am

Zhenyu Wang zhen at kemper.freedesktop.org
Fri Jul 14 11:13:22 EEST 2006


 src/Makefile.am       |    4 
 src/i830_accel.c      |    3 
 src/i830_exa.c        |  285 +++++++++++++++++++++----
 src/i830_exa_render.c |  537 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/i830_reg.h        |  101 ++++++++-
 src/i915_exa_render.c |  553 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/i915_reg.h        |    3 
 7 files changed, 1433 insertions(+), 53 deletions(-)

New commits:
diff-tree 04d1584737fd0d14e99608a97281fd7b1549ae0e (from b85f268051a785f90e4c55bd1cac80d673388f16)
Author: Wang Zhenyu <zhenyu.z.wang at intel.com>
Date:   Fri Jul 14 16:14:18 2006 +0800

    Current exa render implement for i830 and i915, test on
    865GM and 915G. There is issue in picture 'repeat' support.
    And also stop recursive behavior in I830WaitLpRing to allow
    server to abort instead of system hang.

diff --git a/src/Makefile.am b/src/Makefile.am
index c9e8780..9c2a5c2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,7 +60,9 @@ i810_drv_la_SOURCES = \
 	 i915_3d.c \
 	 i915_reg.h \
 	 i830_exa.c \
-	 i830_xaa.c
+	 i830_xaa.c \
+	 i830_exa_render.c \
+	 i915_exa_render.c
 
 if DRI
 i810_drv_la_SOURCES += \
diff --git a/src/i830_accel.c b/src/i830_accel.c
index f299398..6b33887 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -110,6 +110,9 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n,
 #ifdef I830_USE_XAA
 	 pI830->AccelInfoRec = NULL;	/* Stops recursive behavior */
 #endif
+#ifdef I830_USE_EXA
+	 pI830->EXADriverPtr = NULL;
+#endif
 	 FatalError("lockup\n");
       }
 
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 665c4d7..83601dc 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -36,9 +36,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "xaarop.h"
 #include "i830.h"
 #include "i810_reg.h"
+#include "i830_reg.h"
 
 #ifdef I830DEBUG
-#define DEBUG_I830FALLBACK 0
+#define DEBUG_I830FALLBACK 1
 #endif
 
 #ifdef DEBUG_I830FALLBACK
@@ -48,9 +49,15 @@ do {							\
 	return FALSE;					\
 } while(0)
 #else
-#define I830FALLBACK(s, arg...) { return FALSE; }
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
 #endif
 
+float scale_units[2][2];
+int draw_coords[3][2];
+
 const int I830CopyROP[16] =
 {
    ROP_0,               /* GXclear */
@@ -91,12 +98,33 @@ const int I830PatternROP[16] =
     ROP_1
 };
 
-void i830ScratchSave(ScreenPtr pScreen, ExaOffscreenArea *area);
-Bool i830UploadToScreen(PixmapPtr pDst, char *src, int src_pitch);
-Bool i830UploadToScratch(PixmapPtr pSrc, PixmapPtr pDst);
+/* move to common.h */
+union intfloat {
+	float f;
+	unsigned int ui;
+};
+
+#define OUT_RING_F(x) do {			\
+	union intfloat tmp;			\
+	tmp.f = (float)(x);			\
+	OUT_RING(tmp.ui);			\
+} while(0)				
+
+Bool is_transform[2];
+PictTransform *transform[2];
+
+Bool i830UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 
+			    char *src, int src_pitch);
 Bool i830DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
 			    char *dst, int dst_pitch);
 
+extern Bool I830EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
+extern Bool I830EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
+				PixmapPtr, PixmapPtr, PixmapPtr);
+extern Bool I915EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr);
+extern Bool I915EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, 
+				PixmapPtr, PixmapPtr, PixmapPtr);
+
 /**
  * I830EXASync - wait for a command to finish
  * @pScreen: current screen
@@ -295,27 +323,69 @@ I830EXACopy(PixmapPtr pDstPixmap, int sr
 static void
 I830EXADoneCopy(PixmapPtr pDstPixmap)
 {
-    return;
+    	return;
 }
 
-#if 0 /* Not done (or even started for that matter) */
+//#define UPLOAD_USE_BLIT 1
+
 static Bool
-I830EXAUploadToScreen(PixmapPtr pDst, char *src, int src_pitch)
+I830EXAUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 
+		char *src, int src_pitch)
 {
     ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned char *dst = pDst->devPrivate.ptr;
     int dst_pitch = exaGetPixmapPitch(pDst);
-    int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
-    int h = pDst->drawable.height;
+    int dst_offset = exaGetPixmapOffset(pDst);
+    unsigned char *dst;
 
     I830Sync(pScrn);
 
+    ErrorF("Up->Screen: dst offset 0x%x, dst pitch %d, x %d, y %d, src %p, src pitch %d\n",
+		dst_offset, dst_pitch, x, y, src, src_pitch);
+#ifndef UPLOAD_USE_BLIT
+    dst = pI830->FbBase + dst_offset + y*dst_pitch + 
+		x* (pDst->drawable.bitsPerPixel/8);
+    w *= pDst->drawable.bitsPerPixel/8;
     while(h--) {
-	i830MemCopyToVideoRam(pI830, dst, (unsigned char *)src, size);
+	memcpy(dst, src, w);
 	src += src_pitch;
 	dst += dst_pitch;
     }
+#else
+    /* setup blit engine to copy one pixel data by one */
+    {
+	int x1, x2, y1, y2, i, j;
+	CARD32 d, len, *srcp;
+	x1 = x;
+	y1 = y;
+	x2 = x + w;
+	y2 = y + h;
+
+	len = (w * (pDst->drawable.bitsPerPixel/8)) >> 2;
+
+	pI830->BR[13] = (1 << 24) | (1 << 25);
+	pI830->BR[13] |= I830CopyROP[GXcopy]<<16;
+	pI830->BR[13] |= dst_pitch & 0xffff;
+	for (i = 0; i < h; i++) {
+		srcp = (CARD32*)src;
+		for ( j = len; j > 0; j--) {
+			d = *srcp;
+			BEGIN_LP_RING(6);
+			OUT_RING(XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | 
+				XY_COLOR_BLT_WRITE_RGB);
+			OUT_RING(pI830->BR[13]);
+			OUT_RING((y1 << 16) | x1);
+			OUT_RING((y2 << 16) | x2);
+			OUT_RING(dst_offset);
+			OUT_RING(d);
+			ADVANCE_LP_RING();
+			srcp++;
+		}
+		src += src_pitch;
+	}
+
+    }
+#endif
 
     return TRUE;
 }
@@ -326,14 +396,18 @@ I830EXADownloadFromScreen(PixmapPtr pSrc
 {
     ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned char *src = pSrc->devPrivate.ptr;
     int src_pitch = exaGetPixmapPitch(pSrc);
-    int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+    int src_offset = exaGetPixmapOffset(pSrc);
+    unsigned char *src = pI830->FbBase + src_offset + y*src_pitch +
+		x*(pSrc->drawable.bitsPerPixel/8);
 
     I830Sync(pScrn);
 
+    ErrorF("Screen->Mem: src offset 0x%x, src %p, src pitch %d, x %d, y %d, dst %p, dst_pitch %d\n",
+	src_offset, src, src_pitch, x, y, dst, dst_pitch);
+    w *= pSrc->drawable.bitsPerPixel/8;
     while(h--) {
-	i830MemCopyFromVideoRam(pI830, (unsigned char *)dst, src, size);
+	memcpy(dst, src, w);
 	src += src_pitch;
 	dst += dst_pitch;
     }
@@ -341,40 +415,145 @@ I830EXADownloadFromScreen(PixmapPtr pSrc
     return TRUE;
 }
 
-static Bool
-I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
-		      PicturePtr pDstPicture)
+static void
+IntelEXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+		 int dstX, int dstY, int w, int h)
 {
-    return FALSE; /* no Composite yet */
-}
+	/* should be same like I830Composite */
+    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    int srcXend, srcYend, maskXend, maskYend;
+    PictVector v;
+    int pMask = 1;
+
+ErrorF("Composite: srcX %d, srcY %d\n\t maskX %d, maskY %d\n\t"
+	     "dstX %d, dstY %d\n\twidth %d, height %d\n\t"
+	     "src_scale_x %f, src_scale_y %f, mask_scale_x %f, mask_scale_y %f\n""\tdx0 %d, dy0 %x, dx1 %d dy1 %x\n", 
+		srcX, srcY, maskX, maskY, dstX, dstY, w, h,
+		scale_units[0][0], scale_units[0][1], 
+		scale_units[1][0], scale_units[1][1],
+		draw_coords[0][0], draw_coords[0][1], 
+		draw_coords[1][0], draw_coords[1][1]);
+
+    if (scale_units[1][0] == -1 || scale_units[1][1] == -1) {
+	ErrorF("mask is null\n");
+	pMask = 0;
+    }
 
-static Bool
-I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
-			PicturePtr pMaskPicture, PicturePtr pDstPicture,
-			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
-{
-    return FALSE; /* no Composite yet */
-}
+    srcXend = srcX + w;
+    srcYend = srcY + h;
+    maskXend = maskX + w;
+    maskYend = maskY + h;
+    if (is_transform[0]) {
+        v.vector[0] = IntToxFixed(srcX);
+        v.vector[1] = IntToxFixed(srcY);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[0], &v);
+        srcX = xFixedToInt(v.vector[0]);
+        srcY = xFixedToInt(v.vector[1]);
+        v.vector[0] = IntToxFixed(srcXend);
+        v.vector[1] = IntToxFixed(srcYend);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[0], &v);
+        srcXend = xFixedToInt(v.vector[0]);
+        srcYend = xFixedToInt(v.vector[1]);
+    }
+    if (is_transform[1]) {
+        v.vector[0] = IntToxFixed(maskX);
+        v.vector[1] = IntToxFixed(maskY);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[1], &v);
+        maskX = xFixedToInt(v.vector[0]);
+        maskY = xFixedToInt(v.vector[1]);
+        v.vector[0] = IntToxFixed(maskXend);
+        v.vector[1] = IntToxFixed(maskYend);
+        v.vector[2] = xFixed1;
+        PictureTransformPoint(transform[1], &v);
+        maskXend = xFixedToInt(v.vector[0]);
+        maskYend = xFixedToInt(v.vector[1]);
+    }
+DPRINTF(PFX, "After transform: srcX %d, srcY %d,srcXend %d, srcYend %d\n\t"
+		"maskX %d, maskY %d, maskXend %d, maskYend %d\n\t"
+		"dstX %d, dstY %d\n", srcX, srcY, srcXend, srcYend,
+		maskX, maskY, maskXend, maskYend, dstX, dstY);
+
+    draw_coords[0][0] -= draw_coords[2][0];
+    draw_coords[0][1] -= draw_coords[2][1];
+    if (pMask) {
+	draw_coords[1][0] -= draw_coords[2][0];
+	draw_coords[1][1] -= draw_coords[2][1];
+    }
+
+    {
+	int vertex_count; 
+
+	if (pMask)
+		vertex_count = 4*6;
+	else
+		vertex_count = 4*4;
+
+	BEGIN_LP_RING(6+vertex_count);
+
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_NOOP);
+
+	OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (vertex_count-1));
+
+	OUT_RING(dstX);
+	OUT_RING(dstY);
+	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
+	if (pMask) {
+		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
+	}
+
+	OUT_RING(dstX);
+	OUT_RING((dstY+h));
+	OUT_RING_F(((srcX - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
+	if (pMask) {
+		OUT_RING_F(((maskX - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
+	}
+
+	OUT_RING((dstX+w));
+	OUT_RING((dstY+h));
+	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcYend - draw_coords[0][1]) / scale_units[0][1]));
+	if (pMask) {
+		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskYend - draw_coords[1][1]) / scale_units[1][1]));
+	}
+
+	OUT_RING((dstX+w));
+	OUT_RING((dstY));
+	OUT_RING_F(((srcXend - draw_coords[0][0]) / scale_units[0][0]));
+	OUT_RING_F(((srcY - draw_coords[0][1]) / scale_units[0][1]));
+	if (pMask) {
+		OUT_RING_F(((maskXend - draw_coords[1][0]) / scale_units[1][0]));
+		OUT_RING_F(((maskY - draw_coords[1][1]) / scale_units[1][1]));
+	}
+	ADVANCE_LP_RING();
+    }
+#ifdef I830DEBUG
+    ErrorF("sync after 3dprimitive");
+    I830Sync(pScrn);
+#endif
 
-static void
-I830EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
-		 int dstX, int dstY, int width, int height)
-{
-    return; /* no Composite yet */
 }
 
 static void
-I830EXADoneComposite(PixmapPtr pDst)
+IntelEXADoneComposite(PixmapPtr pDst)
 {
-    return; /* no Composite yet */
+    return; 
 }
-#endif
-
 /*
  * TODO:
  *   - Dual head?
- *   - Upload/Download
- *   - Composite
  */
 Bool
 I830EXAInit(ScreenPtr pScreen)
@@ -396,6 +575,12 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
     pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
 	   
+    DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
+		pI830->EXADriverPtr->memoryBase,
+		pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize,
+		pI830->EXADriverPtr->offScreenBase,
+		pI830->EXADriverPtr->memorySize);
+
     if(pI830->EXADriverPtr->memorySize >
        pI830->EXADriverPtr->offScreenBase)
 	pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
@@ -422,17 +607,23 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->PrepareCopy = I830EXAPrepareCopy;
     pI830->EXADriverPtr->Copy = I830EXACopy;
     pI830->EXADriverPtr->DoneCopy = I830EXADoneCopy;
-#if 0
-    /* Upload, download to/from Screen */
-    pI830->EXADriverPtr->UploadToScreen = I830EXAUploadToScreen;
-    pI830->EXADriverPtr->DownloadFromScreen = I830EXADownloadFromScreen;
 
     /* Composite */
-    pI830->EXADriverPtr->CheckComposite = I830EXACheckComposite;
-    pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite;
-    pI830->EXADriverPtr->Composite = I830EXAComposite;
-    pI830->EXADriverPtr->DoneComposite = I830EXADoneComposite;
-#endif
+    if (IS_I9XX(pI830)) {   		
+	pI830->EXADriverPtr->CheckComposite = I915EXACheckComposite;
+   	pI830->EXADriverPtr->PrepareComposite = I915EXAPrepareComposite;
+    	pI830->EXADriverPtr->Composite = IntelEXAComposite;
+    	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
+    } else if (IS_I865G(pI830) || IS_I855(pI830) || IS_845G(pI830) || IS_I830(pI830)) { 
+    	pI830->EXADriverPtr->CheckComposite = I830EXACheckComposite;
+    	pI830->EXADriverPtr->PrepareComposite = I830EXAPrepareComposite;
+    	pI830->EXADriverPtr->Composite = IntelEXAComposite;
+    	pI830->EXADriverPtr->DoneComposite = IntelEXADoneComposite;
+    }
+
+    /* Upload, download to/from Screen, experimental!! */
+    pI830->EXADriverPtr->UploadToScreen = I830EXAUploadToScreen;
+    pI830->EXADriverPtr->DownloadFromScreen = I830EXADownloadFromScreen;
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
 	xfree(pI830->EXADriverPtr);
diff --git a/src/i830_exa_render.c b/src/i830_exa_render.c
new file mode 100644
index 0000000..9b4835b
--- /dev/null
+++ b/src/i830_exa_render.c
@@ -0,0 +1,537 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_reg.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
+#endif
+
+extern float scale_units[2][2];
+extern int draw_coords[3][2];
+extern Bool is_transform[2];
+extern PictTransform *transform[2];
+
+struct blendinfo {
+    Bool dst_alpha;
+    Bool src_alpha;
+    CARD32 blend_cntl;
+};
+
+struct formatinfo {
+    int fmt;
+    CARD32 card_fmt;
+};
+
+extern Bool
+I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture);
+
+extern Bool
+I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
+
+/* I830's Blend factor definition, LOAD_STATE_IMMEDIATE_1 */
+/* move to header...*/
+#define I830_SRC_BLENDFACTOR_ZERO 		(1 << 4)
+#define I830_SRC_BLENDFACTOR_ONE 		(2 << 4)
+#define I830_SRC_BLENDFACTOR_SRC_COLOR		(3 << 4)
+#define I830_SRC_BLENDFACTOR_INV_SRC_COLOR	(4 << 4)
+#define I830_SRC_BLENDFACTOR_SRC_ALPHA		(5 << 4)
+#define I830_SRC_BLENDFACTOR_INV_SRC_ALPHA	(6 << 4)
+#define I830_SRC_BLENDFACTOR_DST_ALPHA		(7 << 4)
+#define I830_SRC_BLENDFACTOR_INV_DST_ALPHA	(8 << 4)
+#define I830_SRC_BLENDFACTOR_DST_COLOR		(9 << 4)
+#define I830_SRC_BLENDFACTOR_INV_DST_COLOR	(0xa << 4)
+#define I830_SRC_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 4)
+#define I830_SRC_BLENDFACTOR_CONST_COLOR	(0xc << 4)
+#define I830_SRC_BLENDFACTOR_INV_CONST_COLOR	(0xd << 4)
+#define I830_SRC_BLENDFACTOR_CONST_ALPHA	(0xe << 4)
+#define I830_SRC_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 4)
+#define I830_SRC_BLENDFACTOR_MASK		(0xf << 4)
+
+#define I830_DST_BLENDFACTOR_ZERO 		(1)
+#define I830_DST_BLENDFACTOR_ONE 		(2)
+#define I830_DST_BLENDFACTOR_SRC_COLOR		(3)
+#define I830_DST_BLENDFACTOR_INV_SRC_COLOR	(4)
+#define I830_DST_BLENDFACTOR_SRC_ALPHA		(5)
+#define I830_DST_BLENDFACTOR_INV_SRC_ALPHA	(6)
+#define I830_DST_BLENDFACTOR_DST_ALPHA		(7)
+#define I830_DST_BLENDFACTOR_INV_DST_ALPHA	(8)
+#define I830_DST_BLENDFACTOR_DST_COLOR		(9)
+#define I830_DST_BLENDFACTOR_INV_DST_COLOR	(0xa)
+#define I830_DST_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb)
+#define I830_DST_BLENDFACTOR_CONST_COLOR	(0xc)
+#define I830_DST_BLENDFACTOR_INV_CONST_COLOR	(0xd)
+#define I830_DST_BLENDFACTOR_CONST_ALPHA	(0xe)
+#define I830_DST_BLENDFACTOR_INV_CONST_ALPHA	(0xf)
+#define I830_DST_BLENDFACTOR_MASK		(0xf)
+
+#define TB0C_LAST_STAGE	(1 << 31)
+#define TB0C_RESULT_SCALE_1X		(0 << 29)
+#define TB0C_RESULT_SCALE_2X		(1 << 29)
+#define TB0C_RESULT_SCALE_4X		(2 << 29)
+#define TB0C_OP_MODULE			(3 << 25)
+#define TB0C_OUTPUT_WRITE_CURRENT	(0 << 24)
+#define TB0C_OUTPUT_WRITE_ACCUM		(1 << 24)
+#define TB0C_ARG3_REPLICATE_ALPHA 	(1<<23)
+#define TB0C_ARG3_INVERT		(1<<22)
+#define TB0C_ARG3_SEL_XXX
+#define TB0C_ARG2_REPLICATE_ALPHA 	(1<<17)
+#define TB0C_ARG2_INVERT		(1<<16)
+#define TB0C_ARG2_SEL_ONE		(0 << 12)
+#define TB0C_ARG2_SEL_FACTOR		(1 << 12)
+#define TB0C_ARG2_SEL_TEXEL0		(6 << 12)
+#define TB0C_ARG2_SEL_TEXEL1		(7 << 12)
+#define TB0C_ARG2_SEL_TEXEL2		(8 << 12)
+#define TB0C_ARG2_SEL_TEXEL3		(9 << 12)
+#define TB0C_ARG1_REPLICATE_ALPHA 	(1<<11)
+#define TB0C_ARG1_INVERT		(1<<10)
+#define TB0C_ARG1_SEL_TEXEL0		(6 << 6)
+#define TB0C_ARG1_SEL_TEXEL1		(7 << 6)
+#define TB0C_ARG1_SEL_TEXEL2		(8 << 6)
+#define TB0C_ARG1_SEL_TEXEL3		(9 << 6)
+#define TB0C_ARG0_REPLICATE_ALPHA 	(1<<5)
+#define TB0C_ARG0_SEL_XXX
+
+#define TB0A_CTR_STAGE_ENABLE 		(1<<31)
+#define TB0A_RESULT_SCALE_1X		(0 << 29)
+#define TB0A_RESULT_SCALE_2X		(1 << 29)
+#define TB0A_RESULT_SCALE_4X		(2 << 29)
+#define TB0A_OP_MODULE			(3 << 25)
+#define TB0A_OUTPUT_WRITE_CURRENT	(0<<24)
+#define TB0A_OUTPUT_WRITE_ACCUM		(1<<24)
+#define TB0A_CTR_STAGE_SEL_BITS_XXX
+#define TB0A_ARG3_SEL_XXX
+#define TB0A_ARG3_INVERT		(1<<17)
+#define TB0A_ARG2_INVERT		(1<<16)
+#define TB0A_ARG2_SEL_ONE		(0 << 12)
+#define TB0A_ARG2_SEL_TEXEL0		(6 << 12)
+#define TB0A_ARG2_SEL_TEXEL1		(7 << 12)
+#define TB0A_ARG2_SEL_TEXEL2		(8 << 12)
+#define TB0A_ARG2_SEL_TEXEL3		(9 << 12)
+#define TB0A_ARG1_INVERT		(1<<10)
+#define TB0A_ARG1_SEL_TEXEL0		(6 << 6)
+#define TB0A_ARG1_SEL_TEXEL1		(7 << 6)
+#define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
+#define TB0A_ARG1_SEL_TEXEL3		(9 << 6)
+#define TB0A_ARG0_SEL_XXX
+
+/* end */
+
+
+static struct blendinfo I830BlendOp[] = { 
+    /* Clear */
+    {0, 0, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_ZERO},
+    /* Src */
+    {0, 0, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_ZERO},
+    /* Dst */
+    {0, 0, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_ONE},
+    /* Over */
+    {0, 1, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* OverReverse */
+    {1, 0, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_ONE},
+    /* In */
+    {1, 0, I830_SRC_BLENDFACTOR_DST_ALPHA     | I830_DST_BLENDFACTOR_ZERO},
+    /* InReverse */
+    {0, 1, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_SRC_ALPHA},
+    /* Out */
+    {1, 0, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_ZERO},
+    /* OutReverse */
+    {0, 1, I830_SRC_BLENDFACTOR_ZERO           | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Atop */
+    {1, 1, I830_SRC_BLENDFACTOR_DST_ALPHA     | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* AtopReverse */
+    {1, 1, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_SRC_ALPHA},
+    /* Xor */
+    {1, 1, I830_SRC_BLENDFACTOR_INV_DST_ALPHA | I830_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Add */
+    {0, 0, I830_SRC_BLENDFACTOR_ONE            | I830_DST_BLENDFACTOR_ONE},
+};
+
+
+static struct formatinfo I830TexFormats[] = {
+        {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
+        {PICT_x8r8g8b8, MT_32BIT_ARGB8888 },
+        {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
+        {PICT_x8b8g8r8, MT_32BIT_ABGR8888 },
+        {PICT_r5g6b5,   MT_16BIT_RGB565	  },
+        {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_a8,       MT_8BIT_I8       },
+};
+
+static Bool I830GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+	/* XXX: color buffer format for i830 */
+    switch (pDstPicture->format) {
+    case PICT_a8r8g8b8:
+    case PICT_x8r8g8b8:
+        *dst_format = COLR_BUF_ARGB8888;
+        break;
+    case PICT_r5g6b5:
+        *dst_format = COLR_BUF_RGB565;
+        break;
+    case PICT_a1r5g5b5:
+    case PICT_x1r5g5b5:
+        *dst_format = COLR_BUF_ARGB1555;
+        break;
+    case PICT_a8:
+        *dst_format = COLR_BUF_8BIT;
+        break;
+    case PICT_a4r4g4b4:
+    case PICT_x4r4g4b4:
+	*dst_format = COLR_BUF_ARGB4444;
+	break;
+    default:
+        I830FALLBACK("Unsupported dest format 0x%x\n",
+                        (int)pDstPicture->format);
+    }
+
+    return TRUE;
+}
+
+
+static CARD32 I830GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
+{
+    CARD32 sblend, dblend;
+
+    sblend = I830BlendOp[op].blend_cntl & I830_SRC_BLENDFACTOR_MASK;
+    dblend = I830BlendOp[op].blend_cntl & I830_DST_BLENDFACTOR_MASK;
+
+    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+     * it as always 1.
+     */
+    if (PICT_FORMAT_A(dst_format) == 0 && I830BlendOp[op].dst_alpha) {
+        if (sblend == I830_SRC_BLENDFACTOR_DST_ALPHA)
+            sblend = I830_SRC_BLENDFACTOR_ONE;
+        else if (sblend == I830_SRC_BLENDFACTOR_INV_DST_ALPHA)
+            sblend = I830_SRC_BLENDFACTOR_ZERO;
+    }
+
+    /* If the source alpha is being used, then we should only be in a case where
+     * the source blend factor is 0, and the source blend value is the mask
+     * channels multiplied by the source picture's alpha.
+     */
+    if (pMask && pMask->componentAlpha && I830BlendOp[op].src_alpha) {
+        if (dblend == I830_DST_BLENDFACTOR_SRC_ALPHA) {
+            dblend = I830_DST_BLENDFACTOR_SRC_COLOR;
+        } else if (dblend == I830_DST_BLENDFACTOR_INV_SRC_ALPHA) {
+            dblend = I830_DST_BLENDFACTOR_INV_SRC_COLOR;
+        }
+    }
+
+    return sblend | dblend;
+}
+
+static Bool I830CheckCompositeTexture(PicturePtr pPict, int unit)
+{
+    int w = pPict->pDrawable->width;
+    int h = pPict->pDrawable->height;
+    int i;
+                                                                                                                                                            
+    if ((w > 0x7ff) || (h > 0x7ff))
+        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++)
+    {
+        if (I830TexFormats[i].fmt == pPict->format)
+            break;
+    }
+    if (i == sizeof(I830TexFormats) / sizeof(I830TexFormats[0]))
+        I830FALLBACK("Unsupported picture format 0x%x\n",
+                         (int)pPict->format);
+
+    /* FIXME: fix repeat support */
+    if (pPict->repeat)
+	I830FALLBACK("repeat unsupport now\n");
+
+    if (pPict->filter != PictFilterNearest &&
+        pPict->filter != PictFilterBilinear)
+        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+    return TRUE;
+}
+
+static Bool
+I830TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
+{
+
+    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 format, offset, pitch, filter;
+    int w, h, i;
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP; 
+
+    offset = exaGetPixmapOffset(pPix);
+    pitch = exaGetPixmapPitch(pPix);
+    w = pPict->pDrawable->width;
+    h = pPict->pDrawable->height;
+    scale_units[unit][0] = pPix->drawable.width;
+    scale_units[unit][1] = pPix->drawable.height;
+    draw_coords[unit][0] = pPix->drawable.x;
+    draw_coords[unit][1] = pPix->drawable.y;
+
+    for (i = 0; i < sizeof(I830TexFormats) / sizeof(I830TexFormats[0]); i++) {
+        if (I830TexFormats[i].fmt == pPict->format)
+	    break;
+    }
+    if ( i == sizeof(I830TexFormats)/ sizeof(I830TexFormats[0]) )
+	I830FALLBACK("unknown texture format\n");
+    format = I830TexFormats[i].card_fmt;
+
+    if (pPict->repeat) 
+	wrap_mode = TEXCOORDMODE_WRAP; /* XXX: correct ? */
+    
+    switch (pPict->filter) {
+    case PictFilterNearest:
+        filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) | 
+			(FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
+        break;
+    case PictFilterBilinear:
+        filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) | 
+			(FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
+        break;
+    default:
+	filter = 0;
+        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
+    }
+
+    {
+	if (pI830->cpp == 1)
+		format |= MAP_SURFACE_8BIT;
+	else if (pI830->cpp == 2)
+		format |= MAP_SURFACE_16BIT;
+	else
+		format |= MAP_SURFACE_32BIT;
+
+	BEGIN_LP_RING(6);
+	OUT_RING(_3DSTATE_MAP_INFO_CMD);
+	OUT_RING(format | TEXMAP_INDEX(unit) | MAP_FORMAT_2D);
+	OUT_RING((pPix->drawable.height<<16)|pPix->drawable.width); /* height, width */
+	OUT_RING(offset<<2); /* map address */
+	OUT_RING(pitch<<2); /* map pitch */
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+     }
+
+     {
+	BEGIN_LP_RING(2);
+	/* coord sets */
+	OUT_RING(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 
+		ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | /*XXX, check this, and fix vertex tex coord*/
+		TEXCOORDTYPE_CARTESIAN | ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(wrap_mode) |
+		ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
+	OUT_RING(MI_NOOP);
+
+	/* XXX: filter seems hang engine...*/
+#if 0
+	OUT_RING(I830_STATE3D_MAP_FILTER | FILTER_MAP_INDEX(unit) | ENABLE_KEYS| DISABLE_COLOR_KEY | DISABLE_CHROMA_KEY | DISABLE_KILL_PIXEL |ENABLE_MIP_MODE_FILTER | MIPFILTER_NONE | filter);
+	OUT_RING(0);
+#endif
+
+	/* max & min mip level ? or base mip level? */
+
+	ADVANCE_LP_RING();
+    }
+
+	/* XXX */
+    if (pPict->transform != 0) {
+        is_transform[unit] = TRUE;
+        transform[unit] = pPict->transform;
+    } else {
+        is_transform[unit] = FALSE;
+    }
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+	
+    return TRUE;
+}
+
+Bool
+I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+    CARD32 tmp1;
+    
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(I830BlendOp) / sizeof(I830BlendOp[0]))
+        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+                                                                                                                                                            
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+        /* Check if it's component alpha that relies on a source alpha and on
+         * the source value.  We can only get one of those into the single
+         * source value that we get to blend with.
+         */
+        if (I830BlendOp[op].src_alpha &&
+            (I830BlendOp[op].blend_cntl & I830_SRC_BLENDFACTOR_MASK) !=
+             I830_SRC_BLENDFACTOR_ZERO)
+            	I830FALLBACK("Component alpha not supported with source "
+                            "alpha and source value blending.\n");
+    }
+
+    if (!I830CheckCompositeTexture(pSrcPicture, 0))
+        I830FALLBACK("Check Src picture texture\n");
+    if (pMaskPicture != NULL && !I830CheckCompositeTexture(pMaskPicture, 1))
+        I830FALLBACK("Check Mask picture texture\n");
+
+    if (!I830GetDestFormat(pDstPicture, &tmp1)) 
+	I830FALLBACK("Get Color buffer format\n");
+
+    return TRUE;
+}
+
+
+static void
+I830DefCtxSetup(ScrnInfoPtr pScrn)
+{
+	/* coord binding */
+	CARD32 mcb;
+    	I830Ptr pI830 = I830PTR(pScrn);
+
+	BEGIN_LP_RING(2);
+	OUT_RING(_3DSTATE_MAP_COORD_SETBIND_CMD);
+	mcb = TEXBIND_SET3(TEXCOORDSRC_VTXSET_3);
+	mcb |= TEXBIND_SET2(TEXCOORDSRC_VTXSET_2);
+	mcb |= TEXBIND_SET1(TEXCOORDSRC_VTXSET_1);
+	mcb |= TEXBIND_SET0(TEXCOORDSRC_VTXSET_0);
+	OUT_RING(mcb);
+	ADVANCE_LP_RING();
+}
+
+
+Bool
+I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+/* XXX: setup texture map from pixmap, vertex format, blend cntl */
+    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 dst_format, dst_offset, dst_pitch;
+
+    I830GetDestFormat(pDstPicture, &dst_format);
+    dst_offset = exaGetPixmapOffset(pDst);
+    dst_pitch = exaGetPixmapPitch(pDst);
+    draw_coords[2][0] = pDst->drawable.x;
+    draw_coords[2][1] = pDst->drawable.y;
+    
+    I830DefCtxSetup(pScrn);
+
+    if (!I830TextureSetup(pSrcPicture, pSrc, 0))
+	I830FALLBACK("fail to setup src texture\n");
+    if (pMask != NULL) {
+	if (!I830TextureSetup(pMaskPicture, pMask, 1))
+		I830FALLBACK("fail to setup mask texture\n");
+    } else {
+	is_transform[1] = FALSE;
+	scale_units[1][0] = -1;
+	scale_units[1][1] = -1;
+    }
+
+    {
+
+	CARD32 cblend, ablend, blendctl, vf2;
+
+	BEGIN_LP_RING(22);
+	
+	/*color buffer*/
+	OUT_RING(_3DSTATE_BUF_INFO_CMD);
+	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch));
+	OUT_RING(BUF_3D_ADDR(dst_offset));
+	OUT_RING(MI_NOOP);
+	
+	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+	OUT_RING(dst_format);
+
+	/* defaults */
+	OUT_RING(_3DSTATE_DFLT_Z_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+	OUT_RING(0);
+	
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(3)|0);
+	OUT_RING((1<<S3_POINT_WIDTH_SHIFT) | (2<<S3_LINE_WIDTH_SHIFT) | S3_CULLMODE_NONE| S3_VERTEXHAS_XY);  
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(2)|0);
+	if (pMask)
+		vf2 = 2 << 12; /* 2 texture coord sets */
+	else
+		vf2 = 1 << 12;
+	vf2 |= (TEXCOORDFMT_2D << 16);
+	if (pMask)
+		vf2 |= (TEXCOORDFMT_2D << 18);
+	else
+		vf2 |= (TEXCOORDFMT_1D << 18);
+		
+	vf2 |= (TEXCOORDFMT_1D << 20);
+	vf2 |= (TEXCOORDFMT_1D << 22);
+	vf2 |= (TEXCOORDFMT_1D << 24);
+	vf2 |= (TEXCOORDFMT_1D << 26);
+	vf2 |= (TEXCOORDFMT_1D << 28);
+	vf2 |= (TEXCOORDFMT_1D << 30);
+	OUT_RING(vf2);
+
+	/* For (src In mask) operation */
+	/* IN operator: Multiply src by mask components or mask alpha.*/
+	/* TEXBLENDOP_MODULE: arg1*arg2 */
+	cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
+		 TB0C_OUTPUT_WRITE_CURRENT;  
+	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE | TB0A_OUTPUT_WRITE_CURRENT;
+	
+	cblend |= TB0C_ARG1_SEL_TEXEL0;
+	ablend |= TB0A_ARG1_SEL_TEXEL0;
+	if (pMask) {
+		if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8)
+			cblend |= TB0C_ARG2_SEL_TEXEL1;
+		else
+			cblend |= (TB0C_ARG2_SEL_TEXEL1 | TB0C_ARG2_REPLICATE_ALPHA);
+		ablend |= TB0A_ARG2_SEL_TEXEL1;
+	} else {
+		cblend |= TB0C_ARG2_SEL_ONE;
+		ablend |= TB0A_ARG2_SEL_ONE;		
+	}
+		
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_BLEND_STAGE(0)|1);
+	OUT_RING(cblend);
+	OUT_RING(ablend);
+	OUT_RING(0);
+
+	blendctl = I830GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0);
+	OUT_RING(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD |(blendctl<<4) |
+		S8_ENABLE_COLOR_BUFFER_WRITE);	
+	ADVANCE_LP_RING();
+    }
+
+#ifdef I830DEBUG
+   Error("try to sync to show any errors...");
+   I830Sync(pScrn);
+#endif
+
+    return TRUE;
+}
+
diff --git a/src/i830_reg.h b/src/i830_reg.h
index be12e76..ae68a2e 100644
--- a/src/i830_reg.h
+++ b/src/i830_reg.h
@@ -31,6 +31,23 @@
 
 #define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
 
+#define CMD_3D (0x3<<29)
+
+#define PRIM3D_INLINE		(CMD_3D | (0x1f<<24))
+#define PRIM3D_TRILIST		(0x0<<18)
+#define PRIM3D_TRISTRIP 	(0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE	(0x2<<18)
+#define PRIM3D_TRIFAN		(0x3<<18)
+#define PRIM3D_POLY		(0x4<<18)
+#define PRIM3D_LINELIST 	(0x5<<18)
+#define PRIM3D_LINESTRIP	(0x6<<18)
+#define PRIM3D_RECTLIST 	(0x7<<18)
+#define PRIM3D_POINTLIST	(0x8<<18)
+#define PRIM3D_DIB		(0x9<<18)
+#define PRIM3D_CLEAR_RECT	(0xa<<18)
+#define PRIM3D_ZONE_INIT	(0xd<<18)
+#define PRIM3D_MASK		(0x1f<<18)
+
 #define _3DSTATE_AA_CMD			(CMD_3D | (0x06<<24))
 #define AA_LINE_ECAAR_WIDTH_ENABLE	(1<<16)
 #define AA_LINE_ECAAR_WIDTH_0_5 	0
@@ -85,6 +102,8 @@
 #define COLR_BUF_RGB555 		(1<<8)
 #define COLR_BUF_RGB565 		(2<<8)
 #define COLR_BUF_ARGB8888		(3<<8)
+#define COLR_BUF_ARGB4444		(8<<8)
+#define COLR_BUF_ARGB1555		(9<<8)
 #define DEPTH_IS_Z			0
 #define DEPTH_IS_W			(1<<6)
 #define DEPTH_FRMT_16_FIXED		0
@@ -301,6 +320,7 @@
 
 /* _3DSTATE_MAP_COORD_SETS, p164 */
 #define _3DSTATE_MAP_COORD_SET_CMD	(CMD_3D|(0x1c<<24)|(0x01<<19))
+#define TEXCOORD_SET(n)			((n)<<16)
 #define ENABLE_TEXCOORD_PARAMS		(1<<15)
 #define TEXCOORDS_ARE_NORMAL		(1<<14)
 #define TEXCOORDS_ARE_IN_TEXELUNITS	0
@@ -329,6 +349,13 @@
 #define CUBE_NEGZ_ENABLE                (1<<1)
 #define CUBE_POSZ_ENABLE                (1<<0)
 
+#define _3DSTATE_MAP_INFO_CMD		(CMD_3D|(0x1d<<24)|(0x0<<16)|3)
+#define TEXMAP_INDEX(x)			((x)<<28)
+#define MAP_SURFACE_8BIT		(1<<24)
+#define MAP_SURFACE_16BIT		(2<<24)
+#define MAP_SURFACE_32BIT		(3<<24)
+#define MAP_FORMAT_2D			(0)
+#define MAP_FORMAT_3D_CUBE		(1<<11)
 
 /* _3DSTATE_MODES_1, p190 */
 #define _3DSTATE_MODES_1_CMD		(CMD_3D|(0x08<<24))
@@ -523,14 +550,57 @@
 
 /* Stipple command, carried over from the i810, apparently:
  */
-#define _3DSTATE_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define _3DSTATE_STIPPLE           (CMD_3D|(0x1d<<24)|(0x83<<16))
 #define ST1_ENABLE               (1<<16)
 #define ST1_MASK                 (0xffff)
 
-
-
-#define _3DSTATE_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
-#define LOAD_TEXTURE_MAP0                   (1<<11)
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_1	     (CMD_3D|(0x1d<<24)|(0x04<<16))
+#define I1_LOAD_S(n)			     (1<<((n)+4))
+#define S3_POINT_WIDTH_SHIFT		     23
+#define S3_LINE_WIDTH_SHIFT		     19
+#define S3_ALPHA_SHADE_MODE_SHIFT	     18
+#define S3_FOG_SHADE_MODE_SHIFT		     17
+#define S3_SPEC_SHADE_MODE_SHIFT	     16
+#define S3_COLOR_SHADE_MODE_SHIFT	     15
+#define S3_CULL_MODE_SHIFT		     13
+#define    S3_CULLMODE_BOTH		     (0)
+#define    S3_CULLMODE_NONE		     (1<<13)
+#define    S3_CULLMODE_CW		     (2<<13)
+#define    S3_CULLMODE_CCW		     (3<<13)
+#define S3_POINT_WIDTH_PRESENT		     (1<<12)
+#define S3_SPEC_FOG_PRESENT		     (1<<11)
+#define S3_DIFFUSE_PRESENT		     (1<<10)
+#define S3_DEPTH_OFFSET_PRESENT		     (1<<9)
+#define S3_POSITION_SHIFT		     6
+#define    S3_VERTEXHAS_XYZ		     (1<<6)
+#define    S3_VERTEXHAS_XYZW		     (2<<6)
+#define    S3_VERTEXHAS_XY		     (3<<6)
+#define    S3_VERTEXHAS_XYW		     (4<<6)
+#define S3_ENABLE_SPEC_ADD		     (1<<5)
+#define S3_ENABLE_FOG			     (1<<4)
+#define S3_ENABLE_LOCAL_DEPTH_BIAS	     (1<<3)
+#define S3_ENABLE_SPRITE_POINT		     (1<<1)
+#define S3_ENABLE_ANTIALIASING		     1
+#define S8_ENABLE_ALPHA_TEST		     (1<<31)
+#define S8_ALPHA_TEST_FUNC_SHIFT	     28
+#define S8_ALPHA_REFVALUE_SHIFT		     20
+#define S8_ENABLE_DEPTH_TEST		     (1<<19)
+#define S8_DEPTH_TEST_FUNC_SHIFT	     16
+#define S8_ENABLE_COLOR_BLEND		     (1<<15)
+#define S8_COLOR_BLEND_FUNC_SHIFT	     12
+#define    S8_BLENDFUNC_ADD		     (0)
+#define    S8_BLENDFUNC_SUB		     (1<<12)
+#define    S8_BLENDFUNC_RVRSE_SUB	     (2<<12)
+#define    S8_BLENDFUNC_MIN		     (3<<12)
+#define    S8_BLENDFUNC_MAX			     (4<<12)
+#define S8_SRC_BLEND_FACTOR_SHIFT	     8
+#define S8_DST_BLEND_FACTOR_SHIFT	     4
+#define S8_ENABLE_DEPTH_BUFFER_WRITE	     (1<<3)
+#define S8_ENABLE_COLOR_BUFFER_WRITE	     (1<<2)
+
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_2      (CMD_3D|(0x1d<<24)|(0x03<<16))
+#define LOAD_TEXTURE_MAP(x)                   (1<<((x)+11))
+#define LOAD_TEXTURE_BLEND_STAGE(x)	      (1<<((x)+7))
 #define LOAD_GLOBAL_COLOR_FACTOR            (1<<6)
 
 #define TM0S0_ADDRESS_MASK              0xfffffffc
@@ -591,6 +661,8 @@
 #define TM0S2_CUBE_FACE_ENA_SHIFT       15
 #define TM0S2_CUBE_FACE_ENA_MASK        (1<<15)
 #define TM0S2_MAP_FORMAT                (1<<14)
+#define    TM0S2_MAP_2D			(0<<14)
+#define    TM0S2_MAP_3D_CUBE		(1<<14)
 #define TM0S2_VERTICAL_LINE_STRIDE      (1<<13)
 #define TM0S2_VERITCAL_LINE_STRIDE_OFF  (1<<12)
 #define TM0S2_OUTPUT_CHAN_SHIFT         10
@@ -634,4 +706,23 @@
 
 #define FLUSH_MAP_CACHE    (1<<0)
 
+#define _3DSTATE_MAP_FILTER_CMD    (CMD_3D|(0x1c<<24)|(0x02<<19))
+#define FILTER_TEXMAP_INDEX(x) ((x) << 16)
+#define MAG_MODE_FILTER_ENABLE (1 << 5) 
+#define MIN_MODE_FILTER_ENABLE (1 << 2) 
+#define MAG_MAPFILTER_NEAREST (0 << 3)
+#define MAG_MAPFILTER_LINEAR  (1 << 3)
+#define MAG_MAPFILTER_ANISOTROPIC (2 << 3)
+#define MIN_MAPFILTER_NEAREST (0)
+#define MIN_MAPFILTER_LINEAR  (1)
+#define MIN_MAPFILTER_ANISOTROPIC (2)
+#define ENABLE_KEYS	(1<<15)
+#define DISABLE_COLOR_KEY	0 
+#define DISABLE_CHROMA_KEY	0
+#define DISABLE_KILL_PIXEL	0
+#define ENABLE_MIP_MODE_FILTER	(1 << 9)
+#define MIPFILTER_NONE		0
+#define MIPFILTER_NEAREST	1
+#define MIPFILTER_LINEAR	3
+
 #endif
diff --git a/src/i915_exa_render.c b/src/i915_exa_render.c
new file mode 100644
index 0000000..68c929e
--- /dev/null
+++ b/src/i915_exa_render.c
@@ -0,0 +1,553 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "i915_reg.h"
+
+#ifdef I830DEBUG
+#define DEBUG_I830FALLBACK 1
+#endif
+
+#ifdef DEBUG_I830FALLBACK
+#define I830FALLBACK(s, arg...)				\
+do {							\
+	DPRINTF(PFX, "EXA fallback: " s "\n", ##arg); 	\
+	return FALSE;					\
+} while(0)
+#else
+#define I830FALLBACK(s, arg...) 			\
+do { 							\
+	return FALSE;					\
+} while(0) 
+#endif
+
+extern float scale_units[2][2];
+extern int draw_coords[3][2];
+extern Bool is_transform[2];
+extern PictTransform *transform[2];
+
+struct formatinfo {
+    int fmt;
+    CARD32 card_fmt;
+};
+
+struct blendinfo {
+    Bool dst_alpha;
+    Bool src_alpha;
+    CARD32 blend_cntl;
+};
+
+extern Bool
+I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture);
+
+extern Bool
+I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
+
+/* copy from Eric's texture-video branch, move to header.. */
+#define OUT_DCL(type, nr) do {                                          \
+   CARD32 chans = 0;                                                    \
+   if (REG_TYPE_##type == REG_TYPE_T)                                   \
+      chans = D0_CHANNEL_ALL;                                           \
+   else if (REG_TYPE_##type != REG_TYPE_S)                              \
+      FatalError("wrong reg type %d to declare\n", REG_TYPE_##type);    \
+   OUT_RING(D0_DCL |                                                    \
+            (REG_TYPE_##type << D0_TYPE_SHIFT) | (nr << D0_NR_SHIFT) |  \
+            chans);                                                     \
+   OUT_RING(0x00000000);                                                \
+   OUT_RING(0x00000000);                                                \
+} while (0)
+
+#define OUT_TEXLD(dest_type, dest_nr, sampler_nr, addr_type, addr_nr)   \
+do {                                                                    \
+      OUT_RING(T0_TEXLD |                                               \
+               (REG_TYPE_##dest_type << T0_DEST_TYPE_SHIFT) |           \
+               (dest_nr << T0_DEST_NR_SHIFT) |                          \
+               (sampler_nr << T0_SAMPLER_NR_SHIFT));                    \
+      OUT_RING((REG_TYPE_##addr_type << T1_ADDRESS_REG_TYPE_SHIFT) |    \
+               (addr_nr << T1_ADDRESS_REG_NR_SHIFT));                   \
+      OUT_RING(0x00000000);                                             \
+} while (0)
+
+/* XXX: It seems that offset of 915's blendfactor in Load_immediate_1
+   is _different_ with i830, so I should just define plain value
+   and use it with shift bits*/
+
+#define I915_SRC_BLENDFACTOR_ZERO 		(1 << 8)
+#define I915_SRC_BLENDFACTOR_ONE 		(2 << 8)
+#define I915_SRC_BLENDFACTOR_SRC_COLOR		(3 << 8)
+#define I915_SRC_BLENDFACTOR_INV_SRC_COLOR	(4 << 8)
+#define I915_SRC_BLENDFACTOR_SRC_ALPHA		(5 << 8)
+#define I915_SRC_BLENDFACTOR_INV_SRC_ALPHA	(6 << 8)
+#define I915_SRC_BLENDFACTOR_DST_ALPHA		(7 << 8)
+#define I915_SRC_BLENDFACTOR_INV_DST_ALPHA	(8 << 8)
+#define I915_SRC_BLENDFACTOR_DST_COLOR		(9 << 8)
+#define I915_SRC_BLENDFACTOR_INV_DST_COLOR	(0xa << 8)
+#define I915_SRC_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 8)
+#define I915_SRC_BLENDFACTOR_CONST_COLOR	(0xc << 8)
+#define I915_SRC_BLENDFACTOR_INV_CONST_COLOR	(0xd << 8)
+#define I915_SRC_BLENDFACTOR_CONST_ALPHA	(0xe << 8)
+#define I915_SRC_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 8)
+#define I915_SRC_BLENDFACTOR_MASK		(0xf << 8)
+
+#define I915_DST_BLENDFACTOR_ZERO 		(1 << 4)
+#define I915_DST_BLENDFACTOR_ONE 		(2 << 4)
+#define I915_DST_BLENDFACTOR_SRC_COLOR		(3 << 4)
+#define I915_DST_BLENDFACTOR_INV_SRC_COLOR	(4 << 4)
+#define I915_DST_BLENDFACTOR_SRC_ALPHA		(5 << 4)
+#define I915_DST_BLENDFACTOR_INV_SRC_ALPHA	(6 << 4)
+#define I915_DST_BLENDFACTOR_DST_ALPHA		(7 << 4)
+#define I915_DST_BLENDFACTOR_INV_DST_ALPHA	(8 << 4)
+#define I915_DST_BLENDFACTOR_DST_COLOR		(9 << 4)
+#define I915_DST_BLENDFACTOR_INV_DST_COLOR	(0xa << 4)
+#define I915_DST_BLENDFACTOR_SRC_ALPHA_SATURATE (0xb << 4)
+#define I915_DST_BLENDFACTOR_CONST_COLOR	(0xc << 4)
+#define I915_DST_BLENDFACTOR_INV_CONST_COLOR	(0xd << 4)
+#define I915_DST_BLENDFACTOR_CONST_ALPHA	(0xe << 4)
+#define I915_DST_BLENDFACTOR_INV_CONST_ALPHA	(0xf << 4)
+#define I915_DST_BLENDFACTOR_MASK		(0xf << 4)
+
+static struct blendinfo I915BlendOp[] = { 
+    /* Clear */
+    {0, 0, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_ZERO},
+    /* Src */
+    {0, 0, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_ZERO},
+    /* Dst */
+    {0, 0, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_ONE},
+    /* Over */
+    {0, 1, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* OverReverse */
+    {1, 0, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_ONE},
+    /* In */
+    {1, 0, I915_SRC_BLENDFACTOR_DST_ALPHA     | I915_DST_BLENDFACTOR_ZERO},
+    /* InReverse */
+    {0, 1, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_SRC_ALPHA},
+    /* Out */
+    {1, 0, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_ZERO},
+    /* OutReverse */
+    {0, 1, I915_SRC_BLENDFACTOR_ZERO           | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Atop */
+    {1, 1, I915_SRC_BLENDFACTOR_DST_ALPHA     | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* AtopReverse */
+    {1, 1, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_SRC_ALPHA},
+    /* Xor */
+    {1, 1, I915_SRC_BLENDFACTOR_INV_DST_ALPHA | I915_DST_BLENDFACTOR_INV_SRC_ALPHA},
+    /* Add */
+    {0, 0, I915_SRC_BLENDFACTOR_ONE            | I915_DST_BLENDFACTOR_ONE},
+};
+
+static struct formatinfo I915TexFormats[] = {
+        {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
+        {PICT_x8r8g8b8, MT_32BIT_XRGB8888 },
+        {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
+        {PICT_x8b8g8r8, MT_32BIT_XBGR8888 },
+        {PICT_r5g6b5,   MT_16BIT_RGB565   },
+        {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
+        {PICT_a8,       MT_8BIT_I8 	  },
+};
+
+static CARD32 I915GetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format)
+{
+    CARD32 sblend, dblend;
+
+    sblend = I915BlendOp[op].blend_cntl & I915_SRC_BLENDFACTOR_MASK;
+    dblend = I915BlendOp[op].blend_cntl & I915_DST_BLENDFACTOR_MASK;
+
+    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
+     * it as always 1.
+     */
+    if (PICT_FORMAT_A(dst_format) == 0 && I915BlendOp[op].dst_alpha) {
+        if (sblend == I915_SRC_BLENDFACTOR_DST_ALPHA)
+            sblend = I915_SRC_BLENDFACTOR_ONE;
+        else if (sblend == I915_SRC_BLENDFACTOR_INV_DST_ALPHA)
+            sblend = I915_SRC_BLENDFACTOR_ZERO;
+    }
+
+    /* If the source alpha is being used, then we should only be in a case where
+     * the source blend factor is 0, and the source blend value is the mask
+     * channels multiplied by the source picture's alpha.
+     */
+    if (pMask && pMask->componentAlpha && I915BlendOp[op].src_alpha) {
+        if (dblend == I915_DST_BLENDFACTOR_SRC_ALPHA) {
+            dblend = I915_DST_BLENDFACTOR_SRC_COLOR;
+        } else if (dblend == I915_DST_BLENDFACTOR_INV_SRC_ALPHA) {
+            dblend = I915_DST_BLENDFACTOR_INV_SRC_COLOR;
+        }
+    }
+
+    return sblend | dblend;
+}
+
+static Bool I915GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format)
+{
+    switch (pDstPicture->format) {
+    case PICT_a8r8g8b8:
+    case PICT_x8r8g8b8:
+        *dst_format = COLR_BUF_ARGB8888;
+        break;
+    case PICT_r5g6b5:
+        *dst_format = COLR_BUF_RGB565;
+        break;
+    case PICT_a1r5g5b5:
+    case PICT_x1r5g5b5:
+        *dst_format = COLR_BUF_ARGB1555;
+        break;
+    case PICT_a8:
+        *dst_format = COLR_BUF_8BIT;
+        break;
+    case PICT_a4r4g4b4:
+    case PICT_x4r4g4b4:
+	*dst_format = COLR_BUF_ARGB4444;
+	break;
+    default:
+        I830FALLBACK("Unsupported dest format 0x%x\n",
+                        (int)pDstPicture->format);
+    }
+
+    return TRUE;
+}
+
+static Bool I915CheckCompositeTexture(PicturePtr pPict, int unit)
+{
+    int w = pPict->pDrawable->width;
+    int h = pPict->pDrawable->height;
+    int i;
+                                                                                                                                                            
+    if ((w > 0x7ff) || (h > 0x7ff))
+        I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
+
+    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++)
+    {
+        if (I915TexFormats[i].fmt == pPict->format)
+            break;
+    }
+    if (i == sizeof(I915TexFormats) / sizeof(I915TexFormats[0]))
+        I830FALLBACK("Unsupported picture format 0x%x\n",
+                         (int)pPict->format);
+
+    /* FIXME: fix repeat support */
+    if (pPict->repeat && ((w&(w-1)) != 0) && ((h&(h-1)) != 0))
+	I830FALLBACK("repeat non log2 aligned!\n");
+
+    if (pPict->filter != PictFilterNearest &&
+        pPict->filter != PictFilterBilinear)
+        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
+
+    return TRUE;
+}
+
+Bool
+I915EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		      PicturePtr pDstPicture)
+{
+    CARD32 tmp1;
+    
+    /* Check for unsupported compositing operations. */
+    if (op >= sizeof(I915BlendOp) / sizeof(I915BlendOp[0]))
+        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
+                                                                                                                                                            
+    if (pMaskPicture != NULL && pMaskPicture->componentAlpha) {
+        /* Check if it's component alpha that relies on a source alpha and on
+         * the source value.  We can only get one of those into the single
+         * source value that we get to blend with.
+         */
+        if (I915BlendOp[op].src_alpha &&
+            (I915BlendOp[op].blend_cntl & I915_SRC_BLENDFACTOR_MASK) !=
+             I915_SRC_BLENDFACTOR_ZERO)
+            	I830FALLBACK("Component alpha not supported with source "
+                            "alpha and source value blending.\n");
+    }
+
+    if (!I915CheckCompositeTexture(pSrcPicture, 0))
+        I830FALLBACK("Check Src picture texture\n");
+    if (pMaskPicture != NULL && !I915CheckCompositeTexture(pMaskPicture, 1))
+        I830FALLBACK("Check Mask picture texture\n");
+
+    if (!I915GetDestFormat(pDstPicture, &tmp1)) 
+	I830FALLBACK("Get Color buffer format\n");
+
+    return TRUE;
+}
+
+static Bool
+I915TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 format, offset, pitch, filter;
+    int w, h, i;
+    CARD32 wrap_mode = TEXCOORDMODE_CLAMP_EDGE; 
+
+    offset = exaGetPixmapOffset(pPix);
+    pitch = exaGetPixmapPitch(pPix);
+    w = pPict->pDrawable->width;
+    h = pPict->pDrawable->height;
+    scale_units[unit][0] = pPix->drawable.width;
+    scale_units[unit][1] = pPix->drawable.height;
+    draw_coords[unit][0] = pPix->drawable.x;
+    draw_coords[unit][1] = pPix->drawable.y;
+
+    for (i = 0; i < sizeof(I915TexFormats) / sizeof(I915TexFormats[0]); i++) {
+        if (I915TexFormats[i].fmt == pPict->format)
+	    break;
+    }
+    if ( i == sizeof(I915TexFormats)/ sizeof(I915TexFormats[0]) )
+	I830FALLBACK("unknown texture format\n");
+    format = I915TexFormats[i].card_fmt;
+
+    if (pPict->repeat) 
+	wrap_mode = TEXCOORDMODE_WRAP; /* XXX:correct ? */
+    
+    switch (pPict->filter) {
+    case PictFilterNearest:
+        filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) | 
+			(FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+        break;
+    case PictFilterBilinear:
+        filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | 
+			(FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
+        break;
+    default:
+	filter = 0;
+        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
+    }
+
+    {
+	CARD32 ms3;
+	if (pI830->cpp == 1)
+		format |= MAPSURF_8BIT;
+	else if (pI830->cpp == 2)
+		format |= MAPSURF_16BIT;
+	else
+		format |= MAPSURF_32BIT;
+
+	BEGIN_LP_RING(6);
+	OUT_RING(_3DSTATE_MAP_STATE | (3 * (1 << unit)));
+	OUT_RING(1<<unit);
+	OUT_RING(offset&MS2_ADDRESS_MASK);
+	ms3 = (pPix->drawable.height << MS3_HEIGHT_SHIFT) | 
+		(pPix->drawable.width << MS3_WIDTH_SHIFT) | format;
+	if (!pI830->disableTiling)
+		ms3 |= MS3_USE_FENCE_REGS;
+	OUT_RING(ms3); 
+	OUT_RING(pitch<<MS4_PITCH_SHIFT);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+     }
+
+     {
+	CARD32 ss2, ss3;
+	BEGIN_LP_RING(6);
+	/* max & min mip level ? or base mip level? */
+
+	OUT_RING(_3DSTATE_SAMPLER_STATE | (3*(1<<unit)));
+	OUT_RING(1<<unit);
+	ss2 = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT);
+	ss2 |= filter;
+	OUT_RING(ss2);
+	/* repeat? */
+	ss3 = TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT;
+	ss3 |= (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT);
+	ss3 |= SS3_NORMALIZED_COORDS;
+	ss3 |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
+	OUT_RING(ss3);
+	OUT_RING(0x00000000); /* default color */
+	OUT_RING(0);
+
+	ADVANCE_LP_RING();
+    }
+
+    if (pPict->transform != 0) {
+        is_transform[unit] = TRUE;
+        transform[unit] = pPict->transform;
+    } else {
+        is_transform[unit] = FALSE;
+    }
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+	
+    return TRUE;
+}
+
+static void
+I915DefCtxSetup(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    BEGIN_LP_RING(2);
+    /* set default texture binding, may be in prepare better */
+    OUT_RING(_3DSTATE_COORD_SET_BINDINGS | CSB_TCB(0,0) | CSB_TCB(1,1) |
+	CSB_TCB(2,2) | CSB_TCB(3,3) | CSB_TCB(4,4) | CSB_TCB(5,5) |
+	CSB_TCB(6,6) | CSB_TCB(7,7));
+    OUT_RING(0);
+    ADVANCE_LP_RING();
+}
+
+Bool
+I915EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+			PicturePtr pMaskPicture, PicturePtr pDstPicture,
+			PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
+    I830Ptr pI830 = I830PTR(pScrn);
+    CARD32 dst_format, dst_offset, dst_pitch;
+    CARD32 blendctl;
+
+ErrorF("i915 prepareComposite\n");
+
+    I915GetDestFormat(pDstPicture, &dst_format);
+    dst_offset = exaGetPixmapOffset(pDst);
+    dst_pitch = exaGetPixmapPitch(pDst);
+    draw_coords[2][0] = pDst->drawable.x;
+    draw_coords[2][1] = pDst->drawable.y;
+    
+    I915DefCtxSetup(pScrn);
+
+    if (!I915TextureSetup(pSrcPicture, pSrc, 0))
+	I830FALLBACK("fail to setup src texture\n");
+    if (pMask != NULL) {
+	if (!I915TextureSetup(pMaskPicture, pMask, 1))
+		I830FALLBACK("fail to setup mask texture\n");
+    } else {
+	is_transform[1] = FALSE;
+	scale_units[1][0] = -1;
+	scale_units[1][1] = -1;
+    }
+
+    {
+	CARD32 ss2;
+	BEGIN_LP_RING(24);
+	/*color buffer*/
+	OUT_RING(_3DSTATE_BUF_INFO_CMD);
+	OUT_RING(BUF_3D_ID_COLOR_BACK| BUF_3D_PITCH(dst_pitch)); /* fence, tile? */
+	OUT_RING(BUF_3D_ADDR(dst_offset));
+	OUT_RING(MI_NOOP);
+	
+	OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+	OUT_RING(dst_format);
+
+	/* XXX: defaults */
+	OUT_RING(_3DSTATE_DFLT_Z_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+	OUT_RING(0);
+
+	OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+	OUT_RING(0);
+	
+	/* XXX:S3? define vertex format with tex coord sets number*/
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1|I1_LOAD_S(2)|I1_LOAD_S(3)|
+		I1_LOAD_S(4)|1);
+	ss2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D);
+	if (pMask)
+		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D);
+	else
+		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT);
+	ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
+	OUT_RING(ss2);
+	OUT_RING(0x00000000); /*XXX: does ss3 needed? */
+	OUT_RING((1<<S4_POINT_WIDTH_SHIFT)|S4_LINE_WIDTH_ONE| 
+		S4_CULLMODE_NONE| S4_VFMT_XY);  
+
+	/* issue a flush */
+	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+	OUT_RING(0);
+
+	/* draw rect is unconditional */
+	OUT_RING(_3DSTATE_DRAW_RECT_CMD);
+	OUT_RING(0x00000000);
+	OUT_RING(0x00000000);  /* ymin, xmin*/
+	OUT_RING(DRAW_YMAX(pScrn->virtualY-1) | DRAW_XMAX(pScrn->virtualX-1));
+	OUT_RING(0x00000000);  /* yorig, xorig (relate to color buffer?)*/
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+    }
+
+	/* For (src In mask) operation */
+	/* IN operator: Multiply src by mask components or mask alpha.*/
+	/* TEXBLENDOP_MODULE: arg1*arg2 */
+
+	/* LOAD_IMMEDIATE_1 ss6 ??*/
+
+	/****
+	   shader program prototype:
+		dcl t0.xy
+		dcl t1.xy
+		dcl_2d s0   
+		dcl_2d s1
+		texld t0, s0
+		texld t1, s1
+		mul oC, t0, t1 ()
+	***/
+    if (!pMask) {
+	BEGIN_LP_RING(1+3+3+3);
+	OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |(3*3-1));
+	OUT_DCL(S, 0);
+	OUT_DCL(T, 0);
+	OUT_TEXLD(OC, 0, 0, T, 0);
+	ADVANCE_LP_RING();
+    } else {
+	BEGIN_LP_RING(1+3*6+3);
+	OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |(3*7-1));
+	OUT_DCL(S, 0);
+	OUT_DCL(S, 1);
+	OUT_DCL(T, 0);
+	OUT_DCL(T, 1);
+	OUT_TEXLD(R, 0, 0, T, 0);
+	OUT_TEXLD(R, 1, 1, T, 1);
+	if (pMaskPicture->componentAlpha && pDstPicture->format != PICT_a8) {
+		/* then just mul */
+		OUT_RING(A0_MUL | (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) | 
+			(0 << A0_DEST_NR_SHIFT) | A0_DEST_CHANNEL_ALL | 
+			(REG_TYPE_R << A0_SRC0_TYPE_SHIFT) | (0 << A0_SRC0_NR_SHIFT));
+		OUT_RING((SRC_X << A1_SRC0_CHANNEL_X_SHIFT)|(SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT)|
+			(SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT)|(SRC_W << A1_SRC0_CHANNEL_W_SHIFT)|
+			(REG_TYPE_R << A1_SRC1_TYPE_SHIFT) | (1 << A1_SRC1_NR_SHIFT) |
+			(SRC_X << A1_SRC1_CHANNEL_X_SHIFT) | (SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT));
+		OUT_RING((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) | (SRC_W << A2_SRC1_CHANNEL_W_SHIFT));
+	} else {
+		/* we should duplicate R1's w for all channel, Arithemic can choose channel to use! */
+		OUT_RING(A0_MUL | (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
+			(0 << A0_DEST_NR_SHIFT) | A0_DEST_CHANNEL_ALL |
+			(REG_TYPE_R << A0_SRC0_TYPE_SHIFT) | (0 << A0_SRC0_NR_SHIFT));
+		OUT_RING((SRC_X << A1_SRC0_CHANNEL_X_SHIFT) | (SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT) |
+			(SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT) | (SRC_W << A1_SRC0_CHANNEL_W_SHIFT) |
+			(REG_TYPE_R << A1_SRC1_TYPE_SHIFT) | (1 << A1_SRC1_NR_SHIFT) |
+			(SRC_W << A1_SRC1_CHANNEL_X_SHIFT) | (SRC_W << A1_SRC1_CHANNEL_Y_SHIFT));
+		OUT_RING((SRC_W << A2_SRC1_CHANNEL_Z_SHIFT) | (SRC_W << A2_SRC1_CHANNEL_W_SHIFT));
+	}
+	ADVANCE_LP_RING();
+    }
+		
+    {
+	CARD32 ss6;
+	blendctl = I915GetBlendCntl(op, pMaskPicture, pDstPicture->format);
+
+	BEGIN_LP_RING(2);
+	OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
+	ss6 = S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE;
+	OUT_RING(ss6 | (0 << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
+	ADVANCE_LP_RING();
+    }
+
+#ifdef I830DEBUG
+    ErrorF("try to sync to show any errors...");
+    I830Sync(pScrn);
+#endif
+
+    return TRUE;
+}
diff --git a/src/i915_reg.h b/src/i915_reg.h
index 886ae81..e2d7b9d 100644
--- a/src/i915_reg.h
+++ b/src/i915_reg.h
@@ -161,6 +161,9 @@
 #define COLR_BUF_RGB555 		(1<<8)
 #define COLR_BUF_RGB565 		(2<<8)
 #define COLR_BUF_ARGB8888		(3<<8)
+#define COLR_BUF_ARGB4444		(8<<8)
+#define COLR_BUF_ARGB1555		(9<<8)
+#define COLR_BUF_ARGB2AAA		(0xa<<8)
 #define DEPTH_FRMT_16_FIXED		0
 #define DEPTH_FRMT_16_FLOAT		(1<<2)
 #define DEPTH_FRMT_24_FIXED_8_OTHER	(2<<2)



More information about the xorg-commit mailing list