diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-02-03 10:44:10 -0500 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2009-02-03 10:44:10 -0500 |
commit | d1f071c7f1dad6babfbcfcc2cb2b722a4987f372 (patch) | |
tree | 8b1d683610782ab59c382c611f8df474c79da91a /src/radeon_textured_video.c | |
parent | c88c3ef6f3db266c1aacba5297b8dfc8b66bf00e (diff) |
Initial R6xx/R7xx EXA and textured video support
Diffstat (limited to 'src/radeon_textured_video.c')
-rw-r--r-- | src/radeon_textured_video.c | 184 |
1 files changed, 157 insertions, 27 deletions
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c index 7712344b..16b2c829 100644 --- a/src/radeon_textured_video.c +++ b/src/radeon_textured_video.c @@ -36,6 +36,7 @@ #include "radeon.h" #include "radeon_reg.h" +#include "r600_reg.h" #include "radeon_macros.h" #include "radeon_probe.h" #include "radeon_video.h" @@ -43,12 +44,18 @@ #include <X11/extensions/Xv.h> #include "fourcc.h" +extern void +R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); + #define IMAGE_MAX_WIDTH 2048 #define IMAGE_MAX_HEIGHT 2048 #define IMAGE_MAX_WIDTH_R500 4096 #define IMAGE_MAX_HEIGHT_R500 4096 +#define IMAGE_MAX_WIDTH_R600 8192 +#define IMAGE_MAX_HEIGHT_R600 8192 + static Bool RADEONTilingEnabled(ScrnInfoPtr pScrn, PixmapPtr pPix) { @@ -146,6 +153,82 @@ static __inline__ uint32_t F_TO_24(float val) #endif /* XF86DRI */ +static void +CopyPlanartoNV12(unsigned char *y_src, unsigned char *u_src, unsigned char *v_src, + unsigned char *dst, + int srcPitch, int srcPitch2, int dstPitch, + int w, int h) +{ + int i, j; + + /* Y */ + if (srcPitch == dstPitch) { + memcpy(dst, y_src, srcPitch * h); + dst += (dstPitch * h); + } else { + for (i = 0; i < h; i++) { + memcpy(dst, y_src, srcPitch); + y_src += srcPitch; + dst += dstPitch; + } + } + + /* tex base need 256B alignment */ + if (h & 1) + dst += dstPitch; + + /* UV */ + for (i = 0; i < (h >> 1); i++) { + unsigned char *u = u_src; + unsigned char *v = v_src; + unsigned char *uv = dst; + + for (j = 0; j < w; j++) { + uv[0] = v[j]; + uv[1] = u[j]; + uv += 2; + } + dst += dstPitch; + u_src += srcPitch2; + v_src += srcPitch2; + } +} + +static void +CopyPackedtoNV12(unsigned char *src, unsigned char *dst, + int srcPitch, int dstPitch, + int w, int h, int id) +{ + int i, j; + int uv_offset = dstPitch * h; + uv_offset = (uv_offset + 255) & ~255; + + // FOURCC_UYVY: U0 Y0 V0 Y1 + // FOURCC_YUY2: Y0 U0 Y1 V0 + for (i = 0; i < h; i++) { + unsigned char *y = dst; + unsigned char *uv = (unsigned char *)dst + uv_offset; + + for (j = 0; j < (w / 2); j++) { + if (id == FOURCC_UYVY) { + uv[1] = src[(j * 4) + 0]; + y[0] = src[(j * 4) + 1]; + uv[0] = src[(j * 4) + 2]; + y[1] = src[(j * 4) + 3]; + } else { + y[0] = src[(j * 4) + 0]; + uv[1] = src[(j * 4) + 1]; + y[1] = src[(j * 4) + 2]; + uv[0] = src[(j * 4) + 3]; + } + y += 2; + uv += 2; + } + dst += dstPitch; + src += srcPitch; + } +} + static int RADEONPutImageTextured(ScrnInfoPtr pScrn, short src_x, short src_y, @@ -214,7 +297,10 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, break; } - dstPitch = (dstPitch + 63) & ~63; + if (info->ChipFamily >= CHIP_FAMILY_R600) + dstPitch = (dstPitch + 511) & ~511; + else + dstPitch = (dstPitch + 63) & ~63; if (pPriv->video_memory != NULL && size != pPriv->size) { radeon_legacy_free_memory(pScrn, pPriv->video_memory); @@ -222,16 +308,21 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, } if (pPriv->video_memory == NULL) { - pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, - &pPriv->video_memory, - size * 2, 64); + if (info->ChipFamily >= CHIP_FAMILY_R600) + pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, + &pPriv->video_memory, + size * 2, 512); + else + pPriv->video_offset = radeon_legacy_allocate_memory(pScrn, + &pPriv->video_memory, + size * 2, 64); if (pPriv->video_offset == 0) return BadAlloc; } /* Bicubic filter setup */ pPriv->bicubic_enabled = (pPriv->bicubic_state != BICUBIC_OFF); - if (!(IS_R300_3D || IS_R500_3D)) + if (!(IS_R300_3D || IS_R500_3D || IS_R600_3D)) pPriv->bicubic_enabled = FALSE; if (pPriv->bicubic_enabled && (pPriv->bicubic_state == BICUBIC_AUTO)) { /* @@ -280,7 +371,10 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; pPriv->src_offset = pPriv->video_offset + info->fbLocation + pScrn->fbOffset; - pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch)); + if (info->ChipFamily >= CHIP_FAMILY_R600) + pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset); + else + pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch)); pPriv->src_pitch = dstPitch; pPriv->size = size; pPriv->pDraw = pDraw; @@ -294,29 +388,51 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, switch(id) { case FOURCC_YV12: case FOURCC_I420: - top &= ~1; - nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; - s2offset = srcPitch * height; - s3offset = (srcPitch2 * (height >> 1)) + s2offset; - top &= ~1; - pPriv->src_addr += left << 1; - tmp = ((top >> 1) * srcPitch2) + (left >> 1); - s2offset += tmp; - s3offset += tmp; - if (id == FOURCC_I420) { - tmp = s2offset; - s2offset = s3offset; - s3offset = tmp; + if (info->ChipFamily >= CHIP_FAMILY_R600) { + s2offset = srcPitch * height; + s3offset = (srcPitch2 * (height >> 1)) + s2offset; + if (id == FOURCC_YV12) + CopyPlanartoNV12(buf, buf + s3offset, buf + s2offset, + pPriv->src_addr, + srcPitch, srcPitch2, pPriv->src_pitch, + width, height); + else + CopyPlanartoNV12(buf, buf + s2offset, buf + s3offset, + pPriv->src_addr, + srcPitch, srcPitch2, pPriv->src_pitch, + width, height); + + } else { + top &= ~1; + nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; + s2offset = srcPitch * height; + s3offset = (srcPitch2 * (height >> 1)) + s2offset; + top &= ~1; + pPriv->src_addr += left << 1; + tmp = ((top >> 1) * srcPitch2) + (left >> 1); + s2offset += tmp; + s3offset += tmp; + if (id == FOURCC_I420) { + tmp = s2offset; + s2offset = s3offset; + s3offset = tmp; + } + RADEONCopyMungedData(pScrn, buf + (top * srcPitch) + left, + buf + s2offset, buf + s3offset, pPriv->src_addr, + srcPitch, srcPitch2, dstPitch, nlines, npixels); } - RADEONCopyMungedData(pScrn, buf + (top * srcPitch) + left, - buf + s2offset, buf + s3offset, pPriv->src_addr, - srcPitch, srcPitch2, dstPitch, nlines, npixels); break; case FOURCC_UYVY: case FOURCC_YUY2: default: - nlines = ((y2 + 0xffff) >> 16) - top; - RADEONCopyData(pScrn, buf, pPriv->src_addr, srcPitch, dstPitch, nlines, npixels, 2); + if (info->ChipFamily >= CHIP_FAMILY_R600) { + CopyPackedtoNV12(buf, pPriv->src_addr, + 2 * width, pPriv->src_pitch, + width, height, id); + } else { + nlines = ((y2 + 0xffff) >> 16) - top; + RADEONCopyData(pScrn, buf, pPriv->src_addr, srcPitch, dstPitch, nlines, npixels, 2); + } break; } @@ -340,7 +456,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, pPriv->h = height; #ifdef XF86DRI - if (info->directRenderingEnabled) + if (IS_R600_3D) + R600DisplayTexturedVideo(pScrn, pPriv); + else if (info->directRenderingEnabled) RADEONDisplayTexturedVideoCP(pScrn, pPriv); else #endif @@ -370,6 +488,16 @@ static XF86VideoEncodingRec DummyEncodingR500[1] = } }; +static XF86VideoEncodingRec DummyEncodingR600[1] = +{ + { + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH_R600, IMAGE_MAX_HEIGHT_R600, + {1, 1} + } +}; + #define NUM_FORMATS 3 static XF86VideoFormatRec Formats[NUM_FORMATS] = @@ -471,7 +599,9 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen) adapt->flags = 0; adapt->name = "Radeon Textured Video"; adapt->nEncodings = 1; - if (IS_R500_3D) + if (IS_R600_3D) + adapt->pEncodings = DummyEncodingR600; + else if (IS_R500_3D) adapt->pEncodings = DummyEncodingR500; else adapt->pEncodings = DummyEncoding; @@ -483,7 +613,7 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen) pPortPriv = (RADEONPortPrivPtr)(&adapt->pPortPrivates[num_texture_ports]); - if (IS_R300_3D || IS_R500_3D) { + if (IS_R300_3D || IS_R500_3D || IS_R600_3D) { adapt->pAttributes = Attributes_r300; adapt->nAttributes = NUM_ATTRIBUTES_R300; } else { |