drm/amd/display: Fix wrong z-order when updating overlay planes
authorNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Fri, 18 Jan 2019 18:17:55 +0000 (13:17 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 19 Feb 2019 20:58:26 +0000 (15:58 -0500)
[Why]
If a commit updates an overlay plane via the legacy plane IOCTL
then the only plane in the state will be the overlay plane.

Overlay planes need to be added first to the DC context, but in the
scenario above the plane will be added last. This will result in wrong
z-order during rendering.

[How]
If any non-cursor plane has been updated then the rest of the
non-cursor planes should be added to the CRTC state.

The cursor plane doesn't need to be included for stream updates and
locking it will cause performance issues. It should be ignored.

DC requires that the surface count passed during stream updates
be the number of surfaces currently on the stream to enable fast
updates. This previously wasn't the case without this patch, so this
also allows this optimization to occur.

Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Reviewed-by: Leo Li <sunpeng.li@amd.com>
Acked-by: Tony Cheng <Tony.Cheng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index c7b66fa4a13eb5cf1ec154f5189b589412354159..409e603a3686e0a0e757a2ea8ff8927b80e49e36 100644 (file)
@@ -5948,6 +5948,42 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                        goto fail;
        }
 
+       /*
+        * Add all primary and overlay planes on the CRTC to the state
+        * whenever a plane is enabled to maintain correct z-ordering
+        * and to enable fast surface updates.
+        */
+       drm_for_each_crtc(crtc, dev) {
+               bool modified = false;
+
+               for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
+                       if (plane->type == DRM_PLANE_TYPE_CURSOR)
+                               continue;
+
+                       if (new_plane_state->crtc == crtc ||
+                           old_plane_state->crtc == crtc) {
+                               modified = true;
+                               break;
+                       }
+               }
+
+               if (!modified)
+                       continue;
+
+               drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) {
+                       if (plane->type == DRM_PLANE_TYPE_CURSOR)
+                               continue;
+
+                       new_plane_state =
+                               drm_atomic_get_plane_state(state, plane);
+
+                       if (IS_ERR(new_plane_state)) {
+                               ret = PTR_ERR(new_plane_state);
+                               goto fail;
+                       }
+               }
+       }
+
        /* Remove exiting planes if they are modified */
        for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
                ret = dm_update_plane_state(dc, state, plane,