xserver: Branch 'transform-proposal' - 5 commits

Keith Packard keithp at kemper.freedesktop.org
Fri Mar 21 03:16:43 PDT 2008


 hw/xfree86/modes/xf86Crtc.c    |   14 +-
 hw/xfree86/modes/xf86Cursors.c |   22 +--
 hw/xfree86/modes/xf86RandR12.c |    4 
 hw/xfree86/modes/xf86Rotate.c  |    2 
 randr/Makefile.am              |    4 
 randr/mirandr.c                |    2 
 randr/randrstr.h               |   22 ---
 randr/rrcrtc.c                 |  230 +-----------------------------------
 randr/rrinfo.c                 |    2 
 randr/rrtransform.c            |  260 +++++++++++++++++++++++++++++++++++++++++
 randr/rrtransform.h            |   75 +++++++++++
 render/matrix.c                |   58 +++------
 render/picturestr.h            |    5 
 13 files changed, 395 insertions(+), 305 deletions(-)

New commits:
commit 16ff2196e2223a4eb419487979123620deb742e6
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 03:16:09 2008 -0700

    Be careful about copying transforms around; they have allocated memory.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 165b9c7..73e67d0 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -271,7 +271,10 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
     saved_x = crtc->x;
     saved_y = crtc->y;
     saved_rotation = crtc->rotation;
-    saved_transform = crtc->transform;
+    if (crtc->transformPresent) {
+	RRTransformInit (&saved_transform);
+	RRTransformCopy (&saved_transform, &crtc->transform);
+    }
     saved_transform_present = crtc->transformPresent;
 
     /* Update crtc values up front so the driver can rely on them for mode
@@ -283,7 +286,6 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
     crtc->rotation = rotation;
     if (transform) {
 	RRTransformCopy (&crtc->transform, transform);
-	crtc->transform = *transform;
 	crtc->transformPresent = TRUE;
     } else
 	crtc->transformPresent = FALSE;
@@ -380,7 +382,8 @@ done:
 	crtc->y = saved_y;
 	crtc->rotation = saved_rotation;
 	crtc->mode = saved_mode;
-	crtc->transform = saved_transform;
+	if (saved_transform_present)
+	    RRTransformCopy (&crtc->transform, &saved_transform);
 	crtc->transformPresent = saved_transform_present;
     }
 
commit 6acc7e9f650465c06d3e9e7b7e59498024e61827
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 03:15:00 2008 -0700

    Fix rotated/reflected cursor positions.
    
    Doing projective transforms required repositioning the cursor using the
    hotspot, but that requires relocating the upper left corner in terms of said
    hotspot.

diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 6f20f63..a72cd6d 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -328,23 +328,23 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 
 	v.v[0] = x + ScreenPriv->HotX; v.v[1] = y + ScreenPriv->HotY; v.v[2] = 1;
 	pict_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
-	x = floor (v.v[0] + 0.5) - ScreenPriv->HotX;
-	y = floor (v.v[1] + 0.5) - ScreenPriv->HotY;
+	x = floor (v.v[0] + 0.5);
+	y = floor (v.v[1] + 0.5);
+	/*
+	 * Transform position of cursor upper left corner
+	 */
+	xf86_crtc_rotate_coord_back (crtc->rotation,
+				     cursor_info->MaxWidth,
+				     cursor_info->MaxHeight,
+				     ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy);
+	x -= dx;
+	y -= dy;
    }
     else
     {
 	x -= crtc->x;
 	y -= crtc->y;
     }
-    /*
-     * Transform position of cursor upper left corner
-     */
-    xf86_crtc_rotate_coord_back (crtc->rotation,
-				 cursor_info->MaxWidth,
-				 cursor_info->MaxHeight,
-				 0, 0, &dx, &dy);
-    x -= dx;
-    y -= dy;
 
     /*
      * Disable the cursor when it is outside the viewport
commit ea5aeee7b909b2d8d1103322f13134eb2f1d0255
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 03:14:47 2008 -0700

    rrtransform needs randrstr to get RANDR_INTERFACE defines

diff --git a/randr/rrtransform.c b/randr/rrtransform.c
index f9934d7..836a7ae 100644
--- a/randr/rrtransform.c
+++ b/randr/rrtransform.c
@@ -20,6 +20,7 @@
  * OF THIS SOFTWARE.
  */
 
