[PATCH] Handle RandR transform matrices in floating point.

Keith Packard keithp at keithp.com
Fri Nov 14 14:12:48 PST 2008


RandR matrix computations lose too much precision in fixed point;
computations using the inverted matrix can be as much as 10 pixels off.
Convert them to double precision values and pass those around. These API
changes are fairly heavyweight; the official Render interface remains fixed
point, so the fixed point matrix comes along for the ride everywhere.
---
 hw/xfree86/modes/xf86Crtc.c    |    3 +-
 hw/xfree86/modes/xf86Crtc.h    |    3 +-
 hw/xfree86/modes/xf86Cursors.c |   16 +-
 hw/xfree86/modes/xf86Rotate.c  |  167 +++++++--------------
 randr/randrstr.h               |   27 ++--
 randr/rrcrtc.c                 |  136 ++++++++++++------
 render/matrix.c                |  324 +++++++++++++++++++++++++++++++---------
 render/picturestr.h            |   63 ++++++++
 8 files changed, 488 insertions(+), 251 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index f977152..f33a228 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -104,7 +104,8 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
     crtc->rotation = RR_Rotate_0;
     crtc->desiredRotation = RR_Rotate_0;
     PictureTransformInitIdentity (&crtc->crtc_to_framebuffer);
-    PictureTransformInitIdentity (&crtc->framebuffer_to_crtc);
+    pict_f_transform_init_identity (&crtc->f_crtc_to_framebuffer);
+    pict_f_transform_init_identity (&crtc->f_framebuffer_to_crtc);
     crtc->filter = NULL;
     crtc->params = NULL;
     crtc->nparams = 0;
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index d093b1a..026ec78 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -305,7 +305,8 @@ struct _xf86Crtc {
      * Current transformation matrix
      */
     PictTransform   crtc_to_framebuffer;
-    PictTransform   framebuffer_to_crtc;
+    struct pict_f_transform f_crtc_to_framebuffer;
+    struct pict_f_transform f_framebuffer_to_crtc;
     PictFilterPtr   filter;
     xFixed	    *params;
     int		    nparams;
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 7bf9265..4065789 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -326,15 +326,13 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 	xf86CursorScreenPtr ScreenPriv =
 	    (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
 						  xf86CursorScreenKey);
-	PictVector	v;
-	x += ScreenPriv->HotX;
-	y += ScreenPriv->HotY;
-	v.vector[0] = IntToxFixed (x); v.vector[1] = IntToxFixed (y); v.vector[2] = IntToxFixed(1);
-	PictureTransformPoint (&crtc->framebuffer_to_crtc, &v);
-	x = xFixedToInt (v.vector[0]); y = xFixedToInt (v.vector[1]);
-	x -= ScreenPriv->HotX;
-	y -= ScreenPriv->HotY;
-    }
+	struct pict_f_vector   v;
+
+	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;
+   }
     else
     {
 	x -= crtc->x;
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 7b49afa..efbacec 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -122,7 +122,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 	dst_box.x2 += crtc->filter_width >> 1;
 	dst_box.y1 -= crtc->filter_height >> 1;
 	dst_box.y2 += crtc->filter_height >> 1;
-	PictureTransformBounds (&dst_box, &crtc->framebuffer_to_crtc);
+	pict_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box);
 	CompositePicture (PictOpSrc,
 			  src, NULL, dst,
 			  dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
@@ -165,6 +165,8 @@ xf86CrtcShadowClear (xf86CrtcPtr crtc)
     xRectangle		rect;
     int			error;
 
+    if (!dst_pixmap)
+	return;
     dst = CreatePicture (None,
 			 &dst_pixmap->drawable,
 			 format,
@@ -199,7 +201,6 @@ xf86RotatePrepare (ScreenPtr pScreen)
 							     crtc->rotatedData,
 							     crtc->mode.HDisplay,
 							     crtc->mode.VDisplay);
-	    xf86CrtcShadowClear (crtc);
 	    if (!xf86_config->rotation_damage_registered)
 	    {
 		/* Hook damage to screen pixmap */
@@ -355,109 +356,33 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
     ScreenPtr		pScreen = screenInfo.screens[pScrn->scrnIndex];
-    PictTransform	crtc_to_fb, fb_to_crtc;
+    PictTransform	crtc_to_fb;
+    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
     xFixed		*new_params = NULL;
     int			new_nparams = 0;
     PictFilterPtr	new_filter = NULL;
     int			new_width = 0;
     int			new_height = 0;
-    
-    PictureTransformInitIdentity (&crtc_to_fb);
-    PictureTransformInitIdentity (&fb_to_crtc);
-    if (rotation != RR_Rotate_0)
-    {
-	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
-	xFixed	scale_x, scale_y, scale_dx, scale_dy;
-	int	mode_w = crtc->mode.HDisplay;
-	int	mode_h = crtc->mode.VDisplay;
-	
-	/* rotation */
-	switch (rotation & 0xf) {
-	default:
-	case RR_Rotate_0:
-	    rot_cos = F ( 1);	    rot_sin = F ( 0);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
-	    break;
-	case RR_Rotate_90:
-	    rot_cos = F ( 0);	    rot_sin = F ( 1);
-	    rot_dx =  F ( mode_h);  rot_dy  = F (0);
-	    break;
-	case RR_Rotate_180:
-	    rot_cos = F (-1);	    rot_sin = F ( 0);
-	    rot_dx  = F (mode_w);   rot_dy  = F ( mode_h);
-	    break;
-	case RR_Rotate_270:
-	    rot_cos = F ( 0);	    rot_sin = F (-1);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( mode_w);
-	    break;
-	}
-	
-	PictureTransformRotate (&crtc_to_fb, &fb_to_crtc, rot_cos, rot_sin);
-	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, rot_dx, rot_dy);
-
-	/* reflection */
-	scale_x = F (1);
-	scale_dx = 0;
-	scale_y = F (1);
-	scale_dy = 0;
-	if (rotation & RR_Reflect_X)
-	{
-	    scale_x = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
-		scale_dx = F(mode_w);
-	    else
-		scale_dx = F(mode_h);
-	}
-	if (rotation & RR_Reflect_Y)
-	{
-	    scale_y = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
-		scale_dy = F(mode_h);
-	    else
-		scale_dy = F(mode_w);
-	}
-	
-	PictureTransformScale (&crtc_to_fb, &fb_to_crtc, scale_x, scale_y);
-	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, scale_dx, scale_dy);
-    }
+    RRTransformPtr	transform = NULL;
     
 #ifdef RANDR_12_INTERFACE
     if (crtc->randr_crtc)
