From c0b8610be112f58da39dae1808b41a22064ec614 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 13 Oct 2019 22:42:24 +0200 Subject: [PATCH 1/3] drm: Add get_primary_plane_rotation() helper function Factor most of the code in ply_renderer_head_clear_plane_rotation() out into a get_primary_plane_rotation() helper, this is a preparation patch for adding support for using hw-rotation in some cases. Signed-off-by: Hans de Goede --- src/plugins/renderers/drm/plugin.c | 155 +++++++++++++++++------------ 1 file changed, 91 insertions(+), 64 deletions(-) diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index 0b7aad3e..c80cc13b 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -1,6 +1,6 @@ /* plugin.c - drm backend renderer plugin * - * Copyright (C) 2006-2009 Red Hat, Inc. + * Copyright (C) 2006-2019 Red Hat, Inc. * 2008 Charlie Brej * * This program is free software; you can redistribute it and/or modify @@ -22,6 +22,7 @@ * Kristian Høgsberg * Peter Jones * Ray Strode + * Hans de Goede */ #include "config.h" @@ -414,6 +415,90 @@ destroy_output_buffer (ply_renderer_backend_t *backend, ply_renderer_buffer_free (backend, buffer); } +static bool +get_primary_plane_rotation (ply_renderer_backend_t *backend, + uint32_t controller_id, + int *primary_id_ret, + int *rotation_prop_id_ret, + uint64_t *rotation_ret) +{ + drmModeObjectPropertiesPtr plane_props; + drmModePlaneResPtr plane_resources; + drmModePropertyPtr prop; + drmModePlanePtr plane; + uint64_t rotation; + uint32_t i, j; + int rotation_prop_id = -1; + int primary_id = -1; + int err; + + if (!controller_id) + return false; + + err = drmSetClientCap (backend->device_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + if (err) + return false; + + plane_resources = drmModeGetPlaneResources (backend->device_fd); + if (!plane_resources) + return false; + + for (i = 0; i < plane_resources->count_planes; i++) { + plane = drmModeGetPlane (backend->device_fd, + plane_resources->planes[i]); + if (!plane) + continue; + + if (plane->crtc_id != controller_id) { + drmModeFreePlane (plane); + continue; + } + + plane_props = drmModeObjectGetProperties (backend->device_fd, + plane->plane_id, + DRM_MODE_OBJECT_PLANE); + + for (j = 0; plane_props && (j < plane_props->count_props); j++) { + prop = drmModeGetProperty (backend->device_fd, + plane_props->props[j]); + if (!prop) + continue; + + if (strcmp (prop->name, "type") == 0 && + plane_props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY) { + primary_id = plane->plane_id; + } + + if (strcmp (prop->name, "rotation") == 0) { + rotation_prop_id = plane_props->props[j]; + rotation = plane_props->prop_values[j]; + } + + drmModeFreeProperty (prop); + } + + drmModeFreeObjectProperties (plane_props); + drmModeFreePlane (plane); + + if (primary_id != -1) + break; + + /* Not primary -> clear any found rotation property */ + rotation_prop_id = -1; + } + + drmModeFreePlaneResources (plane_resources); + + if (primary_id != -1 && rotation_prop_id != -1) { + *primary_id_ret = primary_id; + *rotation_prop_id_ret = rotation_prop_id; + *rotation_ret = rotation; + return true; + } + + return false; +} + static ply_pixel_buffer_rotation_t connector_orientation_prop_to_rotation (drmModePropertyPtr prop, int orientation) @@ -572,69 +657,13 @@ static void ply_renderer_head_clear_plane_rotation (ply_renderer_backend_t *backend, ply_renderer_head_t *head) { - drmModeObjectPropertiesPtr plane_props; - drmModePlaneResPtr plane_resources; - drmModePropertyPtr prop; - drmModePlanePtr plane; + int primary_id, rotation_prop_id, err; uint64_t rotation; - uint32_t i, j; - int rotation_prop_id = -1; - int primary_id = -1; - int err; - err = drmSetClientCap (backend->device_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); - if (err) - return; - - plane_resources = drmModeGetPlaneResources (backend->device_fd); - if (!plane_resources) - return; - - for (i = 0; i < plane_resources->count_planes; i++) { - plane = drmModeGetPlane (backend->device_fd, - plane_resources->planes[i]); - if (!plane) - continue; - - if (plane->crtc_id != head->controller_id) { - drmModeFreePlane (plane); - continue; - } - - plane_props = drmModeObjectGetProperties (backend->device_fd, - plane->plane_id, - DRM_MODE_OBJECT_PLANE); - - for (j = 0; plane_props && (j < plane_props->count_props); j++) { - prop = drmModeGetProperty (backend->device_fd, - plane_props->props[j]); - if (!prop) - continue; - - if (strcmp (prop->name, "type") == 0 && - plane_props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY) { - primary_id = plane->plane_id; - } - - if (strcmp (prop->name, "rotation") == 0) { - rotation_prop_id = plane_props->props[j]; - rotation = plane_props->prop_values[j]; - } - - drmModeFreeProperty (prop); - } - - drmModeFreeObjectProperties (plane_props); - drmModeFreePlane (plane); - - if (primary_id != -1) - break; - - /* Not primary -> clear any found rotation property */ - rotation_prop_id = -1; - } - - if (primary_id != -1 && rotation_prop_id != -1 && rotation != DRM_MODE_ROTATE_0) { + if (get_primary_plane_rotation (backend, head->controller_id, + &primary_id, &rotation_prop_id, + &rotation) && + rotation != DRM_MODE_ROTATE_0) { err = drmModeObjectSetProperty (backend->device_fd, primary_id, DRM_MODE_OBJECT_PLANE, @@ -643,8 +672,6 @@ ply_renderer_head_clear_plane_rotation (ply_renderer_backend_t *backend, ply_trace ("Cleared rotation on primary plane %d result %d", primary_id, err); } - - drmModeFreePlaneResources (plane_resources); } static bool From c598440e4925cf398fbbb343b8b652825e8a9be2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 13 Oct 2019 23:46:31 +0200 Subject: [PATCH 2/3] drm: Keep hw-rotation on devices with upside down LCD panels On devices with an upside down LCD panel and where the hw is capable of rotating the image to correct this the firmware will program the primary plane to use hw rotation. When we reset this, this may lead to a small flicker, where the vendor logo is briefly shown upside down. A bigger problem is the transition to gdm/mutter. We leave the splash on screen when mutter loads for a smooth transition, when mutter turns hw-rotation back on, the splash turns upside down! And mutter then fades from the upside-down splash to the login screen, which looks kinda bad. Keeping the hw-rotation (and disabling our sw rotation) on devices like this fixes both issues. Signed-off-by: Hans de Goede --- src/plugins/renderers/drm/plugin.c | 31 +++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index c80cc13b..32ed4d11 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -83,7 +83,8 @@ struct _ply_renderer_head uint32_t controller_id; uint32_t console_buffer_id; uint32_t scan_out_buffer_id; - bool scan_out_buffer_needs_reset; + bool scan_out_buffer_needs_reset; + bool uses_hw_rotation; int gamma_size; uint16_t *gamma; @@ -128,6 +129,7 @@ typedef struct ply_pixel_buffer_rotation_t rotation; bool tiled; bool connected; + bool uses_hw_rotation; } ply_output_t; struct _ply_renderer_backend @@ -526,8 +528,9 @@ ply_renderer_connector_get_rotation_and_tiled (ply_renderer_backend_t *back drmModeConnector *connector, ply_output_t *output) { + int i, primary_id, rotation_prop_id; drmModePropertyPtr prop; - int i; + uint64_t rotation; output->rotation = PLY_PIXEL_BUFFER_ROTATE_UPRIGHT; output->tiled = false; @@ -554,6 +557,21 @@ ply_renderer_connector_get_rotation_and_tiled (ply_renderer_backend_t *back drmModeFreeProperty (prop); } + + /* If the firmware setup the plane to use hw 180° rotation, then we keep + * the hw rotation. This avoids a flicker and avoids the splash turning + * upside-down when mutter turns hw-rotation back on and then fades from + * the splash to the login screen. + */ + if (output->rotation == PLY_PIXEL_BUFFER_ROTATE_UPSIDE_DOWN && + get_primary_plane_rotation (backend, output->controller_id, + &primary_id, &rotation_prop_id, + &rotation) && + rotation == DRM_MODE_ROTATE_180) { + ply_trace("Keeping hw 180° rotation"); + output->rotation = PLY_PIXEL_BUFFER_ROTATE_UPRIGHT; + output->uses_hw_rotation = true; + } } static bool @@ -598,6 +616,7 @@ ply_renderer_head_new (ply_renderer_backend_t *backend, head->controller_id = output->controller_id; head->console_buffer_id = console_buffer_id; head->connector0_mode = output->mode; + head->uses_hw_rotation = output->uses_hw_rotation; head->area.x = 0; head->area.y = 0; @@ -660,6 +679,9 @@ ply_renderer_head_clear_plane_rotation (ply_renderer_backend_t *backend, int primary_id, rotation_prop_id, err; uint64_t rotation; + if (head->uses_hw_rotation) + return; + if (get_primary_plane_rotation (backend, head->controller_id, &primary_id, &rotation_prop_id, &rotation) && @@ -1412,8 +1434,11 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend, bool change */ if (!change && number_of_setup_outputs != backend->connected_count) { ply_trace ("Some outputs still don't have controllers, re-assigning controllers for all outputs"); - for (i = 0; i < outputs_len; i++) + for (i = 0; i < outputs_len; i++) { + if (outputs[i].uses_hw_rotation) + continue; /* Do not re-assign hw-rotated outputs */ outputs[i].controller_id = 0; + } outputs = setup_outputs (backend, outputs, outputs_len); } for (i = 0; i < outputs_len; i++) From b2b6df3271f2c41895719919e8ec542e5fbbe30c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 14 Oct 2019 08:11:07 +0200 Subject: [PATCH 3/3] two-step: Remove workaround for upside-down panels Now that the drm plugin uses hw-rotation for upside down panels when the GOP does so, there is no need to treat the bgrt rotation for upside-down panels special anymore, Signed-off-by: Hans de Goede --- src/plugins/splash/two-step/plugin.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index 9e648d24..e666cfb5 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -470,11 +470,7 @@ view_set_bgrt_background (view_t *view) } if (have_panel_props) { - /* Upside-down panels are fixed up in HW by the GOP, so the - * bgrt image is not rotated in this case. - */ - if (panel_rotation != PLY_PIXEL_BUFFER_ROTATE_UPSIDE_DOWN) - ply_pixel_buffer_set_device_rotation (bgrt_buffer, panel_rotation); + ply_pixel_buffer_set_device_rotation (bgrt_buffer, panel_rotation); ply_pixel_buffer_set_device_scale (bgrt_buffer, panel_scale); }