aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/randr/rrtransform.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/randr/rrtransform.c')
-rw-r--r--xorg-server/randr/rrtransform.c620
1 files changed, 283 insertions, 337 deletions
diff --git a/xorg-server/randr/rrtransform.c b/xorg-server/randr/rrtransform.c
index f78d5f913..e1620498b 100644
--- a/xorg-server/randr/rrtransform.c
+++ b/xorg-server/randr/rrtransform.c
@@ -1,337 +1,283 @@
-/*
- * 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 "randrstr.h"
-#include "rrtransform.h"
-
-void
-RRTransformInit (RRTransformPtr transform)
-{
- pixman_transform_init_identity (&transform->transform);
- pixman_f_transform_init_identity (&transform->f_transform);
- pixman_f_transform_init_identity (&transform->f_inverse);
- transform->filter = NULL;
- transform->params = NULL;
- transform->nparams = 0;
-}
-
-void
-RRTransformFini (RRTransformPtr transform)
-{
- free(transform->params);
-}
-
-Bool
-RRTransformEqual (RRTransformPtr a, RRTransformPtr b)
-{
- if (a && pixman_transform_is_identity (&a->transform))
- a = NULL;
- if (b && pixman_transform_is_identity (&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 = malloc(nparams * sizeof (xFixed));
- if (!new_params)
- return FALSE;
- memcpy (new_params, params, nparams * sizeof (xFixed));
- }
- else
- new_params = NULL;
- free(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 && pixman_transform_is_identity (&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;
- pixman_transform_init_identity (&dst->transform);
- pixman_f_transform_init_identity (&dst->f_transform);
- pixman_f_transform_init_identity (&dst->f_inverse);
- }
- return TRUE;
-}
-
-#define F(x) IntToxFixed(x)
-
-static void
-RRTransformRescale(struct pixman_f_transform *f_transform, double limit)
-{
- double max = 0, v, scale;
- int i, j;
-
- for (j = 0; j < 3; j++)
- for (i = 0; i < 3; i++)
- if ((v = abs (f_transform->m[j][i])) > max)
- max = v;
- scale = limit / max;
- for (j = 0; j < 3; j++)
- for (i = 0; i < 3; i++)
- f_transform->m[j][i] *= scale;
-}
-
-#define EPSILON (1e-20)
-#define IS_F_SAME(a,b) (fabs((a)-(b)) < EPSILON)
-#define IS_F_ZERO(a) (fabs(a) < EPSILON)
-
-static Bool
-pict_f_transform_is_identity (const struct pixman_f_transform *t)
-{
- return (IS_F_SAME (t->m[0][0], t->m[1][1]) &&
- IS_F_SAME (t->m[0][0], t->m[2][2]) &&
- !IS_F_ZERO (t->m[0][0]) &&
- IS_F_ZERO (t->m[0][1]) &&
- IS_F_ZERO (t->m[0][2]) &&
- IS_F_ZERO (t->m[1][0]) &&
- IS_F_ZERO (t->m[1][2]) &&
- IS_F_ZERO (t->m[2][0]) &&
- IS_F_ZERO (t->m[2][1]));
-}
-
-/*
- * 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,
- struct pixman_f_transform *sprite_position_transform,
- struct pixman_f_transform *sprite_image_transform,
-
- PictTransformPtr transform,
- struct pixman_f_transform *f_transform,
- struct pixman_f_transform *f_inverse,
- struct pixman_f_transform *f_fb_to_sprite,
- struct pixman_f_transform *f_sprite_to_image,
- Bool *sprite_transform_in_use)
-{
- PictTransform t_transform, inverse;
- struct pixman_f_transform tf_transform, tf_inverse;
- struct pixman_f_transform sf_position_transform, sf_image_transform;
- struct pixman_f_transform f_image_to_sprite;
- Bool overflow = FALSE;
- Bool ret = TRUE;
-
- if (!transform) transform = &t_transform;
- if (!f_transform) f_transform = &tf_transform;
- if (!f_inverse) f_inverse = &tf_inverse;
- if (!f_fb_to_sprite) f_fb_to_sprite = &sf_position_transform;
- if (!f_sprite_to_image) f_sprite_to_image = &sf_image_transform;
-
- /* invert the sprite image transform to have it go from dest to source */
- if (!pixman_f_transform_invert (&f_image_to_sprite, f_sprite_to_image))
- pixman_f_transform_init_identity(&f_image_to_sprite);
-
- pixman_transform_init_identity (transform);
- pixman_transform_init_identity (&inverse);
- pixman_f_transform_init_identity (f_transform);
- pixman_f_transform_init_identity (f_inverse);
- pixman_f_transform_init_identity (f_fb_to_sprite);
- pixman_f_transform_init_identity (f_sprite_to_image);
- 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;
- }
-
- pixman_transform_rotate (transform, &inverse, rot_cos, rot_sin);
- pixman_transform_translate (transform, &inverse, rot_dx, rot_dy);
- pixman_f_transform_rotate (f_transform, f_inverse, f_rot_cos, f_rot_sin);
- pixman_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);
- }
- }
-
- pixman_transform_scale (transform, &inverse, scale_x, scale_y);
- pixman_f_transform_scale (f_transform, f_inverse, f_scale_x, f_scale_y);
- pixman_transform_translate (transform, &inverse, scale_dx, scale_dy);
- pixman_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
- }
-
- /*
- * Sprite position is affected by the transform matrix,
- * but the image is not
- */
- pixman_f_transform_multiply(f_sprite_to_image,
- f_transform,
- &f_image_to_sprite);
-
- if (rr_transform)
- {
- if (!pixman_transform_multiply (transform, &rr_transform->transform, transform))
- overflow = TRUE;
- pixman_f_transform_multiply (f_transform, &rr_transform->f_transform, f_transform);
- pixman_f_transform_multiply (f_inverse, f_inverse, &rr_transform->f_inverse);
- }
-
- /*
- * Compute the class of the resulting transform
- */
- if (!overflow && pixman_transform_is_identity (transform))
- {
- pixman_transform_init_translate (transform, F ( x), F ( y));
-
- pixman_f_transform_init_translate (f_transform, x, y);
- pixman_f_transform_init_translate (f_inverse, -x, -y);
- ret = FALSE;
- }
- else
- {
- pixman_f_transform_translate (f_transform, f_inverse, x, y);
- if (!pixman_transform_translate (transform, &inverse, F(x), F(y)))
- overflow = TRUE;
- if (overflow)
- {
- struct pixman_f_transform f_scaled;
- f_scaled = *f_transform;
- RRTransformRescale(&f_scaled, 16384.0);
- pixman_transform_from_pixman_f_transform(transform, &f_scaled);
- }
- ret = TRUE;
- }
-
- /*
- * Sprite position is affected by the transform matrix,
- * but the image is not
- */
- pixman_f_transform_multiply(f_fb_to_sprite,
- f_inverse,
- sprite_position_transform);
- if (sprite_transform_in_use)
- *sprite_transform_in_use = ret || !pict_f_transform_is_identity(f_fb_to_sprite);
- return ret;
-}
-
-
+/*
+ * 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 "randrstr.h"
+#include "rrtransform.h"
+
+void
+RRTransformInit (RRTransformPtr transform)
+{
+ pixman_transform_init_identity (&transform->transform);
+ pixman_f_transform_init_identity (&transform->f_transform);
+ pixman_f_transform_init_identity (&transform->f_inverse);
+ transform->filter = NULL;
+ transform->params = NULL;
+ transform->nparams = 0;
+}
+
+void
+RRTransformFini (RRTransformPtr transform)
+{
+ free(transform->params);
+}
+
+Bool
+RRTransformEqual (RRTransformPtr a, RRTransformPtr b)
+{
+ if (a && pixman_transform_is_identity (&a->transform))
+ a = NULL;
+ if (b && pixman_transform_is_identity (&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 = malloc(nparams * sizeof (xFixed));
+ if (!new_params)
+ return FALSE;
+ memcpy (new_params, params, nparams * sizeof (xFixed));
+ }
+ else
+ new_params = NULL;
+ free(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 && pixman_transform_is_identity (&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;
+ pixman_transform_init_identity (&dst->transform);
+ pixman_f_transform_init_identity (&dst->f_transform);
+ pixman_f_transform_init_identity (&dst->f_inverse);
+ }
+ return TRUE;
+}
+
+#define F(x) IntToxFixed(x)
+
+static void
+RRTransformRescale(struct pixman_f_transform *f_transform, double limit)
+{
+ double max = 0, v, scale;
+ int i, j;
+
+ for (j = 0; j < 3; j++)
+ for (i = 0; i < 3; i++)
+ if ((v = abs (f_transform->m[j][i])) > max)
+ max = v;
+ scale = limit / max;
+ for (j = 0; j < 3; j++)
+ for (i = 0; i < 3; i++)
+ f_transform->m[j][i] *= scale;
+}
+
+/*
+ * 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 pixman_f_transform *f_transform,
+ struct pixman_f_transform *f_inverse)
+{
+ PictTransform t_transform, inverse;
+ struct pixman_f_transform tf_transform, tf_inverse;
+ Bool overflow = FALSE;
+
+ if (!transform) transform = &t_transform;
+ if (!f_transform) f_transform = &tf_transform;
+ if (!f_inverse) f_inverse = &tf_inverse;
+
+ pixman_transform_init_identity (transform);
+ pixman_transform_init_identity (&inverse);
+ pixman_f_transform_init_identity (f_transform);
+ pixman_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;
+ }
+
+ pixman_transform_rotate (transform, &inverse, rot_cos, rot_sin);
+ pixman_transform_translate (transform, &inverse, rot_dx, rot_dy);
+ pixman_f_transform_rotate (f_transform, f_inverse, f_rot_cos, f_rot_sin);
+ pixman_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);
+ }
+ }
+
+ pixman_transform_scale (transform, &inverse, scale_x, scale_y);
+ pixman_f_transform_scale (f_transform, f_inverse, f_scale_x, f_scale_y);
+ pixman_transform_translate (transform, &inverse, scale_dx, scale_dy);
+ pixman_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
+ }
+
+#ifdef RANDR_12_INTERFACE
+ if (rr_transform)
+ {
+ if (!pixman_transform_multiply (transform, &rr_transform->transform, transform))
+ overflow = TRUE;
+ pixman_f_transform_multiply (f_transform, &rr_transform->f_transform, f_transform);
+ pixman_f_transform_multiply (f_inverse, f_inverse, &rr_transform->f_inverse);
+ }
+#endif
+ /*
+ * Compute the class of the resulting transform
+ */
+ if (!overflow && pixman_transform_is_identity (transform))
+ {
+ pixman_transform_init_translate (transform, F ( x), F ( y));
+
+ pixman_f_transform_init_translate (f_transform, x, y);
+ pixman_f_transform_init_translate (f_inverse, -x, -y);
+ return FALSE;
+ }
+ else
+ {
+ pixman_f_transform_translate (f_transform, f_inverse, x, y);
+ if (!pixman_transform_translate (transform, &inverse, F(x), F(y)))
+ overflow = TRUE;
+ if (overflow)
+ {
+ struct pixman_f_transform f_scaled;
+ f_scaled = *f_transform;
+ RRTransformRescale(&f_scaled, 16384.0);
+ pixman_transform_from_pixman_f_transform(transform, &f_scaled);
+ }
+ return TRUE;
+ }
+}