summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alex@samba.(none)>2008-02-23 19:06:30 -0500
committerAlex Deucher <alex@samba.(none)>2008-02-23 19:06:30 -0500
commitd9be9f34b0d3313e7b22b2a8bb0a8924ad3116bf (patch)
tree4dd3416086a3dc9b063bd8b245be973cd9fd903f
parent9dc4acad79196e9d5d94dd710773bfa83456d47f (diff)
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
-rw-r--r--src/Makefile.am1
-rw-r--r--src/radeon.h2
-rw-r--r--src/radeon_commonfuncs.c33
-rw-r--r--src/radeon_exa.c2
-rw-r--r--src/radeon_exa_render.c38
-rw-r--r--src/radeon_reg.h6
-rw-r--r--src/radeon_textured_video.c596
-rw-r--r--src/radeon_textured_videofuncs.c472
-rw-r--r--src/radeon_video.c89
-rw-r--r--src/radeon_video.h31
10 files changed, 1193 insertions, 77 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index a146df30..e0799a56 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 7d63f282..aba3c0f2 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 8c4b598c..629336f0 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 3b0c734d..4ea451d7 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 da1fa47f..9b23cdcf 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 88cf147f..3702ee44 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 00000000..8a14024d
--- /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 00000000..3e635e87
--- /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 0b3f6caa..ba7cf74c 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 072f40e1..a9e9e7dd 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