xf86-video-ati: Branch 'master'

Alex Deucher agd5f at kemper.freedesktop.org
Sat Feb 23 16:08:57 PST 2008


 src/Makefile.am                  |    1 
 src/radeon.h                     |    2 
 src/radeon_commonfuncs.c         |   33 --
 src/radeon_exa.c                 |    2 
 src/radeon_exa_render.c          |   38 ++
 src/radeon_reg.h                 |    6 
 src/radeon_textured_video.c      |  596 +++++++++++++++++++++++++++++++++++++++
 src/radeon_textured_videofuncs.c |  472 ++++++++++++++++++++++++++++++
 src/radeon_video.c               |   89 +++--
 src/radeon_video.h               |   31 +-
 10 files changed, 1193 insertions(+), 77 deletions(-)

New commits:
commit d9be9f34b0d3313e7b22b2a8bb0a8924ad3116bf
Author: Alex Deucher <alex at samba.(none)>
Date:   Sat Feb 23 19:06:30 2008 -0500

    RADEON: add textured video support for r1xx-r4xx radeons
    
    Based on the kdrive ati video code by Eric Anholt.
    R3xx/R4xx still have some clipping issues in certain situations

diff --git a/src/Makefile.am b/src/Makefile.am
index a146df3..e0799a5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -114,6 +114,7 @@ radeon_drv_la_SOURCES = \
 	radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \
 	radeon_vip.c radeon_misc.c radeon_probe.c \
 	legacy_crtc.c legacy_output.c \
+	radeon_textured_video.c \
 	radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \
 	$(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \
 	$(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c
diff --git a/src/radeon.h b/src/radeon.h
index 7d63f28..aba3c0f 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -184,6 +184,8 @@ typedef enum {
 				   * for something else.
 				   */
 
+#define xFixedToFloat(f) (((float) (f)) / 65536)
+
 #define RADEON_LOGLEVEL_DEBUG 4
 
 /* for Xv, outputs */
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index 8c4b598..629336f 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -91,39 +91,6 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 	OUT_ACCEL_REG(R300_GA_OFFSET, 0x0);
 	FINISH_ACCEL();
 
-	BEGIN_ACCEL(26);
-	OUT_ACCEL_REG(R300_VAP_CNTL_STATUS, 0x0);
-	OUT_ACCEL_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0);
-	OUT_ACCEL_REG(R300_VAP_CNTL, 0x300456);
-	OUT_ACCEL_REG(R300_VAP_VTE_CNTL, 0x300);
-	OUT_ACCEL_REG(R300_VAP_PSC_SGN_NORM_CNTL, 0x0);
-	OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_0, 0x4a014001);
-	OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_1, 0x6b01);
-	OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0, 0xf688f688);
-	OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_1, 0xf688);
-	OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_0, 0x100400);
-	OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_1, 0x1);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f00203);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10001);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f02203);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10141);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141);
-	OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141);
-
-	OUT_ACCEL_REG(R300_VAP_PVS_FLOW_CNTL_OPC, 0x0);
-	OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_0, 0x1);
-	OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_1, (0x2 << 3) | 0x2);
-
-	OUT_ACCEL_REG(R300_VAP_GB_VERT_CLIP_ADJ, 0x3f800000);
-	OUT_ACCEL_REG(R300_VAP_GB_VERT_DISC_ADJ, 0x3f800000);
-	OUT_ACCEL_REG(R300_VAP_GB_HORZ_CLIP_ADJ, 0x3f800000);
-	OUT_ACCEL_REG(R300_VAP_GB_HORZ_DISC_ADJ, 0x3f800000);
-	OUT_ACCEL_REG(R300_VAP_CLIP_CNTL, 0x10000);
-	FINISH_ACCEL();
-
 	BEGIN_ACCEL(7);
 	OUT_ACCEL_REG(R300_SU_TEX_WRAP, 0x0);
 	OUT_ACCEL_REG(R300_SU_POLY_OFFSET_ENABLE, 0x0);
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 3b0c734..4ea451d 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -120,8 +120,6 @@ RADEONPow2(int num)
     return pot;
 }
 
-
-
 static __inline__ CARD32 F_TO_DW(float val)
 {
     union {
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index da1fa47..9b23cdc 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -975,6 +975,40 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 
     RADEON_SWITCH_TO_3D();
 
+    /* setup the vertex shader */
+    BEGIN_ACCEL(26);
+    OUT_ACCEL_REG(R300_VAP_CNTL_STATUS, 0x0);
+    OUT_ACCEL_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0);
+    OUT_ACCEL_REG(R300_VAP_CNTL, 0x300456);
+    OUT_ACCEL_REG(R300_VAP_VTE_CNTL, 0x300);
+    OUT_ACCEL_REG(R300_VAP_PSC_SGN_NORM_CNTL, 0x0);
+    OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_0, 0x4a014001);
+    OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_1, 0x6b01);
+    OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0, 0xf688f688);
+    OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_1, 0xf688);
+    OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_0, 0x100400);
+    OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_1, 0x1);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f00203);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10001);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f02203);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10141);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141);
+    OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141);
+
+    OUT_ACCEL_REG(R300_VAP_PVS_FLOW_CNTL_OPC, 0x0);
+    OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_0, 0x1);
+    OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_1, (0x2 << 3) | 0x2);
+
+    OUT_ACCEL_REG(R300_VAP_GB_VERT_CLIP_ADJ, 0x3f800000);
+    OUT_ACCEL_REG(R300_VAP_GB_VERT_DISC_ADJ, 0x3f800000);
+    OUT_ACCEL_REG(R300_VAP_GB_HORZ_CLIP_ADJ, 0x3f800000);
+    OUT_ACCEL_REG(R300_VAP_GB_HORZ_DISC_ADJ, 0x3f800000);
+    OUT_ACCEL_REG(R300_VAP_CLIP_CNTL, 0x10000);
+    FINISH_ACCEL();
+
     /* setup pixel shader */
     BEGIN_ACCEL(12);
     OUT_ACCEL_REG(R300_US_CONFIG, 0x8);
@@ -1094,8 +1128,6 @@ static inline void transformPoint(PictTransform *transform, xPointFixed *point)
 }
 #endif
 
-#define xFixedToFloat(f) (((float) (f)) / 65536)
-
 static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst,
 				     int srcX, int srcY,
 				     int maskX, int maskY,
@@ -1223,7 +1255,6 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst,
     LEAVE_DRAW(0);
 }
 #undef VTX_OUT
-#undef VTX_OUT4
 
 #ifdef ONLY_ONCE
 static void RadeonDoneComposite(PixmapPtr pDst)
@@ -1234,3 +1265,4 @@ static void RadeonDoneComposite(PixmapPtr pDst)
 #endif /* ONLY_ONCE */
 
 #undef ONLY_ONCE