+#include "randrstr.h"
 #include "rrtransform.h"
 
 void
commit f4d97752536f7c0091760f5f31b66db1a4b2d770
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 02:39:49 2008 -0700

    Create rrtransform.[ch]. Add RRTransform argument to RRCrtcNotify.
    
    Instead of using a separate function to notify DIX about transform changes,
    add the transform to RRCrtcNotify so that the whole Crtc state changes
    atomically.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index f1b8a8d..165b9c7 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -282,6 +282,7 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
     crtc->y = y;
     crtc->rotation = rotation;
     if (transform) {
+	RRTransformCopy (&crtc->transform, transform);
 	crtc->transform = *transform;
 	crtc->transformPresent = TRUE;
     } else
@@ -367,10 +368,6 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
 	if (output->crtc == crtc)
 	    output->funcs->commit(output);
     }
-#ifdef RANDR_12_INTERFACE
-    if (crtc->randr_crtc)
-	RRCrtcSetTransform (crtc->randr_crtc, transform);
-#endif
 
     /* XXX free adjustedmode */
     ret = TRUE;
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 26c8e0c..2c8bfff 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -732,7 +732,9 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
 	}
     }
     ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
-			rotation, numOutputs, randr_outputs);
+			rotation, 
+			crtc->transformPresent ? &crtc->transform : NULL,
+			numOutputs, randr_outputs);
     xfree(randr_outputs);
     return ret;
 }
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index c4a2e4d..8925fad 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -379,7 +379,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     if (crtc->transformPresent)
 	transform = &crtc->transform;
 