-    {
-
-	RRTransformPtr	transform = RRCrtcGetTransform (crtc->randr_crtc);
-	if (transform)
-	{
-	    if (transform->nparams) {
-		new_params = xalloc (transform->nparams * sizeof (xFixed));
-		if (new_params) {
-		    memcpy (new_params, transform->params,
-			    transform->nparams * sizeof (xFixed));
-		    new_nparams = transform->nparams;
-		    new_filter = transform->filter;
-		}
-	    } else
-		new_filter = transform->filter;
-	    if (new_filter)
-	    {
-		new_width = new_filter->width;
-		new_height = new_filter->height;
-	    }
-	    PictureTransformMultiply (&crtc_to_fb, &transform->transform, &crtc_to_fb);
-	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &transform->inverse);
-	}
-    }
+	transform = RRCrtcGetTransform (crtc->randr_crtc);
 #endif
-    /*
-     * If the untranslated transformation is the identity,
-     * disable the shadow buffer
-     */
-    if (PictureTransformIsIdentity (&crtc_to_fb))
+    if (!transform ||
+	!RRComputeTransform (crtc->x, crtc->y,
+			     crtc->mode.HDisplay, crtc->mode.VDisplay,
+			     rotation,
+			     transform,
+
+			     &crtc_to_fb,
+			     &f_crtc_to_fb,
+			     &f_fb_to_crtc))
     {
-	PictureTransformInitTranslate (&crtc_to_fb,
-				       F (-crtc->x), F (-crtc->y));
-	PictureTransformInitTranslate (&fb_to_crtc,
-				       F ( crtc->x), F ( crtc->y));
+	/*
+	 * If the untranslated transformation is the identity,
+	 * disable the shadow buffer
+	 */
 	xf86RotateDestroy (crtc);
 	crtc->transform_in_use = FALSE;
 	if (new_params)
@@ -470,24 +395,18 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     }
     else
     {
-	int width, height, old_width, old_height;
-	void *shadowData;
-	PixmapPtr shadow;
-
-	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, F(crtc->x), F(crtc->y));
-
-	/* 
+	/*
 	 * these are the size of the shadow pixmap, which
 	 * matches the mode, not the pre-rotated copy in the
 	 * frame buffer
 	 */