+#undef FUNC_NAME
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 88cf147..3702ee4 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -3901,6 +3901,8 @@
 #	define R300_TX_FORMAT_A8R8G8B8	    	    0x13     /* no swizzle */
 #	define R300_TX_FORMAT_B8G8_B8G8	    	    0x14     /* no swizzle */
 #	define R300_TX_FORMAT_G8R8_G8B8	    	    0x15     /* no swizzle */
+#	define R300_TX_FORMAT_VYUY422	    	    0x14     /* no swizzle */
+#	define R300_TX_FORMAT_YVYU422	    	    0x15     /* no swizzle */
 #	define R300_TX_FORMAT_X24_Y8	    	    0x1e
 #	define R300_TX_FORMAT_X32	    	    0x1e
 	/* Floating point formats */
@@ -3945,6 +3947,10 @@
 		| (R300_TX_FORMAT_##FMT)				\
 		)
 
+#       define R300_TX_FORMAT_YUV_TO_RGB_CLAMP         (1 << 22)
+#       define R300_TX_FORMAT_YUV_TO_RGB_NO_CLAMP      (2 << 22)
+#       define R300_TX_FORMAT_APPLE_YUV                (1 << 24)
+
 #define R300_TX_FORMAT2_0				0x4500
 #define R300_TX_OFFSET_0				0x4540
 #       define R300_ENDIAN_SWAP_16_BIT                  (1 << 0)
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
new file mode 100644
index 0000000..8a14024
--- /dev/null
+++ b/src/radeon_textured_video.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright 2008 Alex Deucher
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *
+ * Based on radeon_exa_render.c and kdrive ati_video.c by Eric Anholt, et al.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_video.h"
+
+#include <X11/extensions/Xv.h>
+#include "fourcc.h"
+
+#define IMAGE_MAX_WIDTH		2048
+#define IMAGE_MAX_HEIGHT	2048
+
+static Bool
+RADEONTilingEnabled(ScrnInfoPtr pScrn, PixmapPtr pPix)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
+#ifdef USE_EXA
+    if (info->useEXA) {
+	if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0)
+	    return TRUE;
+	else
+	    return FALSE;
+    } else
+#endif
+	{
+	    if (info->tilingEnabled)
+		return TRUE;
+	    else
+		return FALSE;
+	}
+}
+
+static __inline__ int
+RADEONPow2(int num)
+{
+    int pot = 2;
+
+    if (num <= 2)
+	return num;
+
+    while (pot < num) {
+	pot *= 2;
+    }
+
+    return pot;
+}
+
+static __inline__ CARD32 F_TO_DW(float val)
+{
+    union {
+	float f;
+	CARD32 l;
+    } tmp;
+    tmp.f = val;
+    return tmp.l;
+}
+
+#define ACCEL_MMIO
+#define VIDEO_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
+#define BEGIN_VIDEO(n)		RADEONWaitForFifo(pScrn, (n))
+#define OUT_VIDEO_REG(reg, val)	OUTREG(reg, val)
+#define OUT_VIDEO_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
+#define FINISH_VIDEO()
+
+#include "radeon_textured_videofuncs.c"
+
+#undef ACCEL_MMIO
+#undef VIDEO_PREAMBLE
+#undef BEGIN_VIDEO
+#undef OUT_VIDEO_REG
+#undef FINISH_VIDEO
+
+#ifdef XF86DRI
+
+#define ACCEL_CP
+#define VIDEO_PREAMBLE()						\
+    RING_LOCALS;							\
+    RADEONCP_REFRESH(pScrn, info)
+#define BEGIN_VIDEO(n)		BEGIN_RING(2*(n))
+#define OUT_VIDEO_REG(reg, val)	OUT_RING_REG(reg, val)
+#define FINISH_VIDEO()		ADVANCE_RING()
+#define OUT_VIDEO_RING_F(x) OUT_RING(F_TO_DW(x))
+
+#include "radeon_textured_videofuncs.c"
+
+#endif /* XF86DRI */
+
+static void
+RADEONXVCopyPlanarData(CARD8 *src, CARD8 *dst, int randr,
+		       int srcPitch, int srcPitch2, int dstPitch,
+		       int srcW, int srcH, int height,
+		       int top, int left, int h, int w, int id)
+{
+    int i, j;
+    CARD8 *src1, *src2, *src3, *dst1;
+    int srcDown = srcPitch, srcDown2 = srcPitch2;
+    int srcRight = 2, srcRight2 = 1, srcNext = 1;
+
+    /* compute source data pointers */
+    src1 = src;
+    src2 = src1 + height * srcPitch;
+    src3 = src2 + (height >> 1) * srcPitch2;
+    switch (randr) {
+    case RR_Rotate_0:
+	srcDown = srcPitch;
+	srcDown2 = srcPitch2;
+	srcRight = 2;
+	srcRight2 = 1;
+	srcNext = 1;
+	break;
+    case RR_Rotate_90:
+	src1 = src1 + srcH - 1;
+	src2 = src2 + (srcH >> 1) - 1;
+	src3 = src3 + (srcH >> 1) - 1;
+	srcDown = -1;
+	srcDown2 = -1;
+	srcRight = srcPitch * 2;
+	srcRight2 = srcPitch2;
+	srcNext = srcPitch;
+	break;
+    case RR_Rotate_180:
+	src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1);
+	src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
+	src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1);
+	srcDown = -srcPitch;
+	srcDown2 = -srcPitch2;
+	srcRight = -2;
+	srcRight2 = -1;
+	srcNext = -1;
+	break;
+    case RR_Rotate_270:
+	src1 = src1 + srcPitch * (srcW - 1);
+	src2 = src2 + srcPitch2 * ((srcW >> 1) - 1);
+	src3 = src3 + srcPitch2 * ((srcW >> 1) - 1);
+	srcDown = 1;
+	srcDown2 = 1;
+	srcRight = -srcPitch * 2;
+	srcRight2 = -srcPitch2;
+	srcNext = -srcPitch;
+	break;
+    }
+
+    /* adjust for origin */
+    src1 += top * srcDown + left * srcNext;
+    src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
+    src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2;
+
+    if (id == FOURCC_I420) {
+	CARD8 *srct = src2;
+	src2 = src3;
+	src3 = srct;
+    }
+
+    dst1 = dst;
+
+    w >>= 1;
+    for (j = 0; j < h; j++) {
+	CARD32 *dst = (CARD32 *)dst1;
+	CARD8 *s1l = src1;
+	CARD8 *s1r = src1 + srcNext;
+	CARD8 *s2 = src2;
+	CARD8 *s3 = src3;
+
+	for (i = 0; i < w; i++) {
+	    *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24);
+	    s1l += srcRight;
+	    s1r += srcRight;
+	    s2 += srcRight2;
+	    s3 += srcRight2;
+	}
+	src1 += srcDown;
+	dst1 += dstPitch;
+	if (j & 1) {
+	    src2 += srcDown2;
+	    src3 += srcDown2;
+	}
+    }
+}
+
+static void
+RADEONXVCopyPackedData(CARD8 *src, CARD8 *dst, int randr,
+		       int srcPitch, int dstPitch,
+		       int srcW, int srcH, int top, int left,
+		       int h, int w)
+{
+    int srcDown = srcPitch, srcRight = 2, srcNext;
+    int p;
+
+    switch (randr) {
+    case RR_Rotate_0:
+	srcDown = srcPitch;
+	srcRight = 2;
+	break;
+    case RR_Rotate_90:
+	src += (srcH - 1) * 2;
+	srcDown = -2;
+	srcRight = srcPitch;
+	break;
+    case RR_Rotate_180:
+	src += srcPitch * (srcH - 1) + (srcW - 1) * 2;
+	srcDown = -srcPitch;
+	srcRight = -2;
+	break;
+    case RR_Rotate_270:
+	src += srcPitch * (srcW - 1);
+	srcDown = 2;
+	srcRight = -srcPitch;
+	break;
+    }
+
+    src = src + top * srcDown + left * srcRight;
+
+    w >>= 1;
+    /* srcRight >>= 1; */
+    srcNext = srcRight >> 1;
+    while (h--) {
+	CARD16 *s = (CARD16 *)src;
+	CARD32 *d = (CARD32 *)dst;
+	p = w;
+	while (p--) {
+	    *d++ = s[0] | (s[srcNext] << 16);
+	    s += srcRight;
+	}
+	src += srcPitch;
+	dst += dstPitch;
+    }
+}
+
+static int
+RADEONPutImageTextured(ScrnInfoPtr pScrn,
+		       short src_x, short src_y,
+		       short drw_x, short drw_y,
+		       short src_w, short src_h,
+		       short drw_w, short drw_h,
+		       int id,
+		       unsigned char *buf,
+		       short width,
+		       short height,
+		       Bool sync,
+		       RegionPtr clipBoxes,
+		       pointer data,
+		       DrawablePtr pDraw)
+{
+    ScreenPtr pScreen = pScrn->pScreen;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
+    INT32 x1, x2, y1, y2;
+    int randr = RR_Rotate_0 /* XXX */;
+    int srcPitch, srcPitch2, dstPitch;
+    int top, left, npixels, nlines, size;
+    BoxRec dstBox;
+    int dst_width = width, dst_height = height;
+    int rot_x1, rot_y1, rot_x2, rot_y2;
+    int dst_x1, dst_y1, dst_x2, dst_y2;
+    int rot_src_w, rot_src_h, rot_drw_w, rot_drw_h;
+
+    /* Clip */
+    x1 = src_x;
+    x2 = src_x + src_w;
+    y1 = src_y;
+    y2 = src_y + src_h;
+
+    dstBox.x1 = drw_x;
+    dstBox.x2 = drw_x + drw_w;
+    dstBox.y1 = drw_y;
+    dstBox.y2 = drw_y + drw_h;
+
+    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height))
+	return Success;
+
+    src_w = (x2 - x1) >> 16;
+    src_h = (y2 - y1) >> 16;
+    drw_w = dstBox.x2 - dstBox.x1;
+    drw_h = dstBox.y2 - dstBox.y1;
+
+    if ((x1 >= x2) || (y1 >= y2))
+	return Success;
+
+    if (randr & (RR_Rotate_0|RR_Rotate_180)) {
+	dst_width = width;
+	dst_height = height;
+	rot_src_w = src_w;
+	rot_src_h = src_h;
+	rot_drw_w = drw_w;
+	rot_drw_h = drw_h;
+    } else {
+	dst_width = height;
+	dst_height = width;
+	rot_src_w = src_h;
+	rot_src_h = src_w;
+	rot_drw_w = drw_h;
+	rot_drw_h = drw_w;
+    }
+
+    switch (randr) {
+    case RR_Rotate_0:
+    default:
+	dst_x1 = dstBox.x1;
+	dst_y1 = dstBox.y1;
+	dst_x2 = dstBox.x2;
+	dst_y2 = dstBox.y2;
+	rot_x1 = x1;
+	rot_y1 = y1;
+	rot_x2 = x2;
+	rot_y2 = y2;
+	break;
+    case RR_Rotate_90:
+	dst_x1 = dstBox.y1;
+	dst_y1 = pScrn->virtualY - dstBox.x2;
+	dst_x2 = dstBox.y2;
+	dst_y2 = pScrn->virtualY - dstBox.x1;
+	rot_x1 = y1;
+	rot_y1 = (src_w << 16) - x2;
+	rot_x2 = y2;
+	rot_y2 = (src_w << 16) - x1;
+	break;
+    case RR_Rotate_180:
+	dst_x1 = pScrn->virtualX - dstBox.x2;
+	dst_y1 = pScrn->virtualY - dstBox.y2;
+	dst_x2 = pScrn->virtualX - dstBox.x1;
+	dst_y2 = pScrn->virtualY - dstBox.y1;
+	rot_x1 = (src_w << 16) - x2;
+	rot_y1 = (src_h << 16) - y2;
+	rot_x2 = (src_w << 16) - x1;
+	rot_y2 = (src_h << 16) - y1;
+	break;
+    case RR_Rotate_270:
+	dst_x1 = pScrn->virtualX - dstBox.y2;
+	dst_y1 = dstBox.x1;
+	dst_x2 = pScrn->virtualX - dstBox.y1;
+	dst_y2 = dstBox.x2;
+	rot_x1 = (src_h << 16) - y2;
+	rot_y1 = x1;
+	rot_x2 = (src_h << 16) - y1;
+	rot_y2 = x2;
+	break;
+    }
+
+    switch(id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	dstPitch = ((dst_width << 1) + 15) & ~15;
+	srcPitch = (width + 3) & ~3;
+	srcPitch2 = ((width >> 1) + 3) & ~3;
+	size = dstPitch * dst_height;
+	break;
+    case FOURCC_UYVY:
+    case FOURCC_YUY2:
+    default:
+	dstPitch = ((dst_width << 1) + 15) & ~15;
+	srcPitch = (width << 1);
+	srcPitch2 = 0;
+	size = dstPitch * dst_height;
+	break;
+    }
+
+    if (pPriv->video_memory != NULL && size != pPriv->size) {
+	RADEONFreeMemory(pScrn, pPriv->video_memory);
+	pPriv->video_memory = NULL;
+    }
+
+    if (pPriv->video_memory == NULL) {
+	pPriv->video_offset = RADEONAllocateMemory(pScrn,
+						       &pPriv->video_memory,
+						       size * 2);
+	if (pPriv->video_offset == 0)
+	    return BadAlloc;
+    }
+
+    if (pDraw->type == DRAWABLE_WINDOW)
+	pPriv->pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
+    else
+	pPriv->pPixmap = (PixmapPtr)pDraw;
+
+#ifdef USE_EXA
+    if (info->useEXA) {
+	/* Force the pixmap into framebuffer so we can draw to it. */
+	exaMoveInPixmap(pPriv->pPixmap);
+    }
+#endif
+
+    if (!info->useEXA &&
+	(((char *)pPriv->pPixmap->devPrivate.ptr < (char *)info->FB) ||
+	 ((char *)pPriv->pPixmap->devPrivate.ptr >= (char *)info->FB +
+	  info->FbMapSize))) {
+	/* If the pixmap wasn't in framebuffer, then we have no way in XAA to
+	 * force it there. So, we simply refuse to draw and fail.
+	 */
+	return BadAlloc;
+    }
+
+    pPriv->src_offset = pPriv->video_offset + info->fbLocation;
+    pPriv->src_addr = (CARD8 *)(info->FB + pPriv->video_offset);
+    pPriv->src_pitch = dstPitch;
+    pPriv->size = size;
+    pPriv->pDraw = pDraw;
+
+#if 0
+    ErrorF("src_offset: 0x%x\n", pPriv->src_offset);
+    ErrorF("src_addr: 0x%x\n", pPriv->src_addr);
+    ErrorF("src_pitch: 0x%x\n", pPriv->src_pitch);
+#endif
+
+    /* copy data */
+    top = rot_y1 >> 16;
+    left = (rot_x1 >> 16) & ~1;
+    npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left;
+
+    /* Since we're probably overwriting the area that might still be used
+     * for the last PutImage request, wait for idle.
+     */
+#ifdef XF86DRI
+    if (info->directRenderingEnabled)
+	RADEONWaitForIdleCP(pScrn);
+    else
+#endif
+	RADEONWaitForIdleMMIO(pScrn);
+
+
+    switch(id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+	top &= ~1;
+	nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top;
+	RADEONXVCopyPlanarData(buf, pPriv->src_addr, randr,
+			       srcPitch, srcPitch2, dstPitch, rot_src_w, rot_src_h,
+			       height, top, left, nlines, npixels, id);
+	break;
+    case FOURCC_UYVY:
+    case FOURCC_YUY2:
+    default:
+	nlines = ((rot_y2 + 0xffff) >> 16) - top;
+	RADEONXVCopyPackedData(buf, pPriv->src_addr, randr,
+			       srcPitch, dstPitch, rot_src_w, rot_src_h, top, left,
+			       nlines, npixels);
+	break;
+    }
+
+    /* update cliplist */
+    if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
+	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+    }
+
+    pPriv->id = id;
+    pPriv->src_x1 = rot_x1;
+    pPriv->src_y1 = rot_y1;
+    pPriv->src_x2 = rot_x2;
+    pPriv->src_y2 = rot_y2;
+    pPriv->src_w = rot_src_w;
+    pPriv->src_h = rot_src_h;
+    pPriv->dst_x1 = dst_x1;
+    pPriv->dst_y1 = dst_y1;
+    pPriv->dst_x2 = dst_x2;
+    pPriv->dst_y2 = dst_y2;
+    pPriv->dst_w = rot_drw_w;
+    pPriv->dst_h = rot_drw_h;
+
+#ifdef XF86DRI
+    if (info->directRenderingEnabled)
+	RADEONDisplayTexturedVideoCP(pScrn, pPriv);
+    else
+#endif
+	RADEONDisplayTexturedVideoMMIO(pScrn, pPriv);
+
+    return Success;
+}
+
+/* client libraries expect an encoding */
+static XF86VideoEncodingRec DummyEncoding[1] =
+{
+    {
+	0,
+	"XV_IMAGE",
+	IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
+	{1, 1}
+    }
+};
+
+#define NUM_FORMATS 3
+
+static XF86VideoFormatRec Formats[NUM_FORMATS] =
+{
+    {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+#define NUM_ATTRIBUTES 0
+
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
+{
+};
+
+#define NUM_IMAGES 4
+
+static XF86ImageRec Images[NUM_IMAGES] =
+{
+    XVIMAGE_YUY2,
+    XVIMAGE_YV12,
+    XVIMAGE_I420,
+    XVIMAGE_UYVY
+};
+
+XF86VideoAdaptorPtr
+RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
+{
+    RADEONPortPrivPtr pPortPriv;
+    XF86VideoAdaptorPtr adapt;
+    int i;
+    int num_texture_ports = 16;
+
+    adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
+		    (sizeof(RADEONPortPrivRec) + sizeof(DevUnion)));
+    if (adapt == NULL)
+	return NULL;
+
+    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+    adapt->flags = 0;
+    adapt->name = "Radeon Textured Video";
+    adapt->nEncodings = 1;
+    adapt->pEncodings = DummyEncoding;
+    adapt->nFormats = NUM_FORMATS;
+    adapt->pFormats = Formats;
+    adapt->nPorts = num_texture_ports;
+    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
+
+    pPortPriv =
+	(RADEONPortPrivPtr)(&adapt->pPortPrivates[num_texture_ports]);
+
+    adapt->nAttributes = NUM_ATTRIBUTES;
+    adapt->pAttributes = Attributes;
+    adapt->pImages = Images;
+    adapt->nImages = NUM_IMAGES;
+    adapt->PutVideo = NULL;
+    adapt->PutStill = NULL;
+    adapt->GetVideo = NULL;
+    adapt->GetStill = NULL;
+    adapt->StopVideo = RADEONStopVideo;
+    adapt->SetPortAttribute = RADEONSetPortAttribute;
+    adapt->GetPortAttribute = RADEONGetPortAttribute;
+    adapt->QueryBestSize = RADEONQueryBestSize;
+    adapt->PutImage = RADEONPutImageTextured;
+    adapt->ReputImage = NULL;
+    adapt->QueryImageAttributes = RADEONQueryImageAttributes;
+
+    for (i = 0; i < num_texture_ports; i++) {
+	RADEONPortPrivPtr pPriv = &pPortPriv[i];
+
+	pPriv->textured = TRUE;
+	pPriv->videoStatus = 0;
+	pPriv->currentBuffer = 0;
+	pPriv->doubleBuffer = 0;
+
+	/* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
+	REGION_NULL(pScreen, &pPriv->clip);
+	adapt->pPortPrivates[i].ptr = (pointer) (pPriv);
+    }
+
+    return adapt;
+}
+
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
new file mode 100644
index 0000000..3e635e8
--- /dev/null
+++ b/src/radeon_textured_videofuncs.c
@@ -0,0 +1,472 @@
+/*
+ * Copyright 2008 Alex Deucher
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *
+ * Based on radeon_exa_render.c and kdrive ati_video.c by Eric Anholt
+ *
+ */
+
+#if defined(ACCEL_MMIO) && defined(ACCEL_CP)
+#error Cannot define both MMIO and CP acceleration!
+#endif
+
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix
+#else
+#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix
+#endif
+
+#ifdef ACCEL_MMIO
+#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO)
+#else
+#ifdef ACCEL_CP
+#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP)
+#else
+#error No accel type defined!
+#endif
+#endif
+
+#define VTX_DWORD_COUNT 4
+
+#ifdef ACCEL_CP
+
+#define VTX_OUT(_dstX, _dstY, _srcX, _srcY)	\
+do {								\
+    OUT_VIDEO_RING_F(_dstX);						\
+    OUT_VIDEO_RING_F(_dstY);						\
+    OUT_VIDEO_RING_F(_srcX);						\
+    OUT_VIDEO_RING_F(_srcY);						\
+} while (0)
+
+#else /* ACCEL_CP */
+
+#define VTX_OUT(_dstX, _dstY, _srcX, _srcY)	\
+do {								\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _dstX);		\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _dstY);		\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _srcX);		\
+    OUT_VIDEO_REG_F(RADEON_SE_PORT_DATA0, _srcY);		\
+} while (0)
+
+#endif /* !ACCEL_CP */
+
+static void
+FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    PixmapPtr pPixmap = pPriv->pPixmap;
+    CARD32 txformat;
+    CARD32 txfilter, txformat0, txformat1, txoffset, txpitch;
+    CARD32 dst_offset, dst_pitch, dst_format;
+    CARD32 txenable, colorpitch;
+    CARD32 blendcntl;
+    int dstxoff, dstyoff, pixel_shift;
+    VIDEO_PREAMBLE();
+
+    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
+    int nBox = REGION_NUM_RECTS(&pPriv->clip);
+
+    pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
+
+#ifdef USE_EXA
+    if (info->useEXA) {
+	dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation;
+	dst_pitch = exaGetPixmapPitch(pPixmap);
+    } else
+#endif
+	{
+	    dst_offset = (pPixmap->devPrivate.ptr - info->FB) +
+		info->fbLocation + pScrn->fbOffset;
+	    dst_pitch = pPixmap->devKind;
+	}
+
+#ifdef COMPOSITE
+    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
+    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
+#else
+    dstxoff = 0;
+    dstyoff = 0;
+#endif
+
+#if 0
+    ErrorF("dst_offset: 0x%x\n", dst_offset);
+    ErrorF("dst_pitch: 0x%x\n", dst_pitch);
+    ErrorF("dstxoff: 0x%x\n", dstxoff);
+    ErrorF("dstyoff: 0x%x\n", dstyoff);
+    ErrorF("src_offset: 0x%x\n", pPriv->src_offset);
+    ErrorF("src_pitch: 0x%x\n", pPriv->src_pitch);
+#endif
+
+    if (!info->XInited3D)
+	RADEONInit3DEngine(pScrn);
+
+    /* we can probably improve this */
+    BEGIN_VIDEO(2);
+    OUT_VIDEO_REG(RADEON_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH);
+    /* We must wait for 3d to idle, in case source was just written as a dest. */
+    OUT_VIDEO_REG(RADEON_WAIT_UNTIL,
+		RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
+    FINISH_VIDEO();
+
+    if (IS_R300_VARIANT) {
+
+	switch (pPixmap->drawable.bitsPerPixel) {
+	case 16:
+	    if (pPixmap->drawable.depth == 15)
+		dst_format = R300_COLORFORMAT_ARGB1555;
+	    else
+		dst_format = R300_COLORFORMAT_RGB565;
+	    break;
+	case 32:
+	    dst_format = R300_COLORFORMAT_ARGB8888;
+	    break;
+	default:
+	    return;
+	}
+
+	colorpitch = dst_pitch >> pixel_shift;
+	colorpitch |= dst_format;
+
+	if (RADEONTilingEnabled(pScrn, pPixmap))
+	    colorpitch |= R300_COLORTILE;
+
+	if (pPriv->id == FOURCC_UYVY)
+	    txformat1 = R300_TX_FORMAT_YVYU422;
+	else
+	    txformat1 = R300_TX_FORMAT_VYUY422;
+
+	txformat1 |= R300_TX_FORMAT_YUV_TO_RGB_CLAMP;
+
+	txformat0 = (((RADEONPow2(pPriv->src_w) - 1) << R300_TXWIDTH_SHIFT) |
+		     ((RADEONPow2(pPriv->src_h) - 1) << R300_TXHEIGHT_SHIFT));
+
+	txformat0 |= R300_TXPITCH_EN;
+
+	info->texW[0] = RADEONPow2(pPriv->src_w);
+	info->texH[0] = RADEONPow2(pPriv->src_h);
+
+	txfilter = (R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR);
+
+	txpitch = pPriv->src_w * 4;
+	txpitch >>= pixel_shift;
+	txpitch -= 1;
+
+	txoffset = pPriv->src_offset;
+
+	BEGIN_VIDEO(6);
+	OUT_VIDEO_REG(R300_TX_FILTER0_0, txfilter);
+	OUT_VIDEO_REG(R300_TX_FILTER1_0, 0x0);
+	OUT_VIDEO_REG(R300_TX_FORMAT0_0, txformat0);
+	OUT_VIDEO_REG(R300_TX_FORMAT1_0, txformat1);
+	OUT_VIDEO_REG(R300_TX_FORMAT2_0, txpitch);
+	OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset);
+	FINISH_VIDEO();
+
+	txenable = R300_TEX_0_ENABLE;
+
+	/* setup vertex shader */
+	BEGIN_VIDEO(26);
+	OUT_VIDEO_REG(R300_VAP_CNTL_STATUS, 0x0);
+	OUT_VIDEO_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0);
+	OUT_VIDEO_REG(R300_VAP_CNTL, 0x300456);
+	OUT_VIDEO_REG(R300_VAP_VTE_CNTL, 0x300);
+	OUT_VIDEO_REG(R300_VAP_PSC_SGN_NORM_CNTL, 0x0);
+	OUT_VIDEO_REG(R300_VAP_PROG_STREAM_CNTL_0, 0x6a014001);
+	OUT_VIDEO_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0, 0xf688f688);
+	OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_0, 0x100400);
+	OUT_VIDEO_REG(R300_VAP_PVS_CODE_CNTL_1, 0x1);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f00203);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10001);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f02203);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10141);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141);
+	OUT_VIDEO_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141);
+
+	OUT_VIDEO_REG(R300_VAP_PVS_FLOW_CNTL_OPC, 0x0);
+	OUT_VIDEO_REG(R300_VAP_OUT_VTX_FMT_0, 0x1);
+	OUT_VIDEO_REG(R300_VAP_OUT_VTX_FMT_1, 0x2);
+
+	OUT_VIDEO_REG(R300_VAP_GB_VERT_CLIP_ADJ, 0x3f800000);
+	OUT_VIDEO_REG(R300_VAP_GB_VERT_DISC_ADJ, 0x3f800000);
+	OUT_VIDEO_REG(R300_VAP_GB_HORZ_CLIP_ADJ, 0x3f800000);
+	OUT_VIDEO_REG(R300_VAP_GB_HORZ_DISC_ADJ, 0x3f800000);
+	OUT_VIDEO_REG(R300_VAP_CLIP_CNTL, 0x10000);
+	FINISH_VIDEO();
+
+	/* setup pixel shader */
+	BEGIN_VIDEO(12);
+	OUT_VIDEO_REG(R300_US_CONFIG, 0x8);
+	OUT_VIDEO_REG(R300_US_PIXSIZE, 0x0);
+	OUT_VIDEO_REG(R300_US_CODE_OFFSET, 0x40040);
+	OUT_VIDEO_REG(R300_US_CODE_ADDR_0, 0x0);
+	OUT_VIDEO_REG(R300_US_CODE_ADDR_1, 0x0);
+	OUT_VIDEO_REG(R300_US_CODE_ADDR_2, 0x0);
+	OUT_VIDEO_REG(R300_US_CODE_ADDR_3, 0x400000);
+	OUT_VIDEO_REG(R300_US_TEX_INST_0, 0x8000);
+	OUT_VIDEO_REG(R300_US_ALU_RGB_ADDR_0, 0x1f800000);
+	OUT_VIDEO_REG(R300_US_ALU_RGB_INST_0, 0x50a80);
+	OUT_VIDEO_REG(R300_US_ALU_ALPHA_ADDR_0, 0x1800000);
+	OUT_VIDEO_REG(R300_US_ALU_ALPHA_INST_0, 0x00040889);
+	FINISH_VIDEO();
+
+	BEGIN_VIDEO(6);
+	OUT_VIDEO_REG(R300_TX_INVALTAGS, 0x0);
+	OUT_VIDEO_REG(R300_TX_ENABLE, txenable);
+
+	OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+	OUT_VIDEO_REG(R300_RB3D_COLORPITCH0, colorpitch);
+
+	blendcntl = RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO;
+	OUT_VIDEO_REG(R300_RB3D_BLENDCNTL, blendcntl);
+	OUT_VIDEO_REG(R300_RB3D_ABLENDCNTL, 0x0);
+	FINISH_VIDEO();
+
+	BEGIN_VIDEO(1);
+	OUT_VIDEO_REG(R300_VAP_VTX_SIZE, VTX_DWORD_COUNT);
+	FINISH_VIDEO();
+
+    } else {
+
+	/* Same for R100/R200 */
+	switch (pPixmap->drawable.bitsPerPixel) {
+	case 16:
+	    if (pPixmap->drawable.depth == 15)
+		dst_format = RADEON_COLOR_FORMAT_ARGB1555;
+	    else
+		dst_format = RADEON_COLOR_FORMAT_RGB565;
+	    break;
+	case 32:
+	    dst_format = RADEON_COLOR_FORMAT_ARGB8888;
+	    break;
+	default:
+	    return;
+	}
+
+	if (pPriv->id == FOURCC_UYVY)
+	    txformat = RADEON_TXFORMAT_YVYU422;
+	else
+	    txformat = RADEON_TXFORMAT_VYUY422;
+
+	txformat |= RADEON_TXFORMAT_NON_POWER2;
+
+	colorpitch = dst_pitch >> pixel_shift;
+
+	if (RADEONTilingEnabled(pScrn, pPixmap))
+	    colorpitch |= RADEON_COLOR_TILE_ENABLE;
+
+	BEGIN_VIDEO(5);
+
+	OUT_VIDEO_REG(RADEON_PP_CNTL,
+		    RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
+	OUT_VIDEO_REG(RADEON_RB3D_CNTL,
+		    dst_format | RADEON_ALPHA_BLEND_ENABLE);
+	OUT_VIDEO_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+
+	OUT_VIDEO_REG(RADEON_RB3D_COLORPITCH, colorpitch);
+
+	OUT_VIDEO_REG(RADEON_RB3D_BLENDCNTL,
+		    RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO);
+
+	FINISH_VIDEO();
+
+
+	if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
+	    (info->ChipFamily == CHIP_FAMILY_RV280) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS300) ||
+	    (info->ChipFamily == CHIP_FAMILY_R200)) {
+
+	    info->texW[0] = pPriv->src_w;
+	    info->texH[0] = pPriv->src_h;
+
+	    BEGIN_VIDEO(12);
+
+	    OUT_VIDEO_REG(R200_SE_VTX_FMT_0, R200_VTX_XY);
+	    OUT_VIDEO_REG(R200_SE_VTX_FMT_1,
+			(2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
+
+	    OUT_VIDEO_REG(R200_PP_TXFILTER_0,
+			R200_MAG_FILTER_LINEAR |
+			R200_MIN_FILTER_LINEAR |
+			R200_YUV_TO_RGB);
+	    OUT_VIDEO_REG(R200_PP_TXFORMAT_0, txformat);
+	    OUT_VIDEO_REG(R200_PP_TXFORMAT_X_0, 0);
+	    OUT_VIDEO_REG(R200_PP_TXSIZE_0,
+			(pPriv->src_w - 1) |
+			((pPriv->src_h - 1) << RADEON_TEX_VSIZE_SHIFT));
+	    OUT_VIDEO_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
+
+	    OUT_VIDEO_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
+
+	    OUT_VIDEO_REG(R200_PP_TXCBLEND_0,
+			R200_TXC_ARG_A_ZERO |
+			R200_TXC_ARG_B_ZERO |
+			R200_TXC_ARG_C_R0_COLOR |
+			R200_TXC_OP_MADD);
+	    OUT_VIDEO_REG(R200_PP_TXCBLEND2_0,
+			R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0);
+	    OUT_VIDEO_REG(R200_PP_TXABLEND_0,
+			R200_TXA_ARG_A_ZERO |
+			R200_TXA_ARG_B_ZERO |
+			R200_TXA_ARG_C_R0_ALPHA |
+			R200_TXA_OP_MADD);
+	    OUT_VIDEO_REG(R200_PP_TXABLEND2_0,
+			R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0);
+	    FINISH_VIDEO();
+	} else {
+
+	    info->texW[0] = 1;
+	    info->texH[0] = 1;
+
+	    BEGIN_VIDEO(8);
+
+	    OUT_VIDEO_REG(RADEON_SE_VTX_FMT, RADEON_SE_VTX_FMT_XY |
+			RADEON_SE_VTX_FMT_ST0);
+
+	    OUT_VIDEO_REG(RADEON_PP_TXFILTER_0, RADEON_MAG_FILTER_LINEAR |
+			RADEON_MIN_FILTER_LINEAR |
+			RADEON_YUV_TO_RGB);
+	    OUT_VIDEO_REG(RADEON_PP_TXFORMAT_0, txformat);
+	    OUT_VIDEO_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset);
+	    OUT_VIDEO_REG(RADEON_PP_TXCBLEND_0,
+			RADEON_COLOR_ARG_A_ZERO |
+			RADEON_COLOR_ARG_B_ZERO |
+			RADEON_COLOR_ARG_C_T0_COLOR |
+			RADEON_BLEND_CTL_ADD |
+			RADEON_CLAMP_TX);
+	    OUT_VIDEO_REG(RADEON_PP_TXABLEND_0,
+			RADEON_ALPHA_ARG_A_ZERO |
+			RADEON_ALPHA_ARG_B_ZERO |
+			RADEON_ALPHA_ARG_C_T0_ALPHA |
+			RADEON_BLEND_CTL_ADD |
+			RADEON_CLAMP_TX);
+
+	    OUT_VIDEO_REG(RADEON_PP_TEX_SIZE_0,
+			(pPriv->src_w - 1) |
+			((pPriv->src_h - 1) << RADEON_TEX_VSIZE_SHIFT));
+	    OUT_VIDEO_REG(RADEON_PP_TEX_PITCH_0,
+			pPriv->src_pitch - 32);
+	    FINISH_VIDEO();
+	}
+    }
+
+    while (nBox--) {
+	int srcX, srcY, srcw, srch;
+	int dstX, dstY, dstw, dsth;
+	xPointFixed srcTopLeft, srcTopRight, srcBottomLeft, srcBottomRight;
+	dstX = pBox->x1 + dstxoff;
+	dstY = pBox->y1 + dstyoff;
+	dstw = pBox->x2 - pBox->x1;
+	dsth = pBox->y2 - pBox->y1;
+	srcX = (pBox->x1 - pPriv->dst_x1) *
+	    pPriv->src_w / pPriv->dst_w;
+	srcY = (pBox->y1 - pPriv->dst_y1) *
+	    pPriv->src_h / pPriv->dst_h;
+
+	srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
+	srch = (pPriv->src_h * dsth) / pPriv->dst_h;
+
+	srcTopLeft.x     = IntToxFixed(srcX);
+	srcTopLeft.y     = IntToxFixed(srcY);
+	srcTopRight.x    = IntToxFixed(srcX + srcw);
+	srcTopRight.y    = IntToxFixed(srcY);
+	srcBottomLeft.x  = IntToxFixed(srcX);
+	srcBottomLeft.y  = IntToxFixed(srcY + srch);
+	srcBottomRight.x = IntToxFixed(srcX + srcw);
+	srcBottomRight.y = IntToxFixed(srcY + srch);
+
+#if 0
+	ErrorF("dst: %d, %d, %d, %d\n", dstX, dstY, dstw, dsth);
+	ErrorF("src: %d, %d, %d, %d\n", srcX, srcY, srcw, srch);
+#endif
+
+#ifdef ACCEL_CP
+	if (info->ChipFamily < CHIP_FAMILY_R200) {
+	    BEGIN_RING(4 * VTX_DWORD_COUNT + 3);
+	    OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD,
+				4 * VTX_DWORD_COUNT + 1));
+	    OUT_RING(RADEON_CP_VC_FRMT_XY |
+		     RADEON_CP_VC_FRMT_ST0);
+	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+		     RADEON_CP_VC_CNTL_MAOS_ENABLE |
+		     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+		     (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	} else {
+	    if (IS_R300_VARIANT)
+		BEGIN_RING(4 * VTX_DWORD_COUNT + 6);
+	    else
+		BEGIN_RING(4 * VTX_DWORD_COUNT + 2);
+	    OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2,
+				4 * VTX_DWORD_COUNT));
+	    OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+		     RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+		     (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+	}
+#else /* ACCEL_CP */
+	if (IS_R300_VARIANT)
+	    BEGIN_VIDEO(3 + VTX_DWORD_COUNT * 4);
+	else
+	    BEGIN_VIDEO(1 + VTX_DWORD_COUNT * 4);
+
+	if (info->ChipFamily < CHIP_FAMILY_R200) {
+	    OUT_VIDEO_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_FAN |
+					      RADEON_VF_PRIM_WALK_DATA |
+					      RADEON_VF_RADEON_MODE |
+					      4 << RADEON_VF_NUM_VERTICES_SHIFT));
+	} else {
+	    OUT_VIDEO_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST |
+					      RADEON_VF_PRIM_WALK_DATA |
+					      4 << RADEON_VF_NUM_VERTICES_SHIFT));
+	}
+#endif
+
+	VTX_OUT((float)dstX,                                      (float)dstY,
+		xFixedToFloat(srcTopLeft.x) / info->texW[0],      xFixedToFloat(srcTopLeft.y) / info->texH[0]);
+	VTX_OUT((float)dstX,                                      (float)(dstY + dsth),
+		xFixedToFloat(srcBottomLeft.x) / info->texW[0],   xFixedToFloat(srcBottomLeft.y) / info->texH[0]);
+	VTX_OUT((float)(dstX + dstw),                                (float)(dstY + dsth),
+		xFixedToFloat(srcBottomRight.x) / info->texW[0],  xFixedToFloat(srcBottomRight.y) / info->texH[0]);
+	VTX_OUT((float)(dstX + dstw),                                (float)dstY,
+		xFixedToFloat(srcTopRight.x) / info->texW[0],     xFixedToFloat(srcTopRight.y) / info->texH[0]);
+
+	if (IS_R300_VARIANT) {
+	    OUT_VIDEO_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA);
+	    OUT_VIDEO_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+	}
+
+#ifdef ACCEL_CP
+	ADVANCE_RING();
+#else
+	FINISH_VIDEO();
+#endif /* !ACCEL_CP */
+
+	pBox++;
+    }
+
+    DamageDamageRegion(pPriv->pDraw, &pPriv->clip);
+}
+
+#undef VTX_OUT
+#undef FUNC_NAME
diff --git a/src/radeon_video.c b/src/radeon_video.c
index 0b3f6ca..ba7cf74 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -74,19 +74,10 @@
 static void RADEONInitOffscreenImages(ScreenPtr);
 
 static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr);
