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