-	width = mode->HDisplay;
-	height = mode->VDisplay;
-	shadowData = crtc->rotatedData;
-	shadow = crtc->rotatedPixmap;
-	old_width = shadow ? shadow->drawable.width : 0;
-	old_height = shadow ? shadow->drawable.height : 0;
-	
+	int	    width = mode->HDisplay;
+	int	    height = mode->VDisplay;
+	void	    *shadowData = crtc->rotatedData;
+	PixmapPtr   shadow = crtc->rotatedPixmap;
+	int	    old_width = shadow ? shadow->drawable.width : 0;
+	int	    old_height = shadow ? shadow->drawable.height : 0;
+
 	/* Allocate memory for rotation */
 	if (old_width != width || old_height != height)
 	{
@@ -522,6 +441,27 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	    xf86_config->BlockHandler = pScreen->BlockHandler;
 	    pScreen->BlockHandler = xf86RotateBlockHandler;
 	}
+#ifdef RANDR_12_INTERFACE
+	if (transform)
+	{
+	    if (transform->nparams) {
+		new_params = xalloc (transform->nparams * sizeof (xFixed));
+		if (new_params) {
+		    memcpy (new_params, transform->params,
+			    transform->nparams * sizeof (xFixed));
+		    new_nparams = transform->nparams;
+		    new_filter = transform->filter;
+		}
+	    } else
+		new_filter = transform->filter;
+	    if (new_filter)
+	    {
+		new_width = new_filter->width;
+		new_height = new_filter->height;
+	    }
+	}
+#endif
+
 	if (0)
 	{
     bail2:
@@ -537,14 +477,13 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 								  NULL,
 								  old_width,
 								  old_height);
-	    if (new_params)
-		xfree (new_params);
 	    return FALSE;
 	}
 	crtc->transform_in_use = TRUE;
     }
     crtc->crtc_to_framebuffer = crtc_to_fb;
-    crtc->framebuffer_to_crtc = fb_to_crtc;
+    crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
+    crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
     if (crtc->params)
 	xfree (crtc->params);
     crtc->params = new_params;
@@ -556,8 +495,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     crtc->bounds.x2 = crtc->mode.HDisplay;
     crtc->bounds.y1 = 0;
     crtc->bounds.y2 = crtc->mode.VDisplay;
