Allow drivers to set crtc transforms.

Track curent transform down in the mode setting code so that it may be set
separately from RandR.
This commit is contained in:
Keith Packard 2008-03-19 12:15:39 -07:00
parent 49db14e4ac
commit 6fe9c15731
8 changed files with 150 additions and 66 deletions

View File

@ -237,8 +237,8 @@ xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen)
* Sets the given video mode on the given crtc
*/
_X_EXPORT Bool
xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
int x, int y)
xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
RRTransformPtr transform, int x, int y)
{
ScrnInfoPtr scrn = crtc->scrn;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@ -249,6 +249,8 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
DisplayModeRec saved_mode;
int saved_x, saved_y;
Rotation saved_rotation;
RRTransformRec saved_transform;
Bool saved_transform_present;
if (crtc->funcs->set_mode_major)
return crtc->funcs->set_mode_major(crtc, mode, rotation, x, y);
@ -269,6 +271,9 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
saved_x = crtc->x;
saved_y = crtc->y;
saved_rotation = crtc->rotation;
saved_transform = crtc->transform;
saved_transform_present = crtc->transformPresent;
/* Update crtc values up front so the driver can rely on them for mode
* setting.
*/
@ -276,6 +281,11 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
crtc->x = x;
crtc->y = y;
crtc->rotation = rotation;
if (transform) {
crtc->transform = *transform;
crtc->transformPresent = TRUE;
} else
crtc->transformPresent = FALSE;
/* Shift offsets that move us out of virtual size */
if (x + mode->HDisplay > xf86_config->maxWidth ||
@ -322,9 +332,8 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
goto done;
}
if (!xf86CrtcRotate (crtc, mode, rotation)) {
if (!xf86CrtcRotate (crtc))
goto done;
}
/* Prepare the outputs and CRTCs before setting the mode. */
for (i = 0; i < xf86_config->num_output; i++) {
@ -356,17 +365,11 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
{
xf86OutputPtr output = xf86_config->output[i];
if (output->crtc == crtc)
{
output->funcs->commit(output);
#ifdef RANDR_12_INTERFACE
if (output->randr_output)
RRPostPendingProperties (output->randr_output);
#endif
}
}
#ifdef RANDR_12_INTERFACE
if (crtc->randr_crtc)
RRCrtcPostPendingTransform (crtc->randr_crtc);
RRCrtcSetTransform (crtc->randr_crtc, transform);
#endif
/* XXX free adjustedmode */
@ -380,6 +383,8 @@ done:
crtc->y = saved_y;
crtc->rotation = saved_rotation;
crtc->mode = saved_mode;
crtc->transform = saved_transform;
crtc->transformPresent = saved_transform_present;
}
if (didLock)
@ -388,6 +393,17 @@ done:
return ret;
}
/**
* Sets the given video mode on the given crtc, but without providing
* a transform
*/
_X_EXPORT Bool
xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
int x, int y)
{
return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y);
}
/*
* Output functions
*/
@ -740,12 +756,12 @@ xf86CrtcScreenInit (ScreenPtr screen)
xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 |
RR_Rotate_180 | RR_Rotate_270 |
RR_Reflect_X | RR_Reflect_Y);
xf86RandR12SetTransform (screen, TRUE);
xf86RandR12SetTransformSupport (screen, TRUE);
}
else
{
xf86RandR12SetRotations (screen, RR_Rotate_0);
xf86RandR12SetTransform (screen, FALSE);
xf86RandR12SetTransformSupport (screen, FALSE);
}
/* Wrap CreateScreenResources so we can initialize the RandR code */
@ -2236,6 +2252,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
crtc->desiredRotation = output->initial_rotation;
crtc->desiredX = output->initial_x;
crtc->desiredY = output->initial_y;
crtc->desiredTransformPresent = FALSE;
crtc->enabled = TRUE;
crtc->x = output->initial_x;
crtc->y = output->initial_y;
@ -2367,6 +2384,7 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
xf86CrtcPtr crtc = config->crtc[c];
xf86OutputPtr output = NULL;
int o;
RRTransformPtr transform;
/* Skip disabled CRTCs */
if (!crtc->enabled)
@ -2397,12 +2415,17 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
return FALSE;
crtc->desiredMode = *mode;
crtc->desiredRotation = RR_Rotate_0;
crtc->desiredTransformPresent = FALSE;
crtc->desiredX = 0;
crtc->desiredY = 0;
}
if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation,
crtc->desiredX, crtc->desiredY))
if (crtc->desiredTransformPresent)
transform = &crtc->desiredTransform;
else
transform = NULL;
if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation,
transform, crtc->desiredX, crtc->desiredY))
return FALSE;
}
@ -2531,12 +2554,13 @@ xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
crtc->enabled = FALSE;
continue;
}
if (!xf86CrtcSetMode (crtc, crtc_mode, rotation, 0, 0))
if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0))
ok = FALSE;
else
{
crtc->desiredMode = *crtc_mode;
crtc->desiredRotation = rotation;
crtc->desiredTransformPresent = FALSE;
crtc->desiredX = 0;
crtc->desiredY = 0;
}