-    if (!RRComputeTransform (crtc->x, crtc->y,
+    if (!RRTransformCompute (crtc->x, crtc->y,
 			     crtc->mode.HDisplay, crtc->mode.VDisplay,
 			     crtc->rotation,
 			     transform,
diff --git a/randr/Makefile.am b/randr/Makefile.am
index 20b0f72..3d16ede 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -20,7 +20,9 @@ librandr_la_SOURCES =	\
 	rrpointer.c	\
 	rrproperty.c	\
 	rrscreen.c	\
-	rrsdispatch.c
+	rrsdispatch.c	\
+	rrtransform.h	\
+	rrtransform.c
 
 if XINERAMA
 librandr_la_SOURCES += ${XINERAMA_SRCS}
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 7777853..05375e4 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -159,7 +159,7 @@ miRandRInit (ScreenPtr pScreen)
 	return FALSE;
     if (!RROutputSetConnection (output, RR_Connected))
 	return FALSE;
-    RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
+    RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output);
 #endif
     return TRUE;
 }
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 089f960..5f664e3 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -43,6 +43,7 @@
 #include "pixmapstr.h"
 #include "extnsionst.h"
 #include "servermd.h"
+#include "rrtransform.h"
 #include <X11/extensions/randr.h>
 #include <X11/extensions/randrproto.h>
 #ifdef RENDER
@@ -75,7 +76,6 @@ typedef struct _rrPropertyValue	RRPropertyValueRec, *RRPropertyValuePtr;
 typedef struct _rrProperty	RRPropertyRec, *RRPropertyPtr;
 typedef struct _rrCrtc		RRCrtcRec, *RRCrtcPtr;
 typedef struct _rrOutput	RROutputRec, *RROutputPtr;
-typedef struct _rrTransform	RRTransformRec, *RRTransformPtr;
 
 struct _rrMode {
     int		    refcnt;
@@ -102,17 +102,6 @@ struct _rrProperty {
     RRPropertyValueRec	current, pending;
 };
 
-struct _rrTransform {
-    PictTransform   transform;
-    struct pict_f_transform f_transform;
-    struct pict_f_transform f_inverse;
-    PictFilterPtr   filter;
-    xFixed	    *params;
-    int		    nparams;
-    int		    width;
-    int		    height;
-};
-
 struct _rrCrtc {
     RRCrtc	    id;
     ScreenPtr	    pScreen;
@@ -554,6 +543,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      int	    x,
 	      int	    y,
 	      Rotation	    rotation,
+	      RRTransformPtr transform,
 	      int	    numOutputs,
 	      RROutputPtr   *outputs);
 
@@ -615,7 +605,7 @@ RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
  * Return TRUE if the resulting transform is not a simple translation.
  */
 Bool
-RRComputeTransform (int			    x,
+RRTransformCompute (int			    x,
 		    int			    y,
 		    int			    width,
 		    int			    height,
@@ -633,12 +623,6 @@ RRTransformPtr
 RRCrtcGetTransform (RRCrtcPtr crtc);
 
 /*
- * Mark the pending transform as current
- */
-void
-RRCrtcSetTransform (RRCrtcPtr crtc, RRTransformPtr transform);
-
-/*
  * Check whether the pending and current transforms are the same
  */
 Bool
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index d59a0c4..14654ff 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -48,69 +48,6 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
     }
 }
 
-static void
-RRTransformInit (RRTransformPtr transform)
-{
-    PictureTransformInitIdentity (&transform->transform);
-    pict_f_transform_init_identity (&transform->f_transform);
-    pict_f_transform_init_identity (&transform->f_inverse);
-    transform->filter = NULL;
-    transform->params = NULL;
-    transform->nparams = 0;
-}
-
-static Bool
-RRTransformSetFilter (RRTransformPtr	dst,
-		      PictFilterPtr	filter,
-		      xFixed		*params,
-		      int		nparams,
-		      int		width,
-		      int		height)
-{
-    xFixed  *new_params;
-
-    if (nparams)
-    {
-	new_params = xalloc (nparams * sizeof (xFixed));
-	if (!new_params)
-	    return FALSE;
-	memcpy (new_params, params, nparams * sizeof (xFixed));
-    }
-    else
-	new_params = NULL;
-    if (dst->params)
-	xfree (dst->params);
-    dst->filter = filter;
-    dst->params = new_params;
-    dst->nparams = nparams;
-    dst->width = width;
-    dst->height = height;
-    return TRUE;
-}
-
-static Bool
-RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
-{
-    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;
-}
-
 /*
  * Create a CRTC
  */
@@ -196,6 +133,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      int	    x,
 	      int	    y,
 	      Rotation	    rotation,
+	      RRTransformPtr transform,
 	      int	    numOutputs,
 	      RROutputPtr   *outputs)
 {
@@ -291,6 +229,10 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	crtc->rotation = rotation;
 	RRCrtcChanged (crtc, TRUE);
     }
+    if (!RRTransformEqual (transform, &crtc->client_current_transform)) {
+	RRTransformCopy (&crtc->client_current_transform, transform);
+	RRCrtcChanged (crtc, TRUE);
+    }
     return TRUE;
 }
 
@@ -391,7 +333,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 
 		if (!mode)
 		{
-		    RRCrtcNotify (crtc, NULL, x, y, rotation, 0, NULL);
+		    RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL);
 		    ret = TRUE;
 		}
 		else
@@ -417,7 +359,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 		     */
 		    if (ret)
 		    {
-			RRCrtcNotify (crtc, mode, x, y, rotation, 1, outputs);
+			RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs);
 			RRScreenSizeNotify (pScreen);
 		    }
 		}
@@ -450,27 +392,6 @@ RRCrtcGetTransform (RRCrtcPtr crtc)
 }
 
 /*
- * Called when driver applies a transform to a crtc
- */
-void
-RRCrtcSetTransform (RRCrtcPtr crtc, RRTransformPtr transform)
-{
-    if (!crtc->mode)
-	return;
-
-    RRTransformCopy (&crtc->client_current_transform, transform);
-
-    RRComputeTransform (crtc->x, crtc->y,
-			crtc->mode->mode.width,
-			crtc->mode->mode.height,
-			crtc->rotation,
-			transform,
-			&crtc->transform,
-			&crtc->f_transform,
-			&crtc->f_inverse);
-}
-
-/*
  * Check whether the pending and current transforms are the same
  */
 Bool
@@ -674,141 +595,6 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
     return Success;
 }
 