-    PictureTransformBounds (&crtc->bounds, &crtc_to_fb);
-    
+    pict_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds);
+
     /* All done */
     return TRUE;
 }
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 792c3d6..5ac983d 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -107,7 +107,8 @@ struct _rrProperty {
 
 struct _rrTransform {
     PictTransform   transform;
-    PictTransform   inverse;
+    struct pict_f_transform f_transform;
+    struct pict_f_transform f_inverse;
     PictFilterPtr   filter;
     xFixed	    *params;
     int		    nparams;
@@ -134,7 +135,8 @@ struct _rrCrtc {
     RRTransformRec  client_pending_transform;
     RRTransformRec  client_current_transform;
     PictTransform   transform;
-    PictTransform   inverse;
+    struct pict_f_transform f_transform;
+    struct pict_f_transform f_inverse;
 };
 
 struct _rrOutput {
@@ -616,14 +618,16 @@ RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
  * Return TRUE if the resulting transform is not a simple translation.
  */
 Bool
-RRComputeTransform (RRModePtr		mode,
-		    Rotation		rotation,
-		    int			x,
-		    int			y,
-		    PictTransformPtr	client_transform,
-		    PictTransformPtr	client_inverse,
-		    PictTransformPtr    transform,
-		    PictTransformPtr    inverse);
+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);
 
 /*
  * Return crtc transform
@@ -657,7 +661,8 @@ RRCrtcDestroy (RRCrtcPtr crtc);
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    PictTransformPtr	inverse,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse,
 		    char		*filter,
 		    int			filter_len,
 		    xFixed		*params,
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index e0fafce..d7ea6f2 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -52,7 +52,8 @@ static void
 RRTransformInit (RRTransformPtr transform)
 {
     PictureTransformInitIdentity (&transform->transform);
-    PictureTransformInitIdentity (&transform->inverse);
+    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;
@@ -94,7 +95,8 @@ RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
 			       src->params, src->nparams, src->width, src->height))
 	return FALSE;
     dst->transform = src->transform;
-    dst->inverse = src->inverse;
+    dst->f_transform = src->f_transform;
+    dst->f_inverse = src->f_inverse;
     return TRUE;
 }
 
@@ -142,7 +144,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     RRTransformInit (&crtc->client_pending_transform);
     RRTransformInit (&crtc->client_current_transform);
     PictureTransformInitIdentity (&crtc->transform);
-    PictureTransformInitIdentity (&crtc->inverse);
+    pict_f_transform_init_identity (&crtc->f_transform);
+    pict_f_transform_init_identity (&crtc->f_inverse);
 
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
@@ -441,13 +444,19 @@ RRCrtcGetTransform (RRCrtcPtr crtc)
 void
 RRCrtcPostPendingTransform (RRCrtcPtr crtc)
 {
+    if (!crtc->mode)
+	return;
+
     RRTransformCopy (&crtc->client_current_transform,
 		     &crtc->client_pending_transform);
-    RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y,
-			&crtc->client_current_transform.transform,
-			&crtc->client_current_transform.inverse,
+    RRComputeTransform (crtc->x, crtc->y,
+			crtc->mode->mode.width,
+			crtc->mode->mode.height,
+			crtc->rotation,
+			&crtc->client_current_transform,
 			&crtc->transform,
-			&crtc->inverse);
+			&crtc->f_transform,
+			&crtc->f_inverse);
 }
 
 /*
@@ -608,7 +617,8 @@ RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    PictTransformPtr	inverse,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse,
 		    char		*filter_name,
 		    int			filter_len,
 		    xFixed		*params,
@@ -648,7 +658,8 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
 	return BadAlloc;
 
     crtc->client_pending_transform.transform = *transform;
-    crtc->client_pending_transform.inverse = *inverse;
+    crtc->client_pending_transform.f_transform = *f_transform;
+    crtc->client_pending_transform.f_inverse = *f_inverse;
     return Success;
 }
 
@@ -662,78 +673,110 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
  * Return TRUE if the resulting transform is not a simple translation.
  */
 Bool
-RRComputeTransform (RRModePtr		mode,
-		    Rotation		rotation,
-		    int			x,
-		    int			y,
-		    PictTransformPtr	client_transform,
-		    PictTransformPtr	client_inverse,
-		    PictTransformPtr    transform,
-		    PictTransformPtr    inverse)
+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);
+    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;
-	int	mode_w = mode->mode.width;
-	int	mode_h = mode->mode.height;
-	
+
 	/* 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 ( mode_h);  rot_dy  = F (0);
+	    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 (mode_w);   rot_dy  = F ( mode_h);
+	    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 ( mode_w);
+	    rot_dx  = F ( 0);	    rot_dy  = F ( width);
 	    break;
 	}
 	
-	PictureTransformRotate (inverse, transform, rot_cos, rot_sin);
-	PictureTransformTranslate (inverse, transform, rot_dx, rot_dy);
+	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))
-		scale_dx = F(mode_w);
-	    else
-		scale_dx = F(mode_h);
+	    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))
-		scale_dy = F(mode_h);
-	    else
-		scale_dy = F(mode_w);
+	    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);
-	PictureTransformTranslate (inverse, transform, scale_dx, scale_dy);
+	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 (inverse, client_inverse, inverse);
-        PictureTransformMultiply (transform, transform, client_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
     /*
@@ -741,13 +784,16 @@ RRComputeTransform (RRModePtr		mode,
      */
     if (PictureTransformIsIdentity (transform))
     {
-	PictureTransformInitTranslate (inverse,   F (-x), F (-y));
 	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);
+	PictureTransformTranslate (&inverse, transform, x, y);
+	pict_f_transform_translate (f_inverse, f_transform, x, y);
 	return TRUE;
     }
 }