-static int  RADEONSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
-static int  RADEONGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
-static void RADEONStopVideo(ScrnInfoPtr, pointer, Bool);
-static void RADEONQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
-			unsigned int *, unsigned int *, pointer);
 static int  RADEONPutImage(ScrnInfoPtr, short, short, short, short, short,
 			short, short, short, int, unsigned char*, short,
 			short, Bool, RegionPtr, pointer,
 			DrawablePtr);
-static int  RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
-			unsigned short *,  int *, int *);
-static void RADEONFreeMemory(ScrnInfoPtr pScrn, void *mem_struct);
-
 static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now);
 static int RADEONPutVideo(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y,
                         short src_w, short src_h, short drw_w, short drw_h, 
@@ -270,36 +261,43 @@ ATIVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area)
 void RADEONInitVideo(ScreenPtr pScreen)
 {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr    info = RADEONPTR(pScrn);
     XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
-    XF86VideoAdaptorPtr newAdaptor = NULL;
+    XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
     int num_adaptors;
 
-    newAdaptor = RADEONSetupImageVideo(pScreen);
-    RADEONInitOffscreenImages(pScreen);
+
     num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+    newAdaptors = xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
+    if (newAdaptors == NULL)
+	return;
 
-    if(newAdaptor) {
-	if(!num_adaptors) {
-	    num_adaptors = 1;
-	    adaptors = &newAdaptor;
-	} else {
-	    newAdaptors =  /* need to free this someplace */
-		xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
-	    if(newAdaptors) {
-		memcpy(newAdaptors, adaptors, num_adaptors *
-					sizeof(XF86VideoAdaptorPtr));
-		newAdaptors[num_adaptors] = newAdaptor;
-		adaptors = newAdaptors;
-		num_adaptors++;
-	    }
-	}
+    memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
+    adaptors = newAdaptors;
+
+    if (!IS_AVIVO_VARIANT) {
+	overlayAdaptor = RADEONSetupImageVideo(pScreen);
+	if (overlayAdaptor != NULL) {
+	    adaptors[num_adaptors++] = overlayAdaptor;
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n");
+	} else
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up overlay video\n");
+	RADEONInitOffscreenImages(pScreen);
     }
 
+    texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen);
+    if (texturedAdaptor != NULL) {
+	adaptors[num_adaptors++] = texturedAdaptor;
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
+    } else
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up textured video\n");
+
     if(num_adaptors)
 	xf86XVScreenInit(pScreen, adaptors, num_adaptors);
 
     if(newAdaptors)
 	xfree(newAdaptors);
+
 }
 
 /* client libraries expect an encoding */
