diff options
author | Alex Deucher <alex@samba.(none)> | 2008-02-23 19:06:30 -0500 |
---|---|---|
committer | Alex Deucher <alex@samba.(none)> | 2008-02-23 19:06:30 -0500 |
commit | d9be9f34b0d3313e7b22b2a8bb0a8924ad3116bf (patch) | |
tree | 4dd3416086a3dc9b063bd8b245be973cd9fd903f | |
parent | 9dc4acad79196e9d5d94dd710773bfa83456d47f (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.am | 1 | ||||
-rw-r--r-- | src/radeon.h | 2 | ||||
-rw-r--r-- | src/radeon_commonfuncs.c | 33 | ||||
-rw-r--r-- | src/radeon_exa.c | 2 | ||||
-rw-r--r-- | src/radeon_exa_render.c | 38 | ||||
-rw-r--r-- | src/radeon_reg.h | 6 | ||||
-rw-r--r-- | src/radeon_textured_video.c | 596 | ||||
-rw-r--r-- | src/radeon_textured_videofuncs.c | 472 | ||||
-rw-r--r-- | src/radeon_video.c | 89 | ||||
-rw-r--r-- | src/radeon_video.h | 31 |
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 |