[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