-#define F(x)	IntToxFixed(x)
-
-/*
- * Compute the complete transformation matrix including
- * client-specified transform, rotation/reflection values and the crtc 
- * offset.
- *
- * Return TRUE if the resulting transform is not a simple translation.
- */
-Bool
-RRComputeTransform (int			    x,
-		    int			    y,
-		    int			    width,
-		    int			    height,
-		    Rotation		    rotation,
-		    RRTransformPtr	    rr_transform,
-
-		    PictTransformPtr	    transform,
-		    struct pict_f_transform *f_transform,
-		    struct pict_f_transform *f_inverse)
-{
-    PictTransform	    inverse;
-
-    PictureTransformInitIdentity (transform);
-    PictureTransformInitIdentity (&inverse);
-    pict_f_transform_init_identity (f_transform);
-    pict_f_transform_init_identity (f_inverse);
-    if (rotation != RR_Rotate_0)
-    {
-	double	f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
-	double	f_scale_x, f_scale_y, f_scale_dx, f_scale_dy;
-	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
-	xFixed	scale_x, scale_y, scale_dx, scale_dy;
-
-	/* rotation */
-	switch (rotation & 0xf) {
-	default:
-	case RR_Rotate_0:
-	    f_rot_cos = 1;	    f_rot_sin = 0;
-	    f_rot_dx  = 0;	    f_rot_dy  = 0;
-	    rot_cos = F ( 1);	    rot_sin = F ( 0);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
-	    break;
-	case RR_Rotate_90:
-	    f_rot_cos = 0;	    f_rot_sin = 1;
-	    f_rot_dx  = height;	    f_rot_dy  = 0;
-	    rot_cos = F ( 0);	    rot_sin = F ( 1);
-	    rot_dx =  F ( height);  rot_dy  = F (0);
-	    break;
-	case RR_Rotate_180:
-	    f_rot_cos = -1;	    f_rot_sin = 0;
-	    f_rot_dx  = width;	    f_rot_dy  = height;
-	    rot_cos = F (-1);	    rot_sin = F ( 0);
-	    rot_dx  = F (width);   rot_dy  = F ( height);
-	    break;
-	case RR_Rotate_270:
-	    f_rot_cos = 0;	    f_rot_sin = -1;
-	    f_rot_dx  = 0;	    f_rot_dy  = width;
-	    rot_cos = F ( 0);	    rot_sin = F (-1);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( width);
-	    break;
-	}
-	
-	PictureTransformRotate (&inverse, transform, rot_cos, rot_sin);
-	PictureTransformTranslate (&inverse, transform, rot_dx, rot_dy);
-	pict_f_transform_rotate (f_inverse, f_transform, f_rot_cos, f_rot_sin);
-	pict_f_transform_translate (f_inverse, f_transform, f_rot_dx, f_rot_dy);
-
-	/* reflection */
-	f_scale_x = 1;
-	f_scale_dx = 0;
-	f_scale_y = 1;
-	f_scale_dy = 0;
-	scale_x = F (1);
-	scale_dx = 0;
-	scale_y = F (1);
-	scale_dy = 0;
-	if (rotation & RR_Reflect_X)
-	{
-	    f_scale_x = -1;
-	    scale_x = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
-		f_scale_dx = width;
-		scale_dx = F(width);
-	    } else {
-		f_scale_dx = height;
-		scale_dx = F(height);
-	    }
-	}
-	if (rotation & RR_Reflect_Y)
-	{
-	    f_scale_y = -1;
-	    scale_y = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
-		f_scale_dy = height;
-		scale_dy = F(height);
-	    } else {
-		f_scale_dy = width;
-		scale_dy = F(width);
-	    }
-	}
-	
-	PictureTransformScale (&inverse, transform, scale_x, scale_y);
-	pict_f_transform_scale (f_inverse, f_transform, f_scale_x, f_scale_y);
-	PictureTransformTranslate (&inverse, transform, scale_dx, scale_dy);
-	pict_f_transform_translate (f_inverse, f_transform, f_scale_dx, f_scale_dy);
-    }
-    
-#ifdef RANDR_12_INTERFACE
-    if (rr_transform)
-    {
-        PictureTransformMultiply (transform, transform, &rr_transform->transform);
-	pict_f_transform_multiply (f_transform, f_transform, &rr_transform->f_transform);
-	pict_f_transform_multiply (f_inverse, &rr_transform->f_inverse, f_inverse);
-    }
-#endif
-    /*
-     * Compute the class of the resulting transform
-     */
-    if (PictureTransformIsIdentity (transform))
-    {
-	PictureTransformInitTranslate (transform, F ( x), F ( y));
-
-	pict_f_transform_init_translate (f_transform, F( x), F( y));
-	pict_f_transform_init_translate (f_inverse,   F(-x), F(-y));
-	return FALSE;
-    }
-    else
-    {
-	PictureTransformTranslate (&inverse, transform, x, y);
-	pict_f_transform_translate (f_inverse, f_transform, x, y);
-	return TRUE;
-    }
-}
-
 /*
  * Initialize crtc type
  */
