From 8060d826b7a03f4765eaa14be966c520b0aacca9 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 6 Feb 2020 15:27:54 +0200 Subject: [PATCH] Redefine output rotations It was discovered in issue #99 that the implementations of the 90 and 270 degree rotations were actually the inverse of what the Wayland specification spelled out. This patch fixes the libweston implementation to follow the specification. As a result, the behaviour of the the weston.ini transform key also changes. To force all users to re-think their configuration, the transform key values are also changed. Since Weston and libweston change their behaviour, the handling of clients' buffer transform changes too. All the functions had their 90/270 cases simply swapped, probably due to confusion of whether WL_OUTPUT_TRANSFORM_* refers to rotating the monitor or the content. Hint: a key to understanding weston_matrix_rotate_xy(m, c, s) is that the rotation matrix is formed as c -s s c that is, it's column-major. This fooled me at first. Fixing window.c fixes weston-terminal and weston-transformed. In simple-damage, window_get_transformed_ball() is fixed to follow the proper transform definitions, but the fix to the viewport path in redraw() is purely mechanical. The viewport path looks broken to me in the presence of any transform, but it is not this patch's job to fix it. Screen-share fix just repeats the general code fix pattern, I did not even try to understand that bit. https://gitlab.freedesktop.org/wayland/weston/issues/99 Signed-off-by: Pekka Paalanen --- clients/simple-damage.c | 32 ++++++++++---------- clients/transformed.c | 3 ++ clients/window.c | 24 +++++++-------- compositor/main.c | 16 +++++----- compositor/screen-share.c | 8 ++--- libweston/compositor.c | 64 +++++++++++++++++++-------------------- man/weston-drm.man | 5 +-- man/weston.ini.man | 20 ++++++------ 8 files changed, 88 insertions(+), 84 deletions(-) diff --git a/clients/simple-damage.c b/clients/simple-damage.c index 0458bd06..821b42b5 100644 --- a/clients/simple-damage.c +++ b/clients/simple-damage.c @@ -461,32 +461,32 @@ window_get_transformed_ball(struct window *window, float *bx, float *by) *by = wy; break; case WL_OUTPUT_TRANSFORM_90: - *bx = window->height - wy; - *by = wx; + *bx = wy; + *by = window->width - wx; break; case WL_OUTPUT_TRANSFORM_180: *bx = window->width - wx; *by = window->height - wy; break; case WL_OUTPUT_TRANSFORM_270: - *bx = wy; - *by = window->width - wx; + *bx = window->height - wy; + *by = wx; break; case WL_OUTPUT_TRANSFORM_FLIPPED: *bx = window->width - wx; *by = wy; break; case WL_OUTPUT_TRANSFORM_FLIPPED_90: - *bx = window->height - wy; - *by = window->width - wx; + *bx = wy; + *by = wx; break; case WL_OUTPUT_TRANSFORM_FLIPPED_180: *bx = wx; *by = window->height - wy; break; case WL_OUTPUT_TRANSFORM_FLIPPED_270: - *bx = wy; - *by = wx; + *bx = window->height - wy; + *by = window->width - wx; break; } @@ -570,32 +570,32 @@ redraw(void *data, struct wl_callback *callback, uint32_t time) off_x = tx; break; case WL_OUTPUT_TRANSFORM_90: - off_y = tx; - off_x = bwidth - ty; + off_y = bheight - tx; + off_x = ty; break; case WL_OUTPUT_TRANSFORM_180: off_y = bheight - ty; off_x = bwidth - tx; break; case WL_OUTPUT_TRANSFORM_270: - off_y = bheight - tx; - off_x = ty; + off_y = tx; + off_x = bwidth - ty; break; case WL_OUTPUT_TRANSFORM_FLIPPED: off_y = ty; off_x = bwidth - tx; break; case WL_OUTPUT_TRANSFORM_FLIPPED_90: - off_y = bheight - tx; - off_x = bwidth - ty; + off_y = tx; + off_x = ty; break; case WL_OUTPUT_TRANSFORM_FLIPPED_180: off_y = bheight - ty; off_x = tx; break; case WL_OUTPUT_TRANSFORM_FLIPPED_270: - off_y = tx; - off_x = ty; + off_y = bheight - tx; + off_x = bwidth - ty; break; } wp_viewport_set_source(window->viewport, diff --git a/clients/transformed.c b/clients/transformed.c index ab9459fa..59f44bca 100644 --- a/clients/transformed.c +++ b/clients/transformed.c @@ -231,6 +231,9 @@ usage(int error_code) " -h \tSet window height to \n" " --help\tShow this help text\n\n"); + fprintf(stderr, "This version has been fixed for " + "https://gitlab.freedesktop.org/wayland/weston/issues/99 .\n"); + exit(error_code); } diff --git a/clients/window.c b/clients/window.c index 970d54ce..5a75bd40 100644 --- a/clients/window.c +++ b/clients/window.c @@ -1832,14 +1832,14 @@ widget_cairo_update_transform(struct widget *widget, cairo_t *cr) translate_y = 0; break; case WL_OUTPUT_TRANSFORM_90: - angle = M_PI_2; - translate_x = surface_height; - translate_y = 0; + angle = M_PI + M_PI_2; + translate_x = 0; + translate_y = surface_width; break; case WL_OUTPUT_TRANSFORM_FLIPPED_90: - angle = M_PI_2; - translate_x = surface_height; - translate_y = surface_width; + angle = M_PI + M_PI_2; + translate_x = 0; + translate_y = 0; break; case WL_OUTPUT_TRANSFORM_180: angle = M_PI; @@ -1852,14 +1852,14 @@ widget_cairo_update_transform(struct widget *widget, cairo_t *cr) translate_y = surface_height; break; case WL_OUTPUT_TRANSFORM_270: - angle = M_PI + M_PI_2; - translate_x = 0; - translate_y = surface_width; + angle = M_PI_2; + translate_x = surface_height; + translate_y = 0; break; case WL_OUTPUT_TRANSFORM_FLIPPED_270: - angle = M_PI + M_PI_2; - translate_x = 0; - translate_y = 0; + angle = M_PI_2; + translate_x = surface_height; + translate_y = surface_width; break; } diff --git a/compositor/main.c b/compositor/main.c index 02944f7b..d5a7f04e 100644 --- a/compositor/main.c +++ b/compositor/main.c @@ -1107,14 +1107,14 @@ weston_choose_default_backend(void) } static const struct { const char *name; uint32_t token; } transforms[] = { - { "normal", WL_OUTPUT_TRANSFORM_NORMAL }, - { "90", WL_OUTPUT_TRANSFORM_90 }, - { "180", WL_OUTPUT_TRANSFORM_180 }, - { "270", WL_OUTPUT_TRANSFORM_270 }, - { "flipped", WL_OUTPUT_TRANSFORM_FLIPPED }, - { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 }, - { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 }, - { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 }, + { "normal", WL_OUTPUT_TRANSFORM_NORMAL }, + { "rotate-90", WL_OUTPUT_TRANSFORM_90 }, + { "rotate-180", WL_OUTPUT_TRANSFORM_180 }, + { "rotate-270", WL_OUTPUT_TRANSFORM_270 }, + { "flipped", WL_OUTPUT_TRANSFORM_FLIPPED }, + { "flipped-rotate-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 }, + { "flipped-rotate-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 }, + { "flipped-rotate-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 }, }; WL_EXPORT int diff --git a/compositor/screen-share.c b/compositor/screen-share.c index c8256fac..62b871bf 100644 --- a/compositor/screen-share.c +++ b/compositor/screen-share.c @@ -551,8 +551,8 @@ output_compute_transform(struct weston_output *output, break; case WL_OUTPUT_TRANSFORM_90: case WL_OUTPUT_TRANSFORM_FLIPPED_90: - pixman_transform_rotate(transform, NULL, 0, pixman_fixed_1); - pixman_transform_translate(transform, NULL, fh, 0); + pixman_transform_rotate(transform, NULL, 0, -pixman_fixed_1); + pixman_transform_translate(transform, NULL, 0, fw); break; case WL_OUTPUT_TRANSFORM_180: case WL_OUTPUT_TRANSFORM_FLIPPED_180: @@ -561,8 +561,8 @@ output_compute_transform(struct weston_output *output, break; case WL_OUTPUT_TRANSFORM_270: case WL_OUTPUT_TRANSFORM_FLIPPED_270: - pixman_transform_rotate(transform, NULL, 0, -pixman_fixed_1); - pixman_transform_translate(transform, NULL, 0, fw); + pixman_transform_rotate(transform, NULL, 0, pixman_fixed_1); + pixman_transform_translate(transform, NULL, fh, 0); break; } diff --git a/libweston/compositor.c b/libweston/compositor.c index d085126a..29c0ab18 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -643,12 +643,12 @@ weston_transformed_coord(int width, int height, *by = sy; break; case WL_OUTPUT_TRANSFORM_90: - *bx = height - sy; - *by = sx; + *bx = sy; + *by = width - sx; break; case WL_OUTPUT_TRANSFORM_FLIPPED_90: - *bx = height - sy; - *by = width - sx; + *bx = sy; + *by = sx; break; case WL_OUTPUT_TRANSFORM_180: *bx = width - sx; @@ -659,12 +659,12 @@ weston_transformed_coord(int width, int height, *by = height - sy; break; case WL_OUTPUT_TRANSFORM_270: - *bx = sy; - *by = width - sx; + *bx = height - sy; + *by = sx; break; case WL_OUTPUT_TRANSFORM_FLIPPED_270: - *bx = sy; - *by = sx; + *bx = height - sy; + *by = width - sx; break; } @@ -830,10 +830,10 @@ weston_transformed_region(int width, int height, dest_rects[i].y2 = src_rects[i].y2; break; case WL_OUTPUT_TRANSFORM_90: - dest_rects[i].x1 = height - src_rects[i].y2; - dest_rects[i].y1 = src_rects[i].x1; - dest_rects[i].x2 = height - src_rects[i].y1; - dest_rects[i].y2 = src_rects[i].x2; + dest_rects[i].x1 = src_rects[i].y1; + dest_rects[i].y1 = width - src_rects[i].x2; + dest_rects[i].x2 = src_rects[i].y2; + dest_rects[i].y2 = width - src_rects[i].x1; break; case WL_OUTPUT_TRANSFORM_180: dest_rects[i].x1 = width - src_rects[i].x2; @@ -842,10 +842,10 @@ weston_transformed_region(int width, int height, dest_rects[i].y2 = height - src_rects[i].y1; break; case WL_OUTPUT_TRANSFORM_270: - dest_rects[i].x1 = src_rects[i].y1; - dest_rects[i].y1 = width - src_rects[i].x2; - dest_rects[i].x2 = src_rects[i].y2; - dest_rects[i].y2 = width - src_rects[i].x1; + dest_rects[i].x1 = height - src_rects[i].y2; + dest_rects[i].y1 = src_rects[i].x1; + dest_rects[i].x2 = height - src_rects[i].y1; + dest_rects[i].y2 = src_rects[i].x2; break; case WL_OUTPUT_TRANSFORM_FLIPPED: dest_rects[i].x1 = width - src_rects[i].x2; @@ -854,10 +854,10 @@ weston_transformed_region(int width, int height, dest_rects[i].y2 = src_rects[i].y2; break; case WL_OUTPUT_TRANSFORM_FLIPPED_90: - dest_rects[i].x1 = height - src_rects[i].y2; - dest_rects[i].y1 = width - src_rects[i].x2; - dest_rects[i].x2 = height - src_rects[i].y1; - dest_rects[i].y2 = width - src_rects[i].x1; + dest_rects[i].x1 = src_rects[i].y1; + dest_rects[i].y1 = src_rects[i].x1; + dest_rects[i].x2 = src_rects[i].y2; + dest_rects[i].y2 = src_rects[i].x2; break; case WL_OUTPUT_TRANSFORM_FLIPPED_180: dest_rects[i].x1 = src_rects[i].x1; @@ -866,10 +866,10 @@ weston_transformed_region(int width, int height, dest_rects[i].y2 = height - src_rects[i].y1; break; case WL_OUTPUT_TRANSFORM_FLIPPED_270: - dest_rects[i].x1 = src_rects[i].y1; - dest_rects[i].y1 = src_rects[i].x1; - dest_rects[i].x2 = src_rects[i].y2; - dest_rects[i].y2 = src_rects[i].x2; + dest_rects[i].x1 = height - src_rects[i].y2; + dest_rects[i].y1 = width - src_rects[i].x2; + dest_rects[i].x2 = height - src_rects[i].y1; + dest_rects[i].y2 = width - src_rects[i].x1; break; } } @@ -3402,9 +3402,9 @@ weston_surface_build_buffer_matrix(const struct weston_surface *surface, break; case WL_OUTPUT_TRANSFORM_90: case WL_OUTPUT_TRANSFORM_FLIPPED_90: - weston_matrix_rotate_xy(matrix, 0, 1); + weston_matrix_rotate_xy(matrix, 0, -1); weston_matrix_translate(matrix, - surface->height_from_buffer, 0, 0); + 0, surface->width_from_buffer, 0); break; case WL_OUTPUT_TRANSFORM_180: case WL_OUTPUT_TRANSFORM_FLIPPED_180: @@ -3415,9 +3415,9 @@ weston_surface_build_buffer_matrix(const struct weston_surface *surface, break; case WL_OUTPUT_TRANSFORM_270: case WL_OUTPUT_TRANSFORM_FLIPPED_270: - weston_matrix_rotate_xy(matrix, 0, -1); + weston_matrix_rotate_xy(matrix, 0, 1); weston_matrix_translate(matrix, - 0, surface->width_from_buffer, 0); + surface->height_from_buffer, 0, 0); break; } @@ -5786,8 +5786,8 @@ weston_output_update_matrix(struct weston_output *output) break; case WL_OUTPUT_TRANSFORM_90: case WL_OUTPUT_TRANSFORM_FLIPPED_90: - weston_matrix_translate(&output->matrix, 0, -output->height, 0); - weston_matrix_rotate_xy(&output->matrix, 0, 1); + weston_matrix_translate(&output->matrix, -output->width, 0, 0); + weston_matrix_rotate_xy(&output->matrix, 0, -1); break; case WL_OUTPUT_TRANSFORM_180: case WL_OUTPUT_TRANSFORM_FLIPPED_180: @@ -5797,8 +5797,8 @@ weston_output_update_matrix(struct weston_output *output) break; case WL_OUTPUT_TRANSFORM_270: case WL_OUTPUT_TRANSFORM_FLIPPED_270: - weston_matrix_translate(&output->matrix, -output->width, 0, 0); - weston_matrix_rotate_xy(&output->matrix, 0, -1); + weston_matrix_translate(&output->matrix, 0, -output->height, 0); + weston_matrix_rotate_xy(&output->matrix, 0, 1); break; } diff --git a/man/weston-drm.man b/man/weston-drm.man index 488eef6e..ebf370eb 100644 --- a/man/weston-drm.man +++ b/man/weston-drm.man @@ -119,8 +119,9 @@ can generate detailed mode lines. \fBtransform\fR=\fItransform\fR Transform for the output, which can be rotated in 90-degree steps and possibly flipped. Possible values are -.BR normal ", " 90 ", " 180 ", " 270 ", " -.BR flipped ", " flipped-90 ", " flipped-180 ", and " flipped-270 . +.BR normal ", " rotate-90 ", " rotate-180 ", " rotate-270 ", " +.BR flipped ", " flipped-rotate-90 ", " flipped-rotate-180 ", and " +.BR flipped-rotate-270 . .TP \fBpixman-shadow\fR=\fIboolean\fR If using the Pixman-renderer, use shadow framebuffers. Defaults to diff --git a/man/weston.ini.man b/man/weston.ini.man index 5e39e4a5..bce5628b 100644 --- a/man/weston.ini.man +++ b/man/weston.ini.man @@ -504,19 +504,19 @@ for examples of modes-formats supported by DRM backend. .RE .TP 7 .BI "transform=" normal -The transformation applied to screen output (string). The transform key can -be one of the following 8 strings: +How you have rotated your monitor from its normal orientation (string). +The transform key can be one of the following 8 strings: .PP .RS 10 .nf -.BR "normal " "Normal output." -.BR "90 " "90 degrees clockwise." -.BR "180 " "Upside down." -.BR "270 " "90 degrees counter clockwise." -.BR "flipped " "Horizontally flipped" -.BR "flipped-90 " "Flipped and 90 degrees clockwise" -.BR "flipped-180 " "Flipped upside down" -.BR "flipped-270 " "Flipped and 90 degrees counter clockwise" +.BR "normal " "Normal output." +.BR "rotate-90 " "90 degrees clockwise." +.BR "rotate-180 " "Upside down." +.BR "rotate-270 " "90 degrees counter clockwise." +.BR "flipped " "Horizontally flipped" +.BR "flipped-rotate-90 " "Flipped and 90 degrees clockwise" +.BR "flipped-rotate-180 " "Flipped and upside down" +.BR "flipped-rotate-270 " "Flipped and 90 degrees counter clockwise" .fi .RE .TP 7