summaryrefslogtreecommitdiff
path: root/src/radeon_video.c
diff options
context:
space:
mode:
authorAlex Deucher <alex@botch2.com>2007-08-16 21:55:14 -0400
committerAlex Deucher <alex@botch2.com>2007-08-16 21:55:14 -0400
commita90d675832ddb02c81ace010ccbf02619b70edac (patch)
tree2a6ef595ea6fd08870e43e2d011636e01782a5c1 /src/radeon_video.c
parent5793e8753d11432bf95c7c6dd80c811e16aba058 (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.c233
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);