View File

@ -313,6 +313,10 @@ struct _xf86Crtc {
int filter_width;
int filter_height;
Bool transform_in_use;
RRTransformRec transform;
Bool transformPresent;
RRTransformRec desiredTransform;
Bool desiredTransformPresent;
/**
* Bounding box in screen space
*/
@ -665,6 +669,11 @@ xf86CrtcDestroy (xf86CrtcPtr crtc);
/**
* Sets the given video mode on the given crtc
*/
Bool
xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
RRTransformPtr transform, int x, int y);
Bool
xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
int x, int y);
@ -673,7 +682,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
* Assign crtc rotation during mode set
*/
Bool
xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
xf86CrtcRotate (xf86CrtcPtr crtc);
/*
* free shadow memory allocated for all crtcs

View File

@ -569,7 +569,7 @@ xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
}
_X_EXPORT void
xf86RandR12SetTransform (ScreenPtr pScreen, Bool transforms)
xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms)
{
XF86RandRInfoPtr randrp;
#if RANDR_13_INTERFACE
@ -588,7 +588,7 @@ xf86RandR12SetTransform (ScreenPtr pScreen, Bool transforms)
for (c = 0; c < config->num_crtc; c++) {
xf86CrtcPtr crtc = config->crtc[c];
RRCrtcSetTransform (crtc->randr_crtc, transforms);
RRCrtcSetTransformSupport (crtc->randr_crtc, transforms);
}
#endif
}
@ -751,18 +751,19 @@ xf86RandRModeConvert (ScrnInfoPtr scrn,
}
static Bool
xf86RandR12CrtcSet (ScreenPtr pScreen,
RRCrtcPtr randr_crtc,
RRModePtr randr_mode,
int x,
int y,
Rotation rotation,
int num_randr_outputs,
RROutputPtr *randr_outputs)
xf86RandR12CrtcSet (ScreenPtr pScreen,
RRCrtcPtr randr_crtc,
RRModePtr randr_mode,
int x,
int y,
Rotation rotation,
int num_randr_outputs,
RROutputPtr *randr_outputs)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
xf86CrtcPtr crtc = randr_crtc->devPrivate;
RRTransformPtr transform;
Bool changed = FALSE;
int o, ro;
xf86CrtcPtr *save_crtcs;
@ -780,7 +781,11 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
if (rotation != crtc->rotation)
changed = TRUE;
if (RRCrtcPendingTransform (randr_crtc))
transform = RRCrtcGetTransform (randr_crtc);
if ((transform != NULL) != crtc->transformPresent)
changed = TRUE;
else if (transform && memcmp (&transform->transform, &crtc->transform.transform,
sizeof (transform->transform)) != 0)
changed = TRUE;
if (x != crtc->x || y != crtc->y)
@ -820,9 +825,10 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
if (randr_mode)
{
DisplayModeRec mode;
RRTransformPtr transform = RRCrtcGetTransform (randr_crtc);
xf86RandRModeConvert (pScrn, randr_mode, &mode);
if (!xf86CrtcSetMode (crtc, &mode, rotation, x, y))
if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y))
{
crtc->enabled = save_enabled;
for (o = 0; o < config->num_output; o++)
@ -838,6 +844,12 @@ xf86RandR12CrtcSet (ScreenPtr pScreen,
*/
crtc->desiredMode = mode;
crtc->desiredRotation = rotation;
if (transform) {
crtc->desiredTransform = *transform;
crtc->desiredTransformPresent = TRUE;
} else
crtc->desiredTransformPresent = FALSE;
crtc->desiredX = x;
crtc->desiredY = y;
}