@@ -1116,7 +902,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    PictTransform transform;
 	    struct pict_f_transform f_transform, f_inverse;
 
-	    RRComputeTransform (stuff->x, stuff->y,
+	    RRTransformCompute (stuff->x, stuff->y,
 				mode->mode.width, mode->mode.height,
 				rotation,
 				&crtc->client_pending_transform,
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 7e77d39..38314de 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -170,7 +170,7 @@ RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
     /* notice current mode */
     if (newMode)
 	RRCrtcNotify (crtc, newMode, 0, 0, pScrPriv->rotation,
-		      1, &output);
+		      NULL, 1, &output);
 }
 #endif
 
diff --git a/randr/rrtransform.c b/randr/rrtransform.c
new file mode 100644
index 0000000..f9934d7
--- /dev/null
+++ b/randr/rrtransform.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright © 2007 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "rrtransform.h"
+
+void
+RRTransformInit (RRTransformPtr transform)
+{
+    PictureTransformInitIdentity (&transform->transform);
+    pict_f_transform_init_identity (&transform->f_transform);
+    pict_f_transform_init_identity (&transform->f_inverse);
+    transform->filter = NULL;
+    transform->params = NULL;
+    transform->nparams = 0;
+}
+
+void
+RRTransformFini (RRTransformPtr transform)
+{
+    if (transform->params)
+	xfree (transform->params);
+}
+
+Bool
+RRTransformEqual (RRTransformPtr a, RRTransformPtr b)
+{
+    if (a && PictureTransformIsIdentity (&a->transform))
+	a = NULL;
+    if (b && PictureTransformIsIdentity (&b->transform))
+	b = NULL;
+    if (a == NULL && b == NULL)
+	return TRUE;
+    if (a == NULL || b == NULL)
+	return FALSE;
+    if (memcmp (&a->transform, &b->transform, sizeof (a->transform)) != 0)
+	return FALSE;
+    if (a->filter != b->filter)
+	return FALSE;
+    if (a->nparams != b->nparams)
+	return FALSE;
+    if (memcmp (a->params, b->params, a->nparams * sizeof (xFixed)) != 0)
+	return FALSE;
+    return TRUE;
+}
+
+Bool
+RRTransformSetFilter (RRTransformPtr	dst,
+		      PictFilterPtr	filter,
+		      xFixed		*params,
+		      int		nparams,
+		      int		width,
+		      int		height)
+{
+    xFixed  *new_params;
+
+    if (nparams)
+    {
+	new_params = xalloc (nparams * sizeof (xFixed));
+	if (!new_params)
+	    return FALSE;
+	memcpy (new_params, params, nparams * sizeof (xFixed));
+    }
+    else
+	new_params = NULL;
+    if (dst->params)
+	xfree (dst->params);
+    dst->filter = filter;
+    dst->params = new_params;
+    dst->nparams = nparams;
+    dst->width = width;
+    dst->height = height;
+    return TRUE;
+}
+
+Bool
+RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
+{
+    if (src && PictureTransformIsIdentity (&src->transform))
+	src = NULL;
+
+    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;
+}
+
+#define F(x)	IntToxFixed(x)
+
+/*
+ * Compute the complete transformation matrix including
+ * client-specified transform, rotation/reflection values and the crtc 
+ * offset.
+ *
+ * Return TRUE if the resulting transform is not a simple translation.
+ */
+Bool
+RRTransformCompute (int			    x,
+		    int			    y,
+		    int			    width,
+		    int			    height,
+		    Rotation		    rotation,
+		    RRTransformPtr	    rr_transform,
+
+		    PictTransformPtr	    transform,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse)
+{
+    PictTransform	    t_transform, inverse;
+    struct pict_f_transform tf_transform, tf_inverse;
+
+    if (!transform) transform = &t_transform;
+    if (!f_transform) f_transform = &tf_transform;
+    if (!f_inverse) f_inverse = &tf_inverse;
+
+    PictureTransformInitIdentity (transform);
+    PictureTransformInitIdentity (&inverse);
+    pict_f_transform_init_identity (f_transform);
+    pict_f_transform_init_identity (f_inverse);
+    if (rotation != RR_Rotate_0)
+    {
+	double	f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
+	double	f_scale_x, f_scale_y, f_scale_dx, f_scale_dy;
+	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
+	xFixed	scale_x, scale_y, scale_dx, scale_dy;
+
+	/* rotation */
+	switch (rotation & 0xf) {
+	default:
+	case RR_Rotate_0:
+	    f_rot_cos = 1;	    f_rot_sin = 0;
+	    f_rot_dx  = 0;	    f_rot_dy  = 0;
+	    rot_cos = F ( 1);	    rot_sin = F ( 0);
+	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
+	    break;
+	case RR_Rotate_90:
+	    f_rot_cos = 0;	    f_rot_sin = 1;
+	    f_rot_dx  = height;	    f_rot_dy  = 0;
+	    rot_cos = F ( 0);	    rot_sin = F ( 1);
+	    rot_dx =  F ( height);  rot_dy  = F (0);
+	    break;
+	case RR_Rotate_180:
+	    f_rot_cos = -1;	    f_rot_sin = 0;
+	    f_rot_dx  = width;	    f_rot_dy  = height;
+	    rot_cos = F (-1);	    rot_sin = F ( 0);
+	    rot_dx  = F (width);   rot_dy  = F ( height);
+	    break;
+	case RR_Rotate_270:
+	    f_rot_cos = 0;	    f_rot_sin = -1;
+	    f_rot_dx  = 0;	    f_rot_dy  = width;
+	    rot_cos = F ( 0);	    rot_sin = F (-1);
+	    rot_dx  = F ( 0);	    rot_dy  = F ( width);
+	    break;
+	}
+	
+	PictureTransformRotate (transform, &inverse, rot_cos, rot_sin);
+	PictureTransformTranslate (transform, &inverse, rot_dx, rot_dy);
+	pict_f_transform_rotate (f_transform, f_inverse, f_rot_cos, f_rot_sin);
+	pict_f_transform_translate (f_transform, f_inverse, f_rot_dx, f_rot_dy);
+
+	/* reflection */
+	f_scale_x = 1;
+	f_scale_dx = 0;
+	f_scale_y = 1;
+	f_scale_dy = 0;
+	scale_x = F (1);
+	scale_dx = 0;
+	scale_y = F (1);
+	scale_dy = 0;
+	if (rotation & RR_Reflect_X)
+	{
+	    f_scale_x = -1;
+	    scale_x = F(-1);
+	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
+		f_scale_dx = width;
+		scale_dx = F(width);
+	    } else {
+		f_scale_dx = height;
+		scale_dx = F(height);
+	    }
+	}
+	if (rotation & RR_Reflect_Y)
+	{
+	    f_scale_y = -1;
+	    scale_y = F(-1);
+	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
+		f_scale_dy = height;
+		scale_dy = F(height);
+	    } else {
+		f_scale_dy = width;
+		scale_dy = F(width);
+	    }
+	}
+	
+	PictureTransformScale (transform, &inverse, scale_x, scale_y);
+	pict_f_transform_scale (f_transform, f_inverse, f_scale_x, f_scale_y);
+	PictureTransformTranslate (transform, &inverse, scale_dx, scale_dy);
+	pict_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
+    }
+    
+#ifdef RANDR_12_INTERFACE
+    if (rr_transform)
+    {
+        PictureTransformMultiply (transform, transform, &rr_transform->transform);
+	pict_f_transform_multiply (f_transform, f_transform, &rr_transform->f_transform);
+	pict_f_transform_multiply (f_inverse, &rr_transform->f_inverse, f_inverse);
+    }
+#endif
+    /*
+     * Compute the class of the resulting transform
+     */
+    if (PictureTransformIsIdentity (transform))
+    {
+	PictureTransformInitTranslate (transform, F ( x), F ( y));
+
+	pict_f_transform_init_translate (f_transform, F( x), F( y));
+	pict_f_transform_init_translate (f_inverse,   F(-x), F(-y));
+	return FALSE;
+    }
+    else
+    {
+	PictureTransformTranslate (&inverse, transform, x, y);
+	pict_f_transform_translate (f_inverse, f_transform, x, y);
+	return TRUE;
+    }
+}
+
diff --git a/randr/rrtransform.h b/randr/rrtransform.h
new file mode 100644
index 0000000..92d3ee7
--- /dev/null
+++ b/randr/rrtransform.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2007 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _RRTRANSFORM_H_
+#define _RRTRANSFORM_H_
+
+#include <X11/extensions/randr.h>
+#include "picturestr.h"
+
+typedef struct _rrTransform	RRTransformRec, *RRTransformPtr;
+
+struct _rrTransform {
+    PictTransform   transform;
+    struct pict_f_transform f_transform;
+    struct pict_f_transform f_inverse;
+    PictFilterPtr   filter;
+    xFixed	    *params;
+    int		    nparams;
+    int		    width;
+    int		    height;
+};
+
+void
+RRTransformInit (RRTransformPtr transform);
+
+void
+RRTransformFini (RRTransformPtr transform);
+
+Bool
+RRTransformEqual (RRTransformPtr a, RRTransformPtr b);
+
+Bool
+RRTransformSetFilter (RRTransformPtr	dst,
+		      PictFilterPtr	filter,
+		      xFixed		*params,
+		      int		nparams,
+		      int		width,
+		      int		height);
+
+Bool
+RRTransformCopy (RRTransformPtr dst, RRTransformPtr src);
+
+Bool
+RRTransformCompute (int			    x,
+		    int			    y,
+		    int			    width,
+		    int			    height,
+		    Rotation		    rotation,
+		    RRTransformPtr	    rr_transform,
+
+		    PictTransformPtr	    transform,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse);
+
+
+#endif /* _RRTRANSFORM_H_ */
commit adae56729790c784c6349f9f34228d307d2c4790
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 02:35:28 2008 -0700

    Avoid overflow in PictureTransformPoint. Fix PictureTransformIsIdentity.
    
    PictureTransformPoint computes homogeneous coordinates internally, but fails
    to handle intermediate values larger than 16.16. Use 64 bit intermediate
    values while computing the final result at 16.16 and only complain if that
    result is too large.
    
    PictureTransformIsIdentity was completely wrong -- it was not checking for
    identity transforms at all.

