Index: radeon_video.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c,v retrieving revision 1.27 diff -u -r1.27 radeon_video.c --- radeon_video.c 11 Sep 2005 20:58:53 -0000 1.27 +++ radeon_video.c 27 Nov 2006 19:35:17 -0000 @@ -2100,6 +2101,61 @@ } } +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(); +} + +#if 0 static void RADEON_420_422( unsigned int *d, unsigned char *s1, @@ -2114,6 +2170,7 @@ n--; } } +#endif static void @@ -2190,6 +2247,7 @@ } } +#if 0 static void RADEONCopyMungedData( ScrnInfoPtr pScrn, @@ -2285,6 +2343,7 @@ #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 @@ -2400,6 +2459,7 @@ 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, @@ -2413,7 +2473,8 @@ int 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; @@ -2427,9 +2488,14 @@ CARD32 scale_cntl; double dsr; int tap_set; + int is_planar; - 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: @@ -2510,7 +2576,6 @@ i=i/2; } - h_inc_d = src_w; h_inc_d = h_inc_d/drw_w; /* we could do a tad better - but why @@ -2524,7 +2589,8 @@ 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; @@ -2542,10 +2608,26 @@ /* keep everything in 16.16 */ - offset1 += ((left >> 16) & ~7) << 1; - offset2 += ((left >> 16) & ~7) << 1; - offset3 += ((left >> 16) & ~7) << 1; - offset4 += ((left >> 16) & ~7) << 1; + if (is_planar) { + offset1 += (left & ~15); + offset2 += ((left >> 1) & ~15); + offset3 += ((left >> 1) & ~15); + offset4 += (left & ~15); + offset5 += ((left >> 1) & ~15); + offset6 += ((left >> 1) & ~15); + offset2 |= RADEON_VIF_BUF0_PITCH_SEL; + offset3 |= RADEON_VIF_BUF0_PITCH_SEL; + offset5 |= RADEON_VIF_BUF0_PITCH_SEL; + offset6 |= RADEON_VIF_BUF0_PITCH_SEL; + } + else { + offset1 += (left & ~7) << 1; + offset2 += (left & ~7) << 1; + offset3 += (left & ~7) << 1; + offset4 += (left & ~7) << 1; + offset5 += (left & ~7) << 1; + offset6 += (left & ~7) << 1; + } if (info->IsSecondary) { offset1 += info->FbMapSize; @@ -2566,6 +2648,16 @@ 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)- 1) << 16); + } + else { + p23_v_accum_init = 0; + p23_blank_lines = 0; + } + left = (left >> 16) & 7; RADEONWaitForFifo(pScrn, 2); @@ -2573,18 +2665,7 @@ if (info->accelOn) RADEON_SYNC(info, pScrn); while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & (1 << 3))); - dsr=(double)(1<<0xC)/h_inc; - if(dsr<0.25)dsr=0.25; - if(dsr>1.0)dsr=1.0; - tap_set=(int)((dsr-0.25)*100); - for(i=0;i<5;i++){ - OUTREG(RADEON_OV0_FOUR_TAP_COEF_0+i*4, (TapCoeffs[tap_set].coeff[i][0] &0xf) | - ((TapCoeffs[tap_set].coeff[i][1] &0x7f)<<8) | - ((TapCoeffs[tap_set].coeff[i][2] &0x7f)<<16) | - ((TapCoeffs[tap_set].coeff[i][3] &0xf)<<24)); - } - - RADEONWaitForFifo(pScrn, 14); + RADEONWaitForFifo(pScrn, 10); OUTREG(RADEON_OV0_H_INC, h_inc | ((h_inc_uv >> 1) << 16)); OUTREG(RADEON_OV0_STEP_BY, step_by_y | (step_by_uv << 8)); @@ -2644,25 +2725,27 @@ ((TapCoeffs[tap_set].coeff[i][3] &0xf)<<24)); } - RADEONWaitForFifo(pScrn, 10); + RADEONWaitForFifo(pScrn, 12); 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, 0x00000fff | 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; - 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); - - 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); + src_w >>= 1; + OUTREG(RADEON_OV0_P2_X_START_END, (src_w + left - 1) | (((left >> 1) & 7) << 16)); + OUTREG(RADEON_OV0_P3_X_START_END, (src_w + left - 1) | (((left >> 1) & 7) << 16)); + 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, 12); + 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 @@ -2685,9 +2768,11 @@ | 0x10000000 | scale_cntl); break; - case FOURCC_YUY2: case FOURCC_YV12: case FOURCC_I420: + OUTREG(RADEON_OV0_SCALE_CNTL, RADEON_SCALER_SOURCE_YUV12 | scale_cntl); + break; + case FOURCC_YUY2: default: OUTREG(RADEON_OV0_SCALE_CNTL, RADEON_SCALER_SOURCE_VYUY422 | ((info->ChipFamily>=CHIP_FAMILY_R200) ? RADEON_SCALER_TEMPORAL_DEINT :0) @@ -2714,8 +2799,9 @@ RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; INT32 xa, xb, ya, yb; unsigned char *dst_start; - int new_size, offset, s2offset, s3offset; + int new_size, offset, s1offset, s2offset, s3offset; int srcPitch, srcPitch2, dstPitch; + int d1line, d2line, d3line; int top, left, npixels, nlines, bpp; BoxRec dstBox; CARD32 tmp; @@ -2735,7 +2821,8 @@ */ /* make the compiler happy */ - s2offset = s3offset = srcPitch2 = 0; + s1offset = s2offset = s3offset = srcPitch2 = 0; + d2line = d3line = 0; if(src_w > (drw_w << 4)) drw_w = src_w >> 4; @@ -2793,11 +2880,9 @@ break; case FOURCC_YV12: case FOURCC_I420: - dstPitch = ((width << 1) + 63) & ~63; + /* working, but bw only */ + dstPitch = ((width + 31) & ~31); srcPitch = (width + 3) & ~3; - s2offset = srcPitch * height; - srcPitch2 = ((width >> 1) + 3) & ~3; - s3offset = (srcPitch2 * (height >> 1)) + s2offset; break; case FOURCC_UYVY: case FOURCC_YUY2: @@ -2808,6 +2893,9 @@ } new_size = dstPitch * height; + if (id == FOURCC_YV12 || id == FOURCC_I420) { + new_size *= 2; + } pPriv->video_offset = RADEONAllocateMemory(pScrn, &pPriv->video_memory, (pPriv->doubleBuffer ? (new_size * 2) : new_size)); @@ -2831,20 +2919,33 @@ 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); + + d1line = top * dstPitch; + d2line = src_h * dstPitch + (d1line >> 2) - d1line; + d3line = d2line + ((src_h * dstPitch) >> 2); + + s1offset = (top * srcPitch) + left; + s2offset = s1offset + (srcPitch * height); + srcPitch2 = ((width >> 1) + 3) & ~3; + s3offset = s2offset + ((srcPitch2 * height) >> 1); + /* hmm I think it should be the other way round strange */ + if(id == FOURCC_YV12) { + tmp = s2offset; + s2offset = s3offset; + s3offset = tmp; + } + + nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; +/* RADEONCopyDataPlanar(pScrn, + buf + s1offset, buf + s2offset, buf + s3offset, + dst_start, dst_start + d2line, dst_start + d3line, + srcPitch, srcPitch2, dstPitch, nlines, npixels);*/ + RADEONCopyData(pScrn, buf + s1offset, 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: @@ -2880,7 +2981,10 @@ xf86XVFillKeyHelper(pScrn->pScreen, 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; @@ -3133,6 +3237,7 @@ 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); @@ -3413,7 +3518,9 @@ xf86XVFillKeyHelper(pScrn->pScreen, 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);