View File

@ -31,7 +31,7 @@
Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen);
Bool xf86RandR12Init(ScreenPtr pScreen);
void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
void xf86RandR12SetTransform (ScreenPtr pScreen, Bool transforms);
void xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms);
Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
RRScreenSizePtr pSize);
Rotation xf86RandR12GetRotation(ScreenPtr pScreen);

View File

@ -38,6 +38,7 @@
#define xf86CrtcInUse XF86NAME(xf86CrtcInUse)
#define xf86CrtcRotate XF86NAME(xf86CrtcRotate)
#define xf86CrtcScreenInit XF86NAME(xf86CrtcScreenInit)
#define xf86CrtcSetModeTransform XF86NAME(xf86CrtcSetModeTransform)
#define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode)
#define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange)
#define xf86CVTMode XF86NAME(xf86CVTMode)

View File

@ -349,8 +349,35 @@ xf86RotateCloseScreen (ScreenPtr screen)
xf86RotateDestroy (xf86_config->crtc[c]);
}
static Bool
xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb)
{
ScrnInfoPtr pScrn = crtc->scrn;
/* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
BoxRec b;
if (!pScreen)
return TRUE;
b.x1 = 0;
b.y1 = 0;
b.x2 = crtc->mode.HDisplay;
b.y2 = crtc->mode.VDisplay;
if (crtc_to_fb)
pict_f_transform_bounds (crtc_to_fb, &b);
else {
b.x1 += crtc->x;
b.y1 += crtc->y;
b.x2 += crtc->x;
b.y2 += crtc->y;
}
return (0 <= b.x1 && b.x2 <= pScreen->width &&
0 <= b.y1 && b.y2 <= pScreen->height);
}
_X_EXPORT Bool
xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
xf86CrtcRotate (xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@ -364,20 +391,19 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
int new_width = 0;
int new_height = 0;
RRTransformPtr transform = NULL;
#ifdef RANDR_12_INTERFACE
if (crtc->randr_crtc)
transform = RRCrtcGetTransform (crtc->randr_crtc);
#endif
if (!transform ||
!RRComputeTransform (crtc->x, crtc->y,
if (crtc->transformPresent)
transform = &crtc->transform;
if (!RRComputeTransform (crtc->x, crtc->y,
crtc->mode.HDisplay, crtc->mode.VDisplay,
rotation,
crtc->rotation,
transform,
&crtc_to_fb,
&f_crtc_to_fb,
&f_fb_to_crtc))
&f_fb_to_crtc) &&
xf86CrtcFitsScreen (crtc, &f_crtc_to_fb))
{
/*
* If the untranslated transformation is the identity,
@ -400,8 +426,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
* matches the mode, not the pre-rotated copy in the
* frame buffer
*/
int width = mode->HDisplay;
int height = mode->VDisplay;
int width = crtc->mode.HDisplay;
int height = crtc->mode.VDisplay;
void *shadowData = crtc->rotatedData;
PixmapPtr shadow = crtc->rotatedPixmap;
int old_width = shadow ? shadow->drawable.width : 0;

View File

@ -545,7 +545,7 @@ RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
* Set whether transforms are allowed on a CRTC
*/
void
RRCrtcSetTransform (RRCrtcPtr crtc, Bool transforms);
RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms);
/*
* Notify the extension that the Crtc has been reconfigured,
@ -639,7 +639,7 @@ RRCrtcGetTransform (RRCrtcPtr crtc);
* Mark the pending transform as current
*/
void
RRCrtcPostPendingTransform (RRCrtcPtr crtc);
RRCrtcSetTransform (RRCrtcPtr crtc, RRTransformPtr transform);
/*
* Check whether the pending and current transforms are the same

View File

@ -91,12 +91,23 @@ RRTransformSetFilter (RRTransformPtr dst,
static Bool
RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
{
if (!RRTransformSetFilter (dst, src->filter,
src->params, src->nparams, src->width, src->height))
return FALSE;
dst->transform = src->transform;
dst->f_transform = src->f_transform;
dst->f_inverse = src->f_inverse;
if (src)
{
if (!RRTransformSetFilter (dst, src->filter,
src->params, src->nparams, src->width, src->height))
return FALSE;
dst->transform = src->transform;
dst->f_transform = src->f_transform;
dst->f_inverse = src->f_inverse;
}
else
{
if (!RRTransformSetFilter (dst, NULL, NULL, 0, 0, 0))
return FALSE;
PictureTransformInitIdentity (&dst->transform);
pict_f_transform_init_identity (&dst->f_transform);
pict_f_transform_init_identity (&dst->f_inverse);
}
return TRUE;
}
@ -170,7 +181,7 @@ RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
* Set whether transforms are allowed on a CRTC
*/
void
RRCrtcSetTransform (RRCrtcPtr crtc, Bool transforms)
RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms)
{
crtc->transforms = transforms;
}
@ -439,21 +450,21 @@ RRCrtcGetTransform (RRCrtcPtr crtc)
}
/*
* Mark the pending transform as current
* Called when driver applies a transform to a crtc
*/
void
RRCrtcPostPendingTransform (RRCrtcPtr crtc)
RRCrtcSetTransform (RRCrtcPtr crtc, RRTransformPtr transform)
{
if (!crtc->mode)
return;
RRTransformCopy (&crtc->client_current_transform,
&crtc->client_pending_transform);
RRTransformCopy (&crtc->client_current_transform, transform);
RRComputeTransform (crtc->x, crtc->y,
crtc->mode->mode.width,
crtc->mode->mode.height,
crtc->rotation,
&crtc->client_current_transform,
transform,
&crtc->transform,
&crtc->f_transform,
&crtc->f_inverse);
@ -1091,23 +1102,25 @@ ProcRRSetCrtcConfig (ClientPtr client)
}
#ifdef RANDR_12_INTERFACE
#if 0
/*
* Check screen size bounds if the DDX provides a 1.2 interface
* for setting screen size. Else, assume the CrtcSet sets
* the size along with the mode
* the size along with the mode. If the driver supports transforms,
* then it must allow crtcs to display a subset of the screen, so
* only do this check for drivers without transform support.
*/
if (pScrPriv->rrScreenSetSize)
if (pScrPriv->rrScreenSetSize && !crtc->transforms)
{
int source_width;
int source_height;
PictTransform transform, inverse;
PictTransform transform;
struct pict_f_transform f_transform, f_inverse;
RRComputeTransform (mode, stuff->rotation,
stuff->x, stuff->y,
&crtc->client_pending_transform.transform,
&crtc->client_pending_transform.inverse,
&transform, &inverse);
RRComputeTransform (stuff->x, stuff->y,
mode->mode.width, mode->mode.height,
rotation,
&crtc->client_pending_transform,
&transform, &f_transform, &f_inverse);
RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
if (stuff->x + source_width > pScreen->width)
@ -1126,7 +1139,6 @@ ProcRRSetCrtcConfig (ClientPtr client)
return BadValue;
}
}
#endif
#endif
}