diff --git a/render/matrix.c b/render/matrix.c
index a4cde4f..603281e 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -50,6 +50,8 @@ PictureTransformInitIdentity (PictTransformPtr matrix)
 	matrix->matrix[i][i] = F(1);
 }
 
+typedef xFixed_32_32	xFixed_34_30;
+
 _X_EXPORT Bool
 PictureTransformPoint3d (PictTransformPtr transform,
                          PictVectorPtr	vector)
@@ -78,7 +80,6 @@ PictureTransformPoint3d (PictTransformPtr transform,
     return TRUE;
 }
 
-
 _X_EXPORT Bool
 PictureTransformPoint (PictTransformPtr transform,
 		       PictVectorPtr	vector)
@@ -86,30 +87,27 @@ PictureTransformPoint (PictTransformPtr transform,
     PictVector	    result;
     int		    i, j;
     xFixed_32_32    partial;
-    xFixed_48_16    v;
+    xFixed_34_30    v[3];
+    xFixed_48_16    quo;
 
     for (j = 0; j < 3; j++)
     {
-	v = 0;
+	v[j] = 0;
 	for (i = 0; i < 3; i++)
 	{
-	    partial = ((xFixed_48_16) transform->matrix[j][i] * 
-		       (xFixed_48_16) vector->vector[i]);
-	    v += partial >> 16;
+	    partial = ((xFixed_32_32) transform->matrix[j][i] * 
+		       (xFixed_32_32) vector->vector[i]);
+	    v[j] += partial >> 2;
 	}
-	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
-	    return FALSE;
-	result.vector[j] = (xFixed) v;
     }
-    if (!result.vector[2])
+    if (!v[2])
 	return FALSE;
     for (j = 0; j < 2; j++)
     {
-	partial = (xFixed_48_16) result.vector[j] << 16;
-	v = partial / result.vector[2];
-	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
+	quo = v[j] / (v[2] >> 16);
+	if (quo > MAX_FIXED_48_16 || quo < MIN_FIXED_48_16)
 	    return FALSE;
-	vector->vector[j] = (xFixed) v;
+	vector->vector[j] = (xFixed) quo;
     }
     vector->vector[2] = xFixed1;
     return TRUE;
@@ -296,29 +294,15 @@ within_epsilon (xFixed a, xFixed b, xFixed epsilon)
 _X_EXPORT Bool
 PictureTransformIsIdentity(PictTransform *t)
 {
-    return (IsUnit (t->matrix[0][0]) &&
-	    IsUnit (t->matrix[0][1]) &&
-            IsInt  (t->matrix[0][2]) &&
-	    IsUnit (t->matrix[1][0]) &&
-	    IsUnit (t->matrix[1][1]) &&
-            IsInt  (t->matrix[1][2]) &&
-            IsZero (t->matrix[2][0]) &&
-            IsZero (t->matrix[2][1]) &&
-	    IsOne  (t->matrix[2][2]));
-}
-
-_X_EXPORT Bool
-PictureTransformIsUnit(PictTransform *t)
-{
-    return (IsSame (t->matrix[0][0],t->matrix[1][1]) &&
+    return (IsSame (t->matrix[0][0], t->matrix[1][1]) &&
 	    IsSame (t->matrix[0][0], t->matrix[2][2]) &&
-            !IsZero (t->matrix[0][0]) &&
+	    !IsZero (t->matrix[0][0]) &&
 	    IsZero (t->matrix[0][1]) &&
-            IsZero (t->matrix[0][2]) &&
-            IsZero (t->matrix[1][0]) &&
-            IsZero (t->matrix[1][2]) &&
-            IsZero (t->matrix[2][0]) &&
-            IsZero (t->matrix[2][1]));
+	    IsZero (t->matrix[0][2]) &&
+	    IsZero (t->matrix[1][0]) &&
+	    IsZero (t->matrix[1][2]) &&
+	    IsZero (t->matrix[2][0]) &&
+	    IsZero (t->matrix[2][1]));
 }
 
 _X_EXPORT Bool
@@ -334,11 +318,11 @@ PictureTransformIsScale(PictTransform *t)
 	    
 	     IsZero (t->matrix[2][0]) &&
 	     IsZero (t->matrix[2][1]) &&
-	     IsOne (t->matrix[2][2]));
+	    !IsZero (t->matrix[2][2]));
 }
 
 _X_EXPORT Bool
-PictureTransformIsTranslate(PictTransform *t)
+PictureTransformIsIntTranslate(PictTransform *t)
 {
     return ( IsOne  (t->matrix[0][0]) &&
 	     IsZero (t->matrix[0][1]) &&
diff --git a/render/picturestr.h b/render/picturestr.h
index c2647cb..c993e93 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -737,13 +737,10 @@ Bool
 PictureTransformIsIdentity(PictTransform *t);
 
 Bool
-PictureTransformIsUnit(PictTransform *t);
-
-Bool
 PictureTransformIsScale(PictTransform *t);
 
 Bool
-PictureTransformIsTranslate (PictTransform *t);
+PictureTransformIsIntTranslate (PictTransform *t);
 
 Bool
 PictureTransformIsInverse(PictTransform *t, PictTransform *i);


More information about the xorg-commit mailing list