Blame SOURCES/0005-drm-Reset-primary-plane-rotation-to-DRM_MODE_ROTATE_.patch

ff210d
From d769f1194c934ed4ff7ce6bfc502ba485d461c12 Mon Sep 17 00:00:00 2001
ff210d
From: Hans de Goede <hdegoede@redhat.com>
ff210d
Date: Sat, 20 Jan 2018 12:20:29 +0100
ff210d
Subject: [PATCH 5/6] drm: Reset primary plane rotation to DRM_MODE_ROTATE_0
ff210d
ff210d
On devices where the (LCD) panel is mounted upside-down in the case
ff210d
the kernel's drm_fb_helper code may have set up rotation on the primary
ff210d
plane to make the text-console (and other fbdev using apps) show the right
ff210d
way up.
ff210d
ff210d
We inherit this rotation from the text-mode and since we do our own rotation
ff210d
where necessary we end up rotating twice and showing the boot-splash
ff210d
upside-down again.
ff210d
ff210d
Dealing with hardware rotation may require using a specific framebuffer
ff210d
tiling which we do not support, so we should just disable the hardware
ff210d
rotation and keep using our own software rotation.
ff210d
ff210d
This commit adds code to find the primary plane and its rotation property
ff210d
and if it is not DRM_MODE_ROTATE_0 then sets it to DRM_MODE_ROTATE_0. fixing
ff210d
the double rotation issue.
ff210d
ff210d
https://bugs.freedesktop.org/show_bug.cgi?id=104714
ff210d
---
ff210d
 src/plugins/renderers/drm/plugin.c | 86 ++++++++++++++++++++++++++++++
ff210d
 1 file changed, 86 insertions(+)
ff210d
ff210d
diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c
ff210d
index f495854..fb79aa6 100644
ff210d
--- a/src/plugins/renderers/drm/plugin.c
ff210d
+++ b/src/plugins/renderers/drm/plugin.c
ff210d
@@ -43,6 +43,7 @@
ff210d
 #include <unistd.h>
ff210d
 
ff210d
 #include <drm.h>
ff210d
+#include <drm_mode.h>
ff210d
 #include <xf86drm.h>
ff210d
 #include <xf86drmMode.h>
ff210d
 
ff210d
@@ -62,6 +63,11 @@
ff210d
 
ff210d
 #define BYTES_PER_PIXEL (4)
ff210d
 
ff210d
+/* For builds with libdrm < 2.4.89 */
ff210d
+#ifndef DRM_MODE_ROTATE_0
ff210d
+#define DRM_MODE_ROTATE_0 (1<<0)
ff210d
+#endif
ff210d
+
ff210d
 struct _ply_renderer_head
ff210d
 {
ff210d
         ply_renderer_backend_t *backend;
ff210d
@@ -499,6 +505,85 @@ ply_renderer_head_free (ply_renderer_head_t *head)
ff210d
         free (head);
ff210d
 }
ff210d
 
ff210d
+static void
ff210d
+ply_renderer_head_clear_plane_rotation (ply_renderer_backend_t *backend,
ff210d
+                                        ply_renderer_head_t    *head)
ff210d
+{
ff210d
+        drmModeObjectPropertiesPtr plane_props;
ff210d
+        drmModePlaneResPtr plane_resources;
ff210d
+        drmModePropertyPtr prop;
ff210d
+        drmModePlanePtr plane;
ff210d
+        uint64_t rotation;
ff210d
+        uint32_t i, j;
ff210d
+        int rotation_prop_id = -1;
ff210d
+        int primary_id = -1;
ff210d
+        int err;
ff210d
+
ff210d
+        err = drmSetClientCap (backend->device_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
ff210d
+        if (err)
ff210d
+                return;
ff210d
+
ff210d
+        plane_resources = drmModeGetPlaneResources (backend->device_fd);
ff210d
+        if (!plane_resources)
ff210d
+                return;
ff210d
+
ff210d
+        for (i = 0; i < plane_resources->count_planes; i++) {
ff210d
+                plane = drmModeGetPlane (backend->device_fd,
ff210d
+                                         plane_resources->planes[i]);
ff210d
+                if (!plane)
ff210d
+                        continue;
ff210d
+
ff210d
+                if (plane->crtc_id != head->controller_id) {
ff210d
+                        drmModeFreePlane (plane);
ff210d
+                        continue;
ff210d
+                }
ff210d
+
ff210d
+                plane_props = drmModeObjectGetProperties (backend->device_fd,
ff210d
+                                                          plane->plane_id,
ff210d
+                                                          DRM_MODE_OBJECT_PLANE);
ff210d
+
ff210d
+                for (j = 0; plane_props && (j < plane_props->count_props); j++) {
ff210d
+                        prop = drmModeGetProperty (backend->device_fd,
ff210d
+                                                   plane_props->props[j]);
ff210d
+                        if (!prop)
ff210d
+                                continue;
ff210d
+
ff210d
+                        if (strcmp (prop->name, "type") == 0 &&
ff210d
+                            plane_props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY) {
ff210d
+                                primary_id = plane->plane_id;
ff210d
+                        }
ff210d
+
ff210d
+                        if (strcmp (prop->name, "rotation") == 0) {
ff210d
+                                rotation_prop_id = plane_props->props[j];
ff210d
+                                rotation = plane_props->prop_values[j];
ff210d
+                        }
ff210d
+
ff210d
+                        drmModeFreeProperty (prop);
ff210d
+                }
ff210d
+
ff210d
+                drmModeFreeObjectProperties (plane_props);
ff210d
+                drmModeFreePlane (plane);
ff210d
+
ff210d
+                if (primary_id != -1)
ff210d
+                        break;
ff210d
+
ff210d
+                /* Not primary -> clear any found rotation property */
ff210d
+                rotation_prop_id = -1;
ff210d
+        }
ff210d
+
ff210d
+        if (primary_id != -1 && rotation_prop_id != -1 && rotation != DRM_MODE_ROTATE_0) {
ff210d
+                err = drmModeObjectSetProperty (backend->device_fd,
ff210d
+                                                primary_id,
ff210d
+                                                DRM_MODE_OBJECT_PLANE,
ff210d
+                                                rotation_prop_id,
ff210d
+                                                DRM_MODE_ROTATE_0);
ff210d
+                ply_trace ("Cleared rotation on primary plane %d result %d",
ff210d
+                           primary_id, err);
ff210d
+        }
ff210d
+
ff210d
+        drmModeFreePlaneResources (plane_resources);
ff210d
+}
ff210d
+
ff210d
 static bool
ff210d
 ply_renderer_head_set_scan_out_buffer (ply_renderer_backend_t *backend,
ff210d
                                        ply_renderer_head_t    *head,
ff210d
@@ -525,6 +610,7 @@ ply_renderer_head_set_scan_out_buffer (ply_renderer_backend_t *backend,
ff210d
                 return false;
ff210d
         }
ff210d
 
ff210d
+        ply_renderer_head_clear_plane_rotation (backend, head);
ff210d
         return true;
ff210d
 }
ff210d
 
ff210d
-- 
ff210d
2.17.0
ff210d