diff options
author | Alex Deucher <alex@botch2.com> | 2007-08-16 21:55:14 -0400 |
---|---|---|
committer | Alex Deucher <alex@botch2.com> | 2007-08-16 21:55:14 -0400 |
commit | a90d675832ddb02c81ace010ccbf02619b70edac (patch) | |
tree | 2a6ef595ea6fd08870e43e2d011636e01782a5c1 /src/radeon_video.c | |
parent | 5793e8753d11432bf95c7c6dd80c811e16aba058 (diff) |
RADEON: fix Xv clipping and overlay sourcing
- Basically just copied from the intel driver. I'm planning to push
this to the server soon, but add it now to get things working
and to provide compat for older servers.
- Overlay crtc source control attribute now called XV_CRTC
The old attribute XV_SWITCHCRT has been removed. If anyone cares,
we can add it back as an alias to XV_CRTC
XV_CRTC: -1 auto, 0 crtc0, 1 crtc1
Diffstat (limited to 'src/radeon_video.c')
-rw-r--r-- | src/radeon_video.c | 233 |
1 files changed, 159 insertions, 74 deletions
diff --git a/src/radeon_video.c b/src/radeon_video.c index dbf66dac..a38931c8 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -106,7 +106,7 @@ static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer; static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity; static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults; static Atom xvGamma, xvColorspace; -static Atom xvSwitchCRT; +static Atom xvCRTC; static Atom xvEncoding, xvFrequency, xvVolume, xvMute, xvDecBrightness, xvDecContrast, xvDecHue, xvDecColor, xvDecSaturation, xvTunerStatus, xvSAP, xvOverlayDeinterlacingMethod, @@ -119,6 +119,114 @@ static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode; #define GET_PORT_PRIVATE(pScrn) \ (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) +static void +radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) +{ + dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; + dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; + dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; + + if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; +} + +static void +radeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->enabled) { + crtc_box->x1 = crtc->x; + crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); + crtc_box->y1 = crtc->y; + crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static int +radeon_box_area(BoxPtr box) +{ + return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); +} + +static xf86CrtcPtr +radeon_covering_crtc(ScrnInfoPtr pScrn, + BoxPtr box, + xf86CrtcPtr desired, + BoxPtr crtc_box_ret) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc, best_crtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + best_crtc = NULL; + best_coverage = 0; + crtc_box_ret->x1 = 0; + crtc_box_ret->x2 = 0; + crtc_box_ret->y1 = 0; + crtc_box_ret->y2 = 0; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + radeon_crtc_box(crtc, &crtc_box); + radeon_box_intersect(&cover_box, &crtc_box, box); + coverage = radeon_box_area(&cover_box); + if (coverage && crtc == desired) { + *crtc_box_ret = crtc_box; + return crtc; + } else if (coverage > best_coverage) { + *crtc_box_ret = crtc_box; + best_crtc = crtc; + best_coverage = coverage; + } + } + return best_crtc; +} + +static Bool +radeon_clip_video_helper(ScrnInfoPtr pScrn, + xf86CrtcPtr *crtc_ret, + xf86CrtcPtr desired_crtc, + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height) +{ + Bool ret; + RegionRec crtc_region_local; + RegionPtr crtc_region = reg; + + /* + * For overlay video, compute the relevant CRTC and + * clip video to that + */ + if (crtc_ret) { + BoxRec crtc_box; + xf86CrtcPtr crtc = radeon_covering_crtc(pScrn, dst, + desired_crtc, + &crtc_box); + + if (crtc) { + REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); + crtc_region = &crtc_region_local; + REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); + } + *crtc_ret = crtc; + } + + ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, + crtc_region, width, height); + + if (crtc_region != reg) + REGION_UNINIT (pScreen, &crtc_region_local); + + return ret; +} #ifdef USE_EXA static void @@ -226,7 +334,7 @@ static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, - {XvSettable | XvGettable, 0, 1, "XV_SWITCHCRT"}, + {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, }; @@ -257,7 +365,7 @@ static XF86AttributeRec Attributes[NUM_DEC_ATTRIBUTES+1] = {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, - {XvSettable | XvGettable, 0, 1, "XV_SWITCHCRT"}, + {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, @@ -1082,7 +1190,7 @@ RADEONResetVideo(ScrnInfoPtr pScrn) xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); - xvSwitchCRT = MAKE_ATOM("XV_SWITCHCRT"); + xvCRTC = MAKE_ATOM("XV_CRTC"); xvOvAlpha = MAKE_ATOM("XV_OVERLAY_ALPHA"); xvGrAlpha = MAKE_ATOM("XV_GRAPHICS_ALPHA"); @@ -1295,11 +1403,8 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) pPriv->currentBuffer = 0; pPriv->autopaint_colorkey = TRUE; pPriv->gamma = 1000; - if (info->OverlayOnCRTC2) - pPriv->crt2 = TRUE; - else - pPriv->crt2 = FALSE; - + pPriv->desired_crtc = NULL; + pPriv->ov_alpha = 255; pPriv->gr_alpha = 255; pPriv->alpha_mode = 0; @@ -1324,24 +1429,14 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) * 0 for PIXCLK < 175Mhz, and 1 (divide by 2) * for higher clocks, sure makes life nicer */ + dot_clock = info->ModeReg.dot_clock_freq; - /* Figure out which head we are on */ - if (info->OverlayOnCRTC2) - dot_clock = info->ModeReg.dot_clock_freq_2; - else - dot_clock = info->ModeReg.dot_clock_freq; - - if(dot_clock < 17500) + if (dot_clock < 17500) info->ecp_div = 0; else info->ecp_div = 1; ecp = (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (info->ecp_div << 8); -#if 0 - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, info->ecp_div); -#endif - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || (info->ChipFamily == CHIP_FAMILY_RS200) || (info->ChipFamily == CHIP_FAMILY_RS300)) { @@ -1353,7 +1448,6 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, ecp); - /* Decide on tuner type */ if((info->tunerType<0) && (info->MM_TABLE_valid)) { pPriv->tuner_type = info->MM_TABLE.tuner_type; @@ -1657,14 +1751,15 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, RADEONSetColorKey (pScrn, pPriv->colorKey); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } - else if(attribute == xvSwitchCRT) + else if(attribute == xvCRTC) { - pPriv->crt2 = ClipValue (value, 0, 1); - pPriv->crt2 = value; - if (pPriv->crt2) - info->OverlayOnCRTC2 = TRUE; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + if ((value < -1) || (value > xf86_config->num_crtc)) + return BadValue; + if (value < 0) + pPriv->desired_crtc = NULL; else - info->OverlayOnCRTC2 = FALSE; + pPriv->desired_crtc = xf86_config->crtc[value]; } else if(attribute == xvOvAlpha) { @@ -1854,8 +1949,16 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->doubleBuffer ? 1 : 0; else if(attribute == xvColorKey) *value = pPriv->colorKey; - else if(attribute == xvSwitchCRT) - *value = pPriv->crt2 ? 1 : 0; + else if(attribute == xvCRTC) { + int c; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + for (c = 0; c < xf86_config->num_crtc; c++) + if (xf86_config->crtc[c] == pPriv->desired_crtc) + break; + if (c == xf86_config->num_crtc) + c = -1; + *value = c; + } else if(attribute == xvOvAlpha) *value = pPriv->ov_alpha; else if(attribute == xvGrAlpha) @@ -2388,7 +2491,8 @@ RADEONFreeMemory( static void RADEONDisplayVideo( ScrnInfoPtr pScrn, - RADEONPortPrivPtr pPriv, + xf86CrtcPtr crtc, + RADEONPortPrivPtr pPriv, int id, int offset1, int offset2, int offset3, int offset4, @@ -2425,10 +2529,10 @@ RADEONDisplayVideo( int predownscale=0; int src_w_d; int leftuv = 0; - xf86CrtcPtr crtc; DisplayModePtr mode; RADEONOutputPrivatePtr radeon_output; xf86OutputPtr output; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; is_rgb=0; is_planar=0; switch(id){ @@ -2451,7 +2555,7 @@ RADEONDisplayVideo( workarounds for chip erratas */ /* Figure out which head we are on for dot clock */ - if (info->OverlayOnCRTC2) + if (radeon_crtc->crtc_id == 1) dot_clock = info->ModeReg.dot_clock_freq_2; else dot_clock = info->ModeReg.dot_clock_freq; @@ -2476,11 +2580,6 @@ RADEONDisplayVideo( v_inc_shift = 20; y_mult = 1; - if (info->OverlayOnCRTC2) - crtc = xf86_config->crtc[1]; - else - crtc = xf86_config->crtc[0]; - mode = &crtc->mode; if (mode->Flags & V_INTERLACE) @@ -2494,6 +2593,7 @@ RADEONDisplayVideo( output = xf86_config->output[i]; if (output->crtc == crtc) { radeon_output = output->driver_private; + break; } } @@ -2653,7 +2753,7 @@ RADEONDisplayVideo( * rendering for the second head. */ - if (info->OverlayOnCRTC2) { + if (radeon_crtc->crtc_id == 1) { x_off = 0; OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 + x_off) | ((dstBox->y1*y_mult) << 16))); @@ -2731,6 +2831,7 @@ RADEONDisplayVideo( | ((info->ChipFamily >= CHIP_FAMILY_R200) ? RADEON_SCALER_TEMPORAL_DEINT : 0); break; } + OUTREG(RADEON_OV0_SCALE_CNTL, scale_cntl); OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0); } @@ -2804,16 +2905,10 @@ RADEONPutImage( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - RADEONChooseOverlayCRTC(pScrn, &dstBox); - - if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, - clipBoxes, width, height)) - return Success; - - if (info->OverlayOnCRTC2) - crtc = xf86_config->crtc[1]; - else - crtc = xf86_config->crtc[0]; + if (!radeon_clip_video_helper(pScrn, &crtc, pPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, + clipBoxes, width, height)) + return Success; dstBox.x1 -= crtc->x; dstBox.x2 -= crtc->x; @@ -2942,7 +3037,7 @@ RADEONPutImage( /* 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, + RADEONDisplayVideo(pScrn, crtc, 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); @@ -3183,17 +3278,11 @@ RADEONDisplaySurface( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - RADEONChooseOverlayCRTC(pScrn, &dstBox); - - if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, - surface->width, surface->height)) - return Success; + if (!radeon_clip_video_helper(pScrn, &crtc, portPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, clipBoxes, + surface->width, surface->height)) + return Success; - if (info->OverlayOnCRTC2) - crtc = xf86_config->crtc[1]; - else - crtc = xf86_config->crtc[0]; - dstBox.x1 -= crtc->x; dstBox.x2 -= crtc->x; dstBox.y1 -= crtc->y; @@ -3203,7 +3292,7 @@ RADEONDisplaySurface( /* this isn't needed */ RADEONResetVideo(pScrn); #endif - RADEONDisplayVideo(pScrn, portPriv, surface->id, + RADEONDisplayVideo(pScrn, crtc, portPriv, surface->id, surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], @@ -3283,6 +3372,7 @@ RADEONPutVideo( int mult; int vbi_line_width, vbi_start, vbi_end; xf86CrtcPtr crtc; + RADEONCrtcPrivatePtr radeon_crtc; RADEON_SYNC(info, pScrn); /* @@ -3320,19 +3410,14 @@ RADEONPutVideo( vbi_line_width = 798*2; if(width<=640) - vbi_line_width = 0x640; /* 1600 actually */ - else - vbi_line_width = 2000; /* might need adjustment */ - - RADEONChooseOverlayCRTC(pScrn, &dstBox); - - if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) - return Success; - - if (info->OverlayOnCRTC2) - crtc = xf86_config->crtc[1]; + vbi_line_width = 0x640; /* 1600 actually */ else - crtc = xf86_config->crtc[0]; + vbi_line_width = 2000; /* might need adjustment */ + + if (!radeon_clip_video_helper(pScrn, &crtc, pPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, + clipBoxes, width, height)) + return Success; dstBox.x1 -= crtc->x; dstBox.x2 -= crtc->x; @@ -3487,7 +3572,7 @@ RADEONPutVideo( RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes); } - RADEONDisplayVideo(pScrn, pPriv, id, offset1+top*srcPitch, offset2+top*srcPitch, + RADEONDisplayVideo(pScrn, crtc, 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); |