xserver: Branch 'transform-proposal' - 2 commits
Keith Packard
keithp at kemper.freedesktop.org
Mon Mar 17 23:05:10 PDT 2008
randr/rrcrtc.c | 5 +--
render/matrix.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
render/picturestr.h | 3 +
3 files changed, 85 insertions(+), 3 deletions(-)
New commits:
commit 4184a2db90045c10d56faa390042ebf062a285fa
Author: Keith Packard <keithp at keithp.com>
Date: Mon Mar 17 23:04:49 2008 -0700
Compute matrix inversion instead of using wire version in RRCrtcTransformSet
It doesn't make sense to have the client invert this matrix when the server
can do so reasonably efficiently. This avoids weird fixed point rounding
errors when testing the transform against its inverse. Now to fix the
protocol.
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 9032b61..a3e2503 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -608,8 +608,6 @@ RRCrtcTransformSet (RRCrtcPtr crtc,
PictFilterPtr filter = NULL;
int width = 0, height = 0;
- if (!PictureTransformIsInverse (transform, inverse))
- return BadMatch;
if (filter_len)
{
filter = PictureFindFilter (crtc->pScreen,
@@ -1220,7 +1218,8 @@ ProcRRSetCrtcTransform (ClientPtr client)
return RRErrorBase + BadRRCrtc;
PictTransform_from_xRenderTransform (&transform, &stuff->transform);
- PictTransform_from_xRenderTransform (&inverse, &stuff->inverse);
+ if (!PictureTransformInvert (&inverse, &transform))
+ return BadMatch;
filter = (char *) (stuff + 1);
nbytes = stuff->nbytesFilter;
commit 47dcd54077b40889f604ac3ed491e2558a4587a5
Author: Keith Packard <keithp at keithp.com>
Date: Mon Mar 17 23:03:56 2008 -0700
Add matrix inversion function (uses doubles)
The obvious matrix inversion function, coded using doubles to avoid fiddling
with fixed point precision adventures.
diff --git a/render/matrix.c b/render/matrix.c
index a976304..6e50205 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -262,6 +262,86 @@ 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;
+ t->matrix[j][i] = pixman_double_to_fixed (d);
+ }
+ return TRUE;
+}
+
+static Bool
+invert (double r[3][3], double m[3][3])
+{
+ double det, norm;
+ 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];
+
+ to_doubles (m, src);
+ if (!invert (r, m))
+ return FALSE;
+ if (!from_doubles (dst, r))
+ return FALSE;
+ return TRUE;
+}
+
static Bool
within_epsilon (xFixed a, xFixed b, xFixed epsilon)
{
diff --git a/render/picturestr.h b/render/picturestr.h
index 4a07070..5db9a04 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -723,6 +723,9 @@ void
PictureTransformBounds (BoxPtr b, PictTransformPtr matrix);
Bool
+PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src);
+
+Bool
PictureTransformIsIdentity(PictTransform *t);
Bool
More information about the xorg-commit
mailing list