diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h index 7325b1c3b..1809676fe 100644 --- a/src/core/monitor-private.h +++ b/src/core/monitor-private.h @@ -43,6 +43,22 @@ #include #include "stack-tracker.h" #include "ui.h" +#ifdef HAVE_WAYLAND +#include +#endif + +#ifndef HAVE_WAYLAND +enum wl_output_transform { + WL_OUTPUT_TRANSFORM_NORMAL, + WL_OUTPUT_TRANSFORM_90, + WL_OUTPUT_TRANSFORM_180, + WL_OUTPUT_TRANSFORM_270, + WL_OUTPUT_TRANSFORM_FLIPPED, + WL_OUTPUT_TRANSFORM_FLIPPED_90, + WL_OUTPUT_TRANSFORM_FLIPPED_180, + WL_OUTPUT_TRANSFORM_FLIPPED_270 +}; +#endif typedef struct _MetaOutput MetaOutput; typedef struct _MetaCRTC MetaCRTC; @@ -92,6 +108,8 @@ struct _MetaCRTC glong crtc_id; MetaRectangle rect; MetaMonitorMode *current_mode; + enum wl_output_transform transform; + unsigned int all_transforms; /* Only used to build the logical configuration from the HW one diff --git a/src/core/monitor.c b/src/core/monitor.c index ba885869d..5c3abf8f4 100644 --- a/src/core/monitor.c +++ b/src/core/monitor.c @@ -43,18 +43,7 @@ #include "meta-dbus-xrandr.h" -#ifndef HAVE_WAYLAND -enum wl_output_transform { - WL_OUTPUT_TRANSFORM_NORMAL, - WL_OUTPUT_TRANSFORM_90, - WL_OUTPUT_TRANSFORM_180, - WL_OUTPUT_TRANSFORM_270, - WL_OUTPUT_TRANSFORM_FLIPPED, - WL_OUTPUT_TRANSFORM_FLIPPED_90, - WL_OUTPUT_TRANSFORM_FLIPPED_180, - WL_OUTPUT_TRANSFORM_FLIPPED_270 -}; -#endif +#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1) typedef enum { META_BACKEND_UNSPECIFIED, @@ -176,6 +165,8 @@ make_dummy_monitor_config (MetaMonitorManager *manager) manager->crtcs[0].rect.width = manager->modes[0].width; manager->crtcs[0].rect.height = manager->modes[0].height; manager->crtcs[0].current_mode = &manager->modes[0]; + manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL; + manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS; manager->crtcs[0].dirty = FALSE; manager->crtcs[0].logical_monitor = NULL; @@ -185,6 +176,8 @@ make_dummy_monitor_config (MetaMonitorManager *manager) manager->crtcs[1].rect.width = 0; manager->crtcs[1].rect.height = 0; manager->crtcs[1].current_mode = NULL; + manager->crtcs[1].transform = WL_OUTPUT_TRANSFORM_NORMAL; + manager->crtcs[1].all_transforms = ALL_WL_TRANSFORMS; manager->crtcs[1].dirty = FALSE; manager->crtcs[1].logical_monitor = NULL; @@ -259,6 +252,76 @@ make_dummy_monitor_config (MetaMonitorManager *manager) } #ifdef HAVE_RANDR +static enum wl_output_transform +wl_transform_from_xrandr (Rotation rotation) +{ + static const enum wl_output_transform y_reflected_map[4] = { + WL_OUTPUT_TRANSFORM_FLIPPED_180, + WL_OUTPUT_TRANSFORM_FLIPPED_90, + WL_OUTPUT_TRANSFORM_FLIPPED, + WL_OUTPUT_TRANSFORM_FLIPPED_270 + }; + enum wl_output_transform ret; + + switch (rotation & 0x7F) + { + default: + case RR_Rotate_0: + ret = WL_OUTPUT_TRANSFORM_NORMAL; + break; + case RR_Rotate_90: + ret = WL_OUTPUT_TRANSFORM_90; + break; + case RR_Rotate_180: + ret = WL_OUTPUT_TRANSFORM_180; + break; + case RR_Rotate_270: + ret = WL_OUTPUT_TRANSFORM_270; + break; + } + + if (rotation & RR_Reflect_X) + return ret + 4; + else if (rotation & RR_Reflect_Y) + return y_reflected_map[ret]; + else + return ret; +} + +#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270) + +static unsigned int +wl_transform_from_xrandr_all (Rotation rotation) +{ + unsigned ret; + + /* Handle the common cases first (none or all) */ + if (rotation == 0 || rotation == RR_Rotate_0) + return (1 << WL_OUTPUT_TRANSFORM_NORMAL); + + /* All rotations and one reflection -> all of them by composition */ + if ((rotation & ALL_ROTATIONS) && + ((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y))) + return ALL_WL_TRANSFORMS; + + ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL; + if (rotation & RR_Rotate_90) + ret |= 1 << WL_OUTPUT_TRANSFORM_90; + if (rotation & RR_Rotate_180) + ret |= 1 << WL_OUTPUT_TRANSFORM_180; + if (rotation & RR_Rotate_270) + ret |= 1 << WL_OUTPUT_TRANSFORM_270; + if (rotation & (RR_Rotate_0 | RR_Reflect_X)) + ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED; + if (rotation & (RR_Rotate_90 | RR_Reflect_X)) + ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90; + if (rotation & (RR_Rotate_180 | RR_Reflect_X)) + ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180; + if (rotation & (RR_Rotate_270 | RR_Reflect_X)) + ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270; + + return ret; +} static void read_monitor_infos_from_xrandr (MetaMonitorManager *manager) @@ -329,6 +392,8 @@ read_monitor_infos_from_xrandr (MetaMonitorManager *manager) meta_crtc->rect.width = crtc->width; meta_crtc->rect.height = crtc->height; meta_crtc->dirty = FALSE; + meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation); + meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations); for (j = 0; j < (unsigned)resources->nmode; j++) { @@ -546,6 +611,8 @@ read_monitor_infos_from_cogl (MetaMonitorManager *manager) cogl_output_get_width (output), cogl_output_get_height (output), cogl_output_get_refresh_rate (output)); + meta_crtc.transform = WL_OUTPUT_TRANSFORM_NORMAL; + meta_crtc.all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL; meta_crtc.logical_monitor = NULL; meta_crtc.dirty = FALSE; @@ -925,7 +992,9 @@ handle_get_resources (MetaDBusDisplayConfig *skeleton, GVariantBuilder transforms; g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au")); - g_variant_builder_add (&transforms, "u", 0); /* 0 = WL_OUTPUT_TRANSFORM_NORMAL */ + for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++) + if (crtc->all_transforms & (1 << j)) + g_variant_builder_add (&transforms, "u", j); g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})", i, /* ID */ @@ -935,7 +1004,7 @@ handle_get_resources (MetaDBusDisplayConfig *skeleton, (int)crtc->rect.width, (int)crtc->rect.height, (int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1), - 0, /* 0 = WL_OUTPUT_TRANSFORM_NORMAL */ + crtc->transform, &transforms, NULL /* properties */); } @@ -1220,6 +1289,7 @@ apply_config_dummy (MetaMonitorManager *manager, crtc->rect.width = mode->width; crtc->rect.height = mode->height; crtc->current_mode = mode; + crtc->transform = transform; screen_width = MAX (screen_width, x + mode->width); screen_height = MAX (screen_height, y + mode->height); diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index e6b33358a..fe01de15b 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -658,7 +658,7 @@ bind_output (struct wl_client *client, output->subpixel_order, output->vendor, output->product, - WL_OUTPUT_TRANSFORM_NORMAL); + output->crtc->transform); wl_resource_post_event (resource, WL_OUTPUT_MODE,