[PATCH] Allow drivers to set crtc transforms.
Keith Packard
keithp at keithp.com
Fri Nov 14 14:12:49 PST 2008
Track curent transform down in the mode setting code so that it may be set
separately from RandR.
---
hw/xfree86/modes/xf86Crtc.c | 56 ++++++++++++++++++++++++++++-----------
hw/xfree86/modes/xf86Crtc.h | 11 +++++++-
hw/xfree86/modes/xf86RandR12.c | 36 +++++++++++++++++--------
hw/xfree86/modes/xf86RandR12.h | 2 +-
hw/xfree86/modes/xf86Rename.h | 1 +
hw/xfree86/modes/xf86Rotate.c | 50 +++++++++++++++++++++++++++--------
randr/randrstr.h | 4 +-
randr/rrcrtc.c | 56 ++++++++++++++++++++++++---------------
8 files changed, 150 insertions(+), 66 deletions(-)
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index f33a228..e3a852e 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -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 */
@@ -2200,6 +2216,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;
@@ -2331,6 +2348,7 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
xf86CrtcPtr crtc = config->crtc[c];
xf86OutputPtr output = NULL;
int o;
+ RRTransformPtr transform;
/* Skip disabled CRTCs */
if (!crtc->enabled)
@@ -2361,12 +2379,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;
}
@@ -2495,12 +2518,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;
}
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 026ec78..4b6f7d2 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -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
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index f247a88..49add63 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -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;
}
diff --git a/hw/xfree86/modes/xf86RandR12.h b/hw/xfree86/modes/xf86RandR12.h
index c361b47..17a2dcc 100644
--- a/hw/xfree86/modes/xf86RandR12.h
+++ b/hw/xfree86/modes/xf86RandR12.h
@@ -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);
diff --git a/hw/xfree86/modes/xf86Rename.h b/hw/xfree86/modes/xf86Rename.h
index b8c1d70..e3418ca 100644
--- a/hw/xfree86/modes/xf86Rename.h
+++ b/hw/xfree86/modes/xf86Rename.h
@@ -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)
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index efbacec..7d35c34 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -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;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 5ac983d..d4cfa67 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -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
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index d7ea6f2..091517a 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -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)
@@ -1127,7 +1140,6 @@ ProcRRSetCrtcConfig (ClientPtr client)
}
}
#endif
-#endif
}
/*
--
1.5.6.5
More information about the xorg
mailing list