diff --git a/src/radeon_video.c b/src/radeon_video.c index 6a910a1..f479944 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -2095,6 +2095,7 @@ #endif } } + #ifdef XF86DRI static void RADEON_420_422( unsigned int *d, @@ -2188,6 +2189,63 @@ #endif } } +#if 0 +static void +RADEONCopyDataPlanar(ScrnInfoPtr pScrn, + unsigned char *src1, + unsigned char *src2, + unsigned char *src3, + unsigned char *dst1, + unsigned char *dst2, + unsigned char *dst3, + int srcPitch, + int srcPitch2, + int dstPitch, + int h, + int w) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int count; + + count = h; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "src1 %x src2 %x src3 %x dst1 %x dst2 %x dst3 %x\n", + src1, src2, src3, dst1, dst2, dst3); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "srcPitch %d srcPitch2 %d dstPitch %d h %d w %d\n", + srcPitch, srcPitch2, dstPitch, h, w); + + + while (count--) { + memcpy(dst1, src1, w); + src1 += srcPitch; + dst1 += dstPitch; + } + + w >>= 1; + h >>= 1; + dstPitch >>= 1; + + count = h; + + while (count--) { + memcpy(dst2, src2, w); + src2 += srcPitch2; + dst2 += dstPitch; + } + + count = h; + + while (count--) { + memcpy(dst3, src3, w); + src3 += srcPitch2; + dst3 += dstPitch; + } + + FLUSH_RING(); +} +#endif + +#if 0 static void RADEONCopyMungedData( ScrnInfoPtr pScrn, @@ -2286,6 +2344,7 @@ #if X_BYTE_ORDER == X_BIG_ENDIAN #endif } } +#endif /* Allocates memory, either by resizing the allocation pointed to by mem_struct, * or by freeing mem_struct (if non-NULL) and allocating a new space. The size @@ -2401,6 +2460,7 @@ RADEONDisplayVideo( int id, int offset1, int offset2, int offset3, int offset4, + int offset5, int offset6, short width, short height, int pitch, int left, int right, int top, @@ -2414,7 +2474,8 @@ RADEONDisplayVideo( CARD32 v_inc, h_inc, h_inc_uv, step_by_y, step_by_uv, tmp; double h_inc_d; int p1_h_accum_init, p23_h_accum_init; - int p1_v_accum_init; + int p1_v_accum_init, p23_v_accum_init; + int p23_blank_lines; int ecp_div; int v_inc_shift; int y_mult; @@ -2424,6 +2485,7 @@ RADEONDisplayVideo( CARD32 dot_clock; DisplayModePtr overlay_mode; int is_rgb; + int is_planar; int i; CARD32 scale_cntl; double dsr; @@ -2431,8 +2493,12 @@ RADEONDisplayVideo( int predownscale=0; int src_w_d; - is_rgb=0; + is_rgb=0; is_planar=0; switch(id){ + case FOURCC_I420: + case FOURCC_YV12: + is_planar=1; + break; case FOURCC_RGBA32: case FOURCC_RGB24: case FOURCC_RGBT16: @@ -2537,7 +2603,8 @@ #endif step_by_y++; step_by_uv = step_by_y; h_inc >>= 1; - } + } + h_inc_uv = h_inc>>(step_by_uv-step_by_y); h_inc = h_inc * h_inc_d; h_inc_uv = h_inc_uv * h_inc_d; @@ -2564,7 +2631,14 @@ #endif offset2 += ((left >> 16) & ~7) << 1; offset3 += ((left >> 16) & ~7) << 1; offset4 += ((left >> 16) & ~7) << 1; - + offset5 += ((left >> 16) & ~7) << 1; + offset6 += ((left >> 16) & ~7) << 1; + if (is_planar) { + offset2 |= RADEON_VIF_BUF0_PITCH_SEL; + offset3 |= RADEON_VIF_BUF0_PITCH_SEL; + offset5 |= RADEON_VIF_BUF0_PITCH_SEL; + offset6 |= RADEON_VIF_BUF0_PITCH_SEL; + } if (info->IsSecondary) { offset1 += info->FbMapSize; offset2 += info->FbMapSize; @@ -2584,6 +2658,16 @@ #endif p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | (((deinterlacing_method!=METHOD_WEAVE)&&!is_rgb)?0x03:0x01); + if (is_planar) { + p23_v_accum_init = ((tmp << 4) & 0x03ff8000) | + ((deinterlacing_method != METHOD_WEAVE) ? 0x03 : 0x01); + p23_blank_lines = (((src_h >> 1)- 1) << 16); + } + else { + p23_v_accum_init = 0; + p23_blank_lines = 0; + } + left = (left >> 16) & 7; RADEONWaitForFifo(pScrn, 2); @@ -2654,25 +2738,27 @@ #endif ((TapCoeffs[tap_set].coeff[i][3] &0xf)<<24)); } - RADEONWaitForFifo(pScrn, 10); + RADEONWaitForFifo(pScrn, 11); OUTREG(RADEON_OV0_V_INC, v_inc); OUTREG(RADEON_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); + OUTREG(RADEON_OV0_P23_BLANK_LINES_AT_TOP, 0x000007ff | p23_blank_lines); OUTREG(RADEON_OV0_VID_BUF_PITCH0_VALUE, pitch); - OUTREG(RADEON_OV0_VID_BUF_PITCH1_VALUE, pitch); + OUTREG(RADEON_OV0_VID_BUF_PITCH1_VALUE, is_planar ? pitch >> 1 : pitch); OUTREG(RADEON_OV0_P1_X_START_END, (src_w + left - 1) | (left << 16)); - left >>= 1; src_w >>= 1; + src_w >>= 1; left >> 1; OUTREG(RADEON_OV0_P2_X_START_END, (src_w + left - 1) | (left << 16)); OUTREG(RADEON_OV0_P3_X_START_END, (src_w + left - 1) | (left << 16)); - OUTREG(RADEON_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0); - OUTREG(RADEON_OV0_VID_BUF1_BASE_ADRS, offset2 & 0xfffffff0); - OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset3 & 0xfffffff0); + OUTREG(RADEON_OV0_VID_BUF0_BASE_ADRS, offset1); + OUTREG(RADEON_OV0_VID_BUF1_BASE_ADRS, offset2); + OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset3); RADEONWaitForFifo(pScrn, 9); - OUTREG(RADEON_OV0_VID_BUF3_BASE_ADRS, offset4 & 0xfffffff0); - OUTREG(RADEON_OV0_VID_BUF4_BASE_ADRS, offset1 & 0xfffffff0); - OUTREG(RADEON_OV0_VID_BUF5_BASE_ADRS, offset2 & 0xfffffff0); + OUTREG(RADEON_OV0_VID_BUF3_BASE_ADRS, offset4); + OUTREG(RADEON_OV0_VID_BUF4_BASE_ADRS, offset5); + OUTREG(RADEON_OV0_VID_BUF5_BASE_ADRS, offset6); OUTREG(RADEON_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); OUTREG(RADEON_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); + OUTREG(RADEON_OV0_P23_V_ACCUM_INIT, p23_v_accum_init); OUTREG(RADEON_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); scale_cntl = RADEON_SCALER_ADAPTIVE_DEINT | RADEON_SCALER_DOUBLE_BUFFER @@ -2690,9 +2776,11 @@ #endif case FOURCC_RGBT16: scale_cntl |= RADEON_SCALER_SOURCE_15BPP | RADEON_SCALER_LIN_TRANS_BYPASS; break; - case FOURCC_YUY2: case FOURCC_YV12: case FOURCC_I420: + scale_cntl |= RADEON_SCALER_SOURCE_YUV12; + break; + case FOURCC_YUY2: default: scale_cntl |= RADEON_SCALER_SOURCE_VYUY422 | ((info->ChipFamily >= CHIP_FAMILY_R200) ? RADEON_SCALER_TEMPORAL_DEINT : 0); @@ -2733,6 +2821,7 @@ RADEONPutImage( unsigned char *dst_start; int new_size, offset, s2offset, s3offset; int srcPitch, srcPitch2, dstPitch; + int d2line, d3line; int top, left, npixels, nlines, bpp; BoxRec dstBox; CARD32 tmp; @@ -2750,6 +2839,7 @@ RADEONPutImage( /* make the compiler happy */ s2offset = s3offset = srcPitch2 = 0; + d2line = d3line = 0; if(src_w > (drw_w << 4)) drw_w = src_w >> 4; @@ -2804,11 +2894,8 @@ RADEONPutImage( break; case FOURCC_YV12: case FOURCC_I420: - dstPitch = ((width << 1) + 63) & ~63; - srcPitch = (width + 3) & ~3; - s2offset = srcPitch * height; - srcPitch2 = ((width >> 1) + 3) & ~3; - s3offset = (srcPitch2 * (height >> 1)) + s2offset; + dstPitch = ((width + 31) & ~31); + srcPitch = width; break; case FOURCC_UYVY: case FOURCC_YUY2: @@ -2819,6 +2906,9 @@ RADEONPutImage( } new_size = dstPitch * height; + if (id == FOURCC_YV12 || id == FOURCC_I420) { + new_size += (dstPitch >> 1) * height; + } pPriv->video_offset = RADEONAllocateMemory(pScrn, &pPriv->video_memory, (pPriv->doubleBuffer ? (new_size * 2) : new_size)); @@ -2840,22 +2930,35 @@ RADEONPutImage( dst_start = info->FB + offset; switch(id) { - case FOURCC_YV12: - case FOURCC_I420: - top &= ~1; - dst_start += left << 1; - tmp = ((top >> 1) * srcPitch2) + (left >> 1); - s2offset += tmp; - s3offset += tmp; - if(id == FOURCC_I420) { - tmp = s2offset; - s2offset = s3offset; - s3offset = tmp; - } - nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; - RADEONCopyMungedData(pScrn, buf + (top * srcPitch) + left, - buf + s2offset, buf + s3offset, dst_start, - srcPitch, srcPitch2, dstPitch, nlines, npixels); + case FOURCC_YV12: + case FOURCC_I420: + buf += (top * srcPitch) + left; + /* odd number of lines? That'll probably not work */ + nlines = ((yb + 0xffff) >> 16) - top; + dst_start += left; + d2line = height * dstPitch; + d3line = d3line + (height >> 1) * (dstPitch >> 1); + + s2offset = (srcPitch * height); + /* odd number of pixels? See above... */ + srcPitch2 = width >> 1; + s3offset = s2offset + srcPitch2 * (height >> 1); + if(id == FOURCC_YV12) { + tmp = s2offset; + s2offset = s3offset; + s3offset = tmp; + } + +/* RADEONCopyDataPlanar(pScrn, + buf, buf + s2offset, buf + s3offset, + dst_start, dst_start + d2line, dst_start + d3line, + srcPitch, srcPitch2, dstPitch, nlines, npixels);*/ + RADEONCopyData(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels, 1); + RADEONCopyData(pScrn, buf + s2offset, dst_start + d2line, srcPitch2, + dstPitch >> 1, nlines >> 1, npixels >> 1, 1); + RADEONCopyData(pScrn, buf + s3offset, dst_start + d3line, srcPitch2, + dstPitch >> 1, nlines >> 1, npixels >> 1, 1); + break; case FOURCC_RGBT16: case FOURCC_RGB16: @@ -2891,7 +2994,10 @@ RADEONPutImage( RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes); } - RADEONDisplayVideo(pScrn, pPriv, id, offset, offset, offset, offset, width, height, dstPitch, + /* FIXME: someone should look at these offsets, I don't think it makes sense how + they are handled throughout the source. */ + RADEONDisplayVideo(pScrn, pPriv, id, offset, offset + d2line, offset + d3line, + offset, offset + d2line, offset + d3line, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h, METHOD_BOB); pPriv->videoStatus = CLIENT_VIDEO_ON; @@ -3156,6 +3262,7 @@ #endif RADEONDisplayVideo(pScrn, portPriv, surface->id, surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], + surface->offsets[0], surface->offsets[0], surface->width, surface->height, surface->pitches[0], xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h, METHOD_BOB); @@ -3437,7 +3544,9 @@ RADEONPutVideo( RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes); } - RADEONDisplayVideo(pScrn, pPriv, id, offset1+top*srcPitch, offset2+top*srcPitch, offset3+top*srcPitch, offset4+top*srcPitch, width, height, dstPitch*mult/2, + RADEONDisplayVideo(pScrn, pPriv, id, offset1+top*srcPitch, offset2+top*srcPitch, + offset3+top*srcPitch, offset4+top*srcPitch, offset1+top*srcPitch, + offset2+top*srcPitch, width, height, dstPitch*mult/2, xa, xb, ya, &dstBox, src_w, src_h*mult/2, drw_w, drw_h, pPriv->overlay_deinterlacing_method); RADEONWaitForFifo(pScrn, 1);