@@ -1045,6 +1091,7 @@ 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
@@ -1080,6 +1127,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    }
 	}
 #endif
+#endif
     }
     
     /*
@@ -1227,7 +1275,8 @@ ProcRRSetCrtcTransform (ClientPtr client)
 {
     REQUEST(xRRSetCrtcTransformReq);
     RRCrtcPtr		    crtc;
-    PictTransform	    transform, inverse;
+    PictTransform	    transform;
+    struct pict_f_transform f_transform, f_inverse;
     char		    *filter;
     int			    nbytes;
     xFixed		    *params;
@@ -1239,7 +1288,8 @@ ProcRRSetCrtcTransform (ClientPtr client)
 	return RRErrorBase + BadRRCrtc;
 
     PictTransform_from_xRenderTransform (&transform, &stuff->transform);
-    if (!PictureTransformInvert (&inverse, &transform))
+    pict_f_transform_from_pixman_transform (&f_transform, &transform);
+    if (!pict_f_transform_invert (&f_inverse, &f_transform))
 	return BadMatch;
 
     filter = (char *) (stuff + 1);
@@ -1249,7 +1299,7 @@ ProcRRSetCrtcTransform (ClientPtr client)
     if (nparams < 0)
 	return BadLength;
 
-    return RRCrtcTransformSet (crtc, &transform, &inverse,
+    return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse,
 			       filter, nbytes, params, nparams);
 }
 
diff --git a/render/matrix.c b/render/matrix.c
index 0d5d962..a4cde4f 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -262,83 +262,15 @@ PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
     }
 }
 
-static const int	a[3] = { 3, 3, 2 };
-static const int	b[3] = { 2, 1, 1 };
-
-static void
-to_doubles (double m[3][3], const PictTransformPtr t)
-{
-    int	i, j;
-
-    for (j = 0; j < 3; j++)
-	for (i = 0; i < 3; i++)
-	    m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
-}
-
-static Bool
-from_doubles (PictTransformPtr t, double m[3][3])
-{
-    int	i, j;
-
-    for (j = 0; j < 3; j++)
-	for (i = 0; i < 3; i++)
-	{
-	    double  d = m[j][i];
-	    if (d < -32767.0 || d > 32767.0)
-		return FALSE;
-	    d = d * 65536.0 + 0.5;
-	    t->matrix[j][i] = (xFixed) floor (d);
-	}
-    return TRUE;
-}
-
-static Bool
-invert (double r[3][3], double m[3][3])
-{
-    double  det;
-    int	    i, j;
-    static int	a[3] = { 2, 2, 1 };
-    static int	b[3] = { 1, 0, 0 };
-
-    det = 0;
-    for (i = 0; i < 3; i++) {
-	double	p;
-	int	ai = a[i];
-	int	bi = b[i];
-	p = m[i][0] * (m[ai][2] * m[bi][1] - m[ai][1] * m[bi][2]);
-	if (i == 1)
-	    p = -p;
-	det += p;
-    }
-    if (det == 0)
-	return FALSE;
-    det = 1/det;
-    for (j = 0; j < 3; j++) {
-	for (i = 0; i < 3; i++) {
-	    double  p;
-	    int	    ai = a[i];
-	    int	    aj = a[j];
-	    int	    bi = b[i];
-	    int	    bj = b[j];
-
-	    p = m[ai][aj] * m[bi][bj] - m[ai][bj] * m[bi][aj];
-	    if (((i + j) & 1) != 0)
-		p = -p;
-	    r[j][i] = det * p;
-	}
-    }
-    return TRUE;
-}
-
 _X_EXPORT Bool
 PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src)
 {
-    double  m[3][3], r[3][3];
+    struct pict_f_transform m, r;
 
-    to_doubles (m, src);
-    if (!invert (r, m))
+    pict_f_transform_from_pixman_transform (&m, src);
+    if (!pict_f_transform_invert (&r, &m))
 	return FALSE;
-    if (!from_doubles (dst, r))
+    if (!pixman_transform_from_pict_f_transform (dst, &r))
 	return FALSE;
     return TRUE;
 }
@@ -464,3 +396,251 @@ xRenderTransform_from_PictTransform (xRenderTransform *render,
     render->matrix33 = pict->matrix[2][2];
 }
 
+/*
+ * Floating point matrix interfaces
+ */
+
+_X_EXPORT void
+pict_f_transform_from_pixman_transform (struct pict_f_transform *ft,
+					struct pixman_transform	*t)
+{
+    int	i, j;
+
+    for (j = 0; j < 3; j++)
+	for (i = 0; i < 3; i++)
+	    ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
+}
+
+_X_EXPORT Bool
+pixman_transform_from_pict_f_transform (struct pixman_transform	*t,
+					struct pict_f_transform	*ft)
+{
+    int	i, j;
+
+    for (j = 0; j < 3; j++)
+	for (i = 0; i < 3; i++)
+	{
+	    double  d = ft->m[j][i];
+	    if (d < -32767.0 || d > 32767.0)
+		return FALSE;
+	    d = d * 65536.0 + 0.5;
+	    t->matrix[j][i] = (xFixed) floor (d);
+	}
+    return TRUE;
+}
+
+static const int	a[3] = { 3, 3, 2 };
+static const int	b[3] = { 2, 1, 1 };
+
+_X_EXPORT Bool
+pict_f_transform_invert (struct pict_f_transform *r,
+			 struct pict_f_transform *m)
+{
+    double  det;
+    int	    i, j;
+    static int	a[3] = { 2, 2, 1 };
+    static int	b[3] = { 1, 0, 0 };
+
+    det = 0;
+    for (i = 0; i < 3; i++) {
+	double	p;
+	int	ai = a[i];
+	int	bi = b[i];
+	p = m->m[i][0] * (m->m[ai][2] * m->m[bi][1] - m->m[ai][1] * m->m[bi][2]);
+	if (i == 1)
+	    p = -p;
+	det += p;
+    }
+    if (det == 0)
+	return FALSE;
+    det = 1/det;
+    for (j = 0; j < 3; j++) {
+	for (i = 0; i < 3; i++) {
+	    double  p;
+	    int	    ai = a[i];
+	    int	    aj = a[j];
+	    int	    bi = b[i];
+	    int	    bj = b[j];
+
+	    p = m->m[ai][aj] * m->m[bi][bj] - m->m[ai][bj] * m->m[bi][aj];
+	    if (((i + j) & 1) != 0)
+		p = -p;
+	    r->m[j][i] = det * p;
+	}
+    }
+    return TRUE;
+}
+
+_X_EXPORT Bool
+pict_f_transform_point (struct pict_f_transform *t,
+			struct pict_f_vector	*v)
+{
+    struct pict_f_vector    result;
+    int			    i, j;
+    double		    a;
+
+    for (j = 0; j < 3; j++)
+    {
+	a = 0;
+	for (i = 0; i < 3; i++)
+	    a += t->m[j][i] * v->v[i];
+	result.v[j] = a;
+    }
+    if (!result.v[2])
+	return FALSE;
+    for (j = 0; j < 2; j++)
+	v->v[j] = result.v[j] / result.v[2];
+    v->v[2] = 1;
+    return TRUE;
+}
+
+_X_EXPORT void
+pict_f_transform_point_3d (struct pict_f_transform *t,
+			   struct pict_f_vector	*v)
+{
+    struct pict_f_vector    result;
+    int			    i, j;
+    double		    a;
+
+    for (j = 0; j < 3; j++)
+    {
+	a = 0;
+	for (i = 0; i < 3; i++)
+	    a += t->m[j][i] * v->v[i];
+	result.v[j] = a;
+    }
+    *v = result;
+}
+
+_X_EXPORT void
+pict_f_transform_multiply (struct pict_f_transform *dst,
+			   struct pict_f_transform *l, struct pict_f_transform *r)
+{
+    struct pict_f_transform d;
+    int			    dx, dy;
+    int			    o;
+
+    for (dy = 0; dy < 3; dy++)
+	for (dx = 0; dx < 3; dx++)
+	{
+	    double v = 0;
+	    for (o = 0; o < 3; o++)
+		v += l->m[dy][o] * r->m[o][dx];
+	    d.m[dy][dx] = v;
+	}
+    *dst = d;
+}
+
+_X_EXPORT void
+pict_f_transform_init_scale (struct pict_f_transform *t, double sx, double sy)
+{
+    t->m[0][0] = sx;	t->m[0][1] = 0;	    t->m[0][2] = 0;
+    t->m[1][0] = 0;	t->m[1][1] = sy;    t->m[1][2] = 0;
+    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
+}
+
+_X_EXPORT Bool
+pict_f_transform_scale (struct pict_f_transform *forward,
+			struct pict_f_transform *reverse,
+			double sx, double sy)
+{
+    struct pict_f_transform t;
+
+    if (sx == 0 || sy == 0)
+	return FALSE;
+
+    pict_f_transform_init_scale (&t, sx, sy);
+    pict_f_transform_multiply (forward, &t, forward);
+    pict_f_transform_init_scale (&t, 1/sx, 1/sy);
+    pict_f_transform_multiply (reverse, reverse, &t);
+    return TRUE;
+}
+
+_X_EXPORT void
+pict_f_transform_init_rotate (struct pict_f_transform *t, double c, double s)
+{
+    t->m[0][0] = c;	t->m[0][1] = -s;    t->m[0][2] = 0;
+    t->m[1][0] = s;	t->m[1][1] = c;	    t->m[1][2] = 0;
+    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
+}
+
+_X_EXPORT Bool
+pict_f_transform_rotate (struct pict_f_transform *forward,
+			 struct pict_f_transform *reverse,
+			 double c, double s)
+{
+    struct pict_f_transform t;
+
+    pict_f_transform_init_rotate (&t, c, s);
+    pict_f_transform_multiply (forward, &t, forward);
+    pict_f_transform_init_rotate (&t, c, -s);
+    pict_f_transform_multiply (reverse, reverse, &t);
+    return TRUE;
+}
+
+_X_EXPORT void
+pict_f_transform_init_translate (struct pict_f_transform *t, double tx, double ty)
+{
+    t->m[0][0] = 1;	t->m[0][1] = 0;	    t->m[0][2] = tx;
+    t->m[1][0] = 0;	t->m[1][1] = 1;	    t->m[1][2] = ty;
+    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
+}
+
+_X_EXPORT Bool
+pict_f_transform_translate (struct pict_f_transform *forward,
+			    struct pict_f_transform *reverse,
+			    double tx, double ty)
+{
+    struct pict_f_transform t;
+
+    pict_f_transform_init_translate (&t, tx, ty);
+    pict_f_transform_multiply (forward, &t, forward);
+    pict_f_transform_init_translate (&t, -tx, -ty);
+    pict_f_transform_multiply (reverse, reverse, &t);
+    return TRUE;
+}
+
+_X_EXPORT Bool
+pict_f_transform_bounds (struct pict_f_transform *t, BoxPtr b)
+{
+    struct pict_f_vector    v[4];
+    int			    i;
+    int			    x1, y1, x2, y2;
+
+    v[0].v[0] = b->x1;    v[0].v[1] = b->y1;	v[0].v[2] = 1;
+    v[1].v[0] = b->x2;    v[1].v[1] = b->y1;	v[1].v[2] = 1;
+    v[2].v[0] = b->x2;    v[2].v[1] = b->y2;	v[2].v[2] = 1;
+    v[3].v[0] = b->x1;    v[3].v[1] = b->y2;	v[3].v[2] = 1;
+    for (i = 0; i < 4; i++)
+    {
+	if (!pict_f_transform_point (t, &v[i]))
+	    return FALSE;
+	x1 = floor (v[i].v[0]);
+	y1 = floor (v[i].v[1]);
+	x2 = ceil (v[i].v[0]);
+	y2 = ceil (v[i].v[1]);
+	if (i == 0)
+	{
+	    b->x1 = x1; b->y1 = y1;
+	    b->x2 = x2; b->y2 = y2;
+	}
+	else
+	{
+	    if (x1 < b->x1) b->x1 = x1;
+	    if (y1 < b->y1) b->y1 = y1;
+	    if (x2 > b->x2) b->x2 = x2;
+	    if (y2 > b->y2) b->y2 = y2;
+	}
+    }
+    return TRUE;
+}
+
+_X_EXPORT void
+pict_f_transform_init_identity (struct pict_f_transform *t)
+{
+    int	i, j;
+
+    for (j = 0; j < 3; j++)
+	for (i = 0; i < 3; i++)
+	    t->m[j][i] = i == j ? 1 : 0;
+}
diff --git a/render/picturestr.h b/render/picturestr.h
index 658e221..b18f316 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -56,6 +56,14 @@ typedef struct _PictFormat {
 typedef struct pixman_vector PictVector, *PictVectorPtr;
 typedef struct pixman_transform PictTransform, *PictTransformPtr;
 
+struct pict_f_vector {
+    double  v[3];
+};
+
+struct pict_f_transform {
+    double  m[3][3];
+};
+
 #define PICT_GRADIENT_STOPTABLE_SIZE 1024
 #define SourcePictTypeSolidFill 0
 #define SourcePictTypeLinear 1
@@ -745,4 +753,59 @@ void
 xRenderTransform_from_PictTransform (xRenderTransform *render,
 				     PictTransformPtr pict);
 
+void
+pict_f_transform_from_pixman_transform (struct pict_f_transform *ft,
+					struct pixman_transform	*t);
+
+Bool
+pixman_transform_from_pict_f_transform (struct pixman_transform	*t,
+					struct pict_f_transform	*ft);
+
+Bool
+pict_f_transform_invert (struct pict_f_transform *r,
+			 struct pict_f_transform *m);
+
+
+Bool
+pict_f_transform_point (struct pict_f_transform *t,
+			struct pict_f_vector	*v);
+
+void
+pict_f_transform_point_3d (struct pict_f_transform *t,
+			   struct pict_f_vector	*v);
+
+void
+pict_f_transform_multiply (struct pict_f_transform *dst,
+			   struct pict_f_transform *l, struct pict_f_transform *r);
+
+void
+pict_f_transform_init_scale (struct pict_f_transform *t, double sx, double sy);
+
+Bool
+pict_f_transform_scale (struct pict_f_transform *forward,
+			struct pict_f_transform *reverse,
+			double sx, double sy);
+
+void
+pict_f_transform_init_rotate (struct pict_f_transform *t, double c, double s);
+
+Bool
+pict_f_transform_rotate (struct pict_f_transform *forward,
+			 struct pict_f_transform *reverse,
+			 double c, double s);
+
+void
+pict_f_transform_init_translate (struct pict_f_transform *t, double tx, double ty);
+
+Bool
+pict_f_transform_translate (struct pict_f_transform *forward,
+			    struct pict_f_transform *reverse,
+			    double tx, double ty);
+
+Bool
+pict_f_transform_bounds (struct pict_f_transform *t, BoxPtr b);
+
+void
+pict_f_transform_init_identity (struct pict_f_transform *t);
+
 #endif /* _PICTURESTR_H_ */
-- 
1.5.6.5




More information about the xorg mailing list