[PATCH] map-to-output: implement reflections and rotations
Alon Levy
alevy at redhat.com
Sat Jun 9 07:23:37 PDT 2012
Uses the rotation & translation currently set according to RandR.
Signed-off-by: Alon Levy <alevy at redhat.com>
---
Tested with a x220t (lenovo tablet). The comments below "correct in working
zone", I believe are not related to the wrong matrix, you can see for instance
that 'RR_Rotate_270 | RR_Reflect_All' is limited but 'RR_Rotate_90' is not and
they both set the same matrix. So I think it's a RandR related bug.
src/transform.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 69 insertions(+), 9 deletions(-)
diff --git a/src/transform.c b/src/transform.c
index f80a592..d85b071 100644
--- a/src/transform.c
+++ b/src/transform.c
@@ -107,10 +107,30 @@ apply_matrix(Display *dpy, int deviceid, Matrix *m)
}
static void
+matrix_s4(Matrix *m, float x02, float x12, float d1, float d2, int main_diag)
+{
+ matrix_set(m, 0, 2, x02);
+ matrix_set(m, 1, 2, x12);
+
+ if (main_diag) {
+ matrix_set(m, 0, 0, d1);
+ matrix_set(m, 1, 1, d2);
+ } else {
+ matrix_set(m, 0, 0, 0);
+ matrix_set(m, 1, 1, 0);
+ matrix_set(m, 0, 1, d1);
+ matrix_set(m, 1, 0, d2);
+ }
+}
+
+#define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y)
+
+static void
set_transformation_matrix(Display *dpy, Matrix *m, int offset_x, int offset_y,
- int screen_width, int screen_height)
+ int screen_width, int screen_height,
+ int rotation)
{
- /* offset */
+ /* total display size */
int width = DisplayWidth(dpy, DefaultScreen(dpy));
int height = DisplayHeight(dpy, DefaultScreen(dpy));
@@ -124,11 +144,49 @@ set_transformation_matrix(Display *dpy, Matrix *m, int offset_x, int offset_y,
matrix_set_unity(m);
- matrix_set(m, 0, 2, x);
- matrix_set(m, 1, 2, y);
-
- matrix_set(m, 0, 0, w);
- matrix_set(m, 1, 1, h);
+ /*
+ * There are 16 cases:
+ * Rotation X Reflection
+ * Rotation: 0 | 90 | 180 | 270
+ * Reflection: None | X | Y | XY
+ *
+ * They are spelled out instead of doing matrix multiplication to avoid
+ * any floating point errors.
+ */
+ switch (rotation) {
+ case RR_Rotate_0:
+ case RR_Rotate_180 | RR_Reflect_All:
+ matrix_s4(m, x, y, w, h, 1);
+ break;
+ case RR_Reflect_X|RR_Rotate_0:
+ case RR_Reflect_Y|RR_Rotate_180:
+ matrix_s4(m, x + w, y, -w, h, 1);
+ break;
+ case RR_Reflect_Y|RR_Rotate_0:
+ case RR_Reflect_X|RR_Rotate_180:
+ matrix_s4(m, x, y + h, w, -h, 1);
+ break;
+ case RR_Rotate_90:
+ case RR_Rotate_270 | RR_Reflect_All: /* left limited - correct in working zone. */
+ matrix_s4(m, x + w, y, -w, h, 0);
+ break;
+ case RR_Rotate_270:
+ case RR_Rotate_90 | RR_Reflect_All: /* left limited - correct in working zone. */
+ matrix_s4(m, x, y + h, w, -h, 0);
+ break;
+ case RR_Rotate_90 | RR_Reflect_X: /* left limited - correct in working zone. */
+ case RR_Rotate_270 | RR_Reflect_Y: /* left limited - correct in working zone. */
+ matrix_s4(m, x, y, w, h, 0);
+ break;
+ case RR_Rotate_90 | RR_Reflect_Y: /* right limited - correct in working zone. */
+ case RR_Rotate_270 | RR_Reflect_X: /* right limited - correct in working zone. */
+ matrix_s4(m, x + w, y + h, -w, -h, 0);
+ break;
+ case RR_Rotate_180:
+ case RR_Reflect_All|RR_Rotate_0:
+ matrix_s4(m, x + w, y + h, -w, -h, 1);
+ break;
+ }
#if DEBUG
matrix_print(m);
@@ -186,7 +244,8 @@ map_output_xrandr(Display *dpy, int deviceid, const char *output_name)
matrix_set_unity(&m);
crtc_info = XRRGetCrtcInfo (dpy, res, output_info->crtc);
set_transformation_matrix(dpy, &m, crtc_info->x, crtc_info->y,
- crtc_info->width, crtc_info->height);
+ crtc_info->width, crtc_info->height,
+ crtc_info->rotation);
rc = apply_matrix(dpy, deviceid, &m);
XRRFreeCrtcInfo(crtc_info);
XRRFreeOutputInfo(output_info);
@@ -242,7 +301,8 @@ map_output_xinerama(Display *dpy, int deviceid, const char *output_name)
matrix_set_unity(&m);
set_transformation_matrix(dpy, &m,
screens[head].x_org, screens[head].y_org,
- screens[head].width, screens[head].height);
+ screens[head].width, screens[head].height,
+ RR_Rotate_0);
rc = apply_matrix(dpy, deviceid, &m);
out:
--
1.7.10.1
More information about the xorg-devel
mailing list