@@ -1611,6 +1609,8 @@ RADEONSetupImageVideo(ScreenPtr pScreen)
     pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr);
     REGION_NULL(pScreen, &(pPriv->clip));
 
+    pPriv->textured = FALSE;
+
     if(pPriv->theatre != NULL) 
     {
 	/* video decoder is present, extend capabilities */
@@ -1626,13 +1626,16 @@ RADEONSetupImageVideo(ScreenPtr pScreen)
     return adapt;
 }
 
-static void
+void
 RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
 {
   RADEONInfoPtr info = RADEONPTR(pScrn);
   unsigned char *RADEONMMIO = info->MMIO;
   RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
 
+    if (pPriv->textured)
+	return;
+
   REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
 
   if(cleanup) {
@@ -1663,7 +1666,7 @@ RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
   }
 }
 
-static int
+int
 RADEONSetPortAttribute(ScrnInfoPtr  pScrn,
 		       Atom	    attribute,
 		       INT32	    value,
@@ -1675,6 +1678,9 @@ RADEONSetPortAttribute(ScrnInfoPtr  pScrn,
     Bool		setAlpha = FALSE;
     unsigned char *RADEONMMIO = info->MMIO;
 
+    if (pPriv->textured)
+	return BadMatch;
+
     RADEON_SYNC(info, pScrn);
 
 #define RTFSaturation(a)   (1.0 + ((a)*1.0)/1000.0)
@@ -1937,7 +1943,7 @@ RADEONSetPortAttribute(ScrnInfoPtr  pScrn,
     return Success;
 }
 
-static int
+int
 RADEONGetPortAttribute(ScrnInfoPtr  pScrn,
 		       Atom	    attribute,
 		       INT32	    *value,
@@ -1946,6 +1952,9 @@ RADEONGetPortAttribute(ScrnInfoPtr  pScrn,
     RADEONInfoPtr	info = RADEONPTR(pScrn);
     RADEONPortPrivPtr	pPriv = (RADEONPortPrivPtr)data;
 
+    if (pPriv->textured)
+	return BadMatch;
+
     if (info->accelOn) RADEON_SYNC(info, pScrn);
 
     if(attribute == xvAutopaintColorkey)
@@ -2031,7 +2040,7 @@ RADEONGetPortAttribute(ScrnInfoPtr  pScrn,
     return Success;
 }
 
-static void
+void
 RADEONQueryBestSize(
   ScrnInfoPtr pScrn,
   Bool motion,
@@ -2040,10 +2049,14 @@ RADEONQueryBestSize(
   unsigned int *p_w, unsigned int *p_h,
   pointer data
 ){
-   if(vid_w > (drw_w << 4))
-	drw_w = vid_w >> 4;
-   if(vid_h > (drw_h << 4))
-	drw_h = vid_h >> 4;
+    RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
+
+    if (!pPriv->textured) {
+	if (vid_w > (drw_w << 4))
+	    drw_w = vid_w >> 4;
+	if (vid_h > (drw_h << 4))
+	    drw_h = vid_h >> 4;
+    }
 
   *p_w = drw_w;
   *p_h = drw_h;
@@ -2405,7 +2418,7 @@ RADEONCopyMungedData(
  * is measured in bytes, and the offset from the beginning of card space is
  * returned.
  */
-static CARD32
+CARD32
 RADEONAllocateMemory(
    ScrnInfoPtr pScrn,
    void **mem_struct,
@@ -2482,7 +2495,7 @@ RADEONAllocateMemory(
     return offset;
 }
 
-static void
+void
 RADEONFreeMemory(
    ScrnInfoPtr pScrn,
    void *mem_struct
@@ -3122,7 +3135,7 @@ RADEONPutImage(
 }
 
 
-static int
+int
 RADEONQueryImageAttributes(
     ScrnInfoPtr pScrn,
     int id,
diff --git a/src/radeon_video.h b/src/radeon_video.h
index 072f40e..a9e9e7d 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -81,8 +81,8 @@ typedef struct {
    Bool          autopaint_colorkey;
    xf86CrtcPtr   desired_crtc;
 
-#ifdef USE_EXA
    int              size;
+#ifdef USE_EXA
    ExaOffscreenArea *off_screen;
 #endif
 
@@ -90,6 +90,20 @@ typedef struct {
    int           video_offset;
 
    Atom          device_id, location_id, instance_id;
+
+    /* textured video */
+    Bool textured;
+    DrawablePtr pDraw;
+    PixmapPtr pPixmap;
+
+    CARD32 src_offset;
+    CARD32 src_pitch;
+    CARD8 *src_addr;
+
+    int id;
+    int src_x1, src_y1, src_x2, src_y2;
+    int dst_x1, dst_y1, dst_x2, dst_y2;
+    int src_w, src_h, dst_w, dst_h;
 } RADEONPortPrivRec, *RADEONPortPrivPtr;
 
 
@@ -99,5 +113,20 @@ void RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
 void RADEONVIP_init(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
 void RADEONVIP_reset(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
 
+CARD32
+RADEONAllocateMemory(ScrnInfoPtr pScrn, void **mem_struct, int size);
+void
+RADEONFreeMemory(ScrnInfoPtr pScrn, void *mem_struct);
+
+int  RADEONSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
+int  RADEONGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
+void RADEONStopVideo(ScrnInfoPtr, pointer, Bool);
+void RADEONQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
+			 unsigned int *, unsigned int *, pointer);
+int  RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
+			unsigned short *,  int *, int *);
+
+XF86VideoAdaptorPtr
+RADEONSetupImageTexturedVideo(ScreenPtr pScreen);
 
 #endif


More information about the xorg-commit mailing list