Commit 38e0c3df authored by Leo Li's avatar Leo Li Committed by Alex Deucher

drm/amd/display: Move PRIMARY plane zpos higher

[Why]

Compositors have different ways of assigning surfaces to DRM planes for
render offloading. It may decide between various strategies: overlay,
underlay, or a mix of both (see here for more info:
https://gitlab.freedesktop.org/emersion/libliftoff/-/issues/76)

One way for compositors to implement the underlay strategy is to assign
a higher zpos to the DRM_PRIMARY plane than the DRM_OVERLAY planes,
effectively turning the DRM_OVERLAY plane into an underlay plane.

Today, amdgpu attaches an immutable zpos of 0 to the DRM_PRIMARY plane.
This however, is an arbitrary restriction. DCN pipes are general
purpose, and can be arranged in any z-order. To support compositors
using this allocation scheme, we can set a non-zero immutable zpos for
the PRIMARY, allowing the placement of OVERLAYS (mutable zpos range
0-254) beneath the PRIMARY.

[How]

Assign a zpos = #no of OVERLAY planes to the PRIMARY plane. Then, clean
up any assumptions in the driver of PRIMARY plane having the lowest
zpos.

v2: Fix typo s/decending/descending/
Reviewed-by: default avatarHarry Wentland <harry.wentland@amd.com>
Acked-by: default avatarZaeem Mohamed <zaeem.mohamed@amd.com>
Signed-off-by: default avatarLeo Li <sunpeng.li@amd.com>
Acked-by: default avatarPekka Paalanen <pekka.paalanen@collabora.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 1b04dcca
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/sort.h>
#include <drm/display/drm_dp_mst_helper.h> #include <drm/display/drm_dp_mst_helper.h>
#include <drm/display/drm_hdmi_helper.h> #include <drm/display/drm_hdmi_helper.h>
...@@ -376,6 +377,20 @@ static inline void reverse_planes_order(struct dc_surface_update *array_of_surfa ...@@ -376,6 +377,20 @@ static inline void reverse_planes_order(struct dc_surface_update *array_of_surfa
swap(array_of_surface_update[i], array_of_surface_update[j]); swap(array_of_surface_update[i], array_of_surface_update[j]);
} }
/*
* DC will program planes with their z-order determined by their ordering
* in the dc_surface_updates array. This comparator is used to sort them
* by descending zpos.
*/
static int dm_plane_layer_index_cmp(const void *a, const void *b)
{
const struct dc_surface_update *sa = (struct dc_surface_update *)a;
const struct dc_surface_update *sb = (struct dc_surface_update *)b;
/* Sort by descending dc_plane layer_index (i.e. normalized_zpos) */
return sb->surface->layer_index - sa->surface->layer_index;
}
/** /**
* update_planes_and_stream_adapter() - Send planes to be updated in DC * update_planes_and_stream_adapter() - Send planes to be updated in DC
* *
...@@ -400,7 +415,8 @@ static inline bool update_planes_and_stream_adapter(struct dc *dc, ...@@ -400,7 +415,8 @@ static inline bool update_planes_and_stream_adapter(struct dc *dc,
struct dc_stream_update *stream_update, struct dc_stream_update *stream_update,
struct dc_surface_update *array_of_surface_update) struct dc_surface_update *array_of_surface_update)
{ {
reverse_planes_order(array_of_surface_update, planes_count); sort(array_of_surface_update, planes_count,
sizeof(*array_of_surface_update), dm_plane_layer_index_cmp, NULL);
/* /*
* Previous frame finished and HW is ready for optimization. * Previous frame finished and HW is ready for optimization.
...@@ -9775,6 +9791,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -9775,6 +9791,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
for (j = 0; j < status->plane_count; j++) for (j = 0; j < status->plane_count; j++)
dummy_updates[j].surface = status->plane_states[0]; dummy_updates[j].surface = status->plane_states[0];
sort(dummy_updates, status->plane_count,
sizeof(*dummy_updates), dm_plane_layer_index_cmp, NULL);
mutex_lock(&dm->dc_lock); mutex_lock(&dm->dc_lock);
dc_exit_ips_for_hw_access(dm->dc); dc_exit_ips_for_hw_access(dm->dc);
...@@ -10510,6 +10528,16 @@ static bool should_reset_plane(struct drm_atomic_state *state, ...@@ -10510,6 +10528,16 @@ static bool should_reset_plane(struct drm_atomic_state *state,
if (new_crtc_state->color_mgmt_changed) if (new_crtc_state->color_mgmt_changed)
return true; return true;
/*
* On zpos change, planes need to be reordered by removing and re-adding
* them one by one to the dc state, in order of descending zpos.
*
* TODO: We can likely skip bandwidth validation if the only thing that
* changed about the plane was it'z z-ordering.
*/
if (new_crtc_state->zpos_changed)
return true;
if (drm_atomic_crtc_needs_modeset(new_crtc_state)) if (drm_atomic_crtc_needs_modeset(new_crtc_state))
return true; return true;
...@@ -11352,7 +11380,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -11352,7 +11380,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
} }
/* Remove exiting planes if they are modified */ /* Remove exiting planes if they are modified */
for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) { for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, new_plane_state) {
if (old_plane_state->fb && new_plane_state->fb && if (old_plane_state->fb && new_plane_state->fb &&
get_mem_type(old_plane_state->fb) != get_mem_type(old_plane_state->fb) !=
get_mem_type(new_plane_state->fb)) get_mem_type(new_plane_state->fb))
...@@ -11397,7 +11425,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -11397,7 +11425,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
} }
/* Add new/modified planes */ /* Add new/modified planes */
for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) { for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, new_plane_state) {
ret = dm_update_plane_state(dc, state, plane, ret = dm_update_plane_state(dc, state, plane,
old_plane_state, old_plane_state,
new_plane_state, new_plane_state,
......
...@@ -104,8 +104,6 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state ...@@ -104,8 +104,6 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state
*global_alpha = false; *global_alpha = false;
*global_alpha_value = 0xff; *global_alpha_value = 0xff;
if (plane_state->plane->type == DRM_PLANE_TYPE_PRIMARY)
return;
if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI || if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) { plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
...@@ -1701,6 +1699,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, ...@@ -1701,6 +1699,7 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
int res = -EPERM; int res = -EPERM;
unsigned int supported_rotations; unsigned int supported_rotations;
uint64_t *modifiers = NULL; uint64_t *modifiers = NULL;
unsigned int primary_zpos = dm->dc->caps.max_slave_planes;
num_formats = amdgpu_dm_plane_get_plane_formats(plane, plane_cap, formats, num_formats = amdgpu_dm_plane_get_plane_formats(plane, plane_cap, formats,
ARRAY_SIZE(formats)); ARRAY_SIZE(formats));
...@@ -1730,10 +1729,19 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, ...@@ -1730,10 +1729,19 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
} }
if (plane->type == DRM_PLANE_TYPE_PRIMARY) { if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
drm_plane_create_zpos_immutable_property(plane, 0); /*
* Allow OVERLAY planes to be used as underlays by assigning an
* immutable zpos = # of OVERLAY planes to the PRIMARY plane.
*/
drm_plane_create_zpos_immutable_property(plane, primary_zpos);
} else if (plane->type == DRM_PLANE_TYPE_OVERLAY) { } else if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
unsigned int zpos = 1 + drm_plane_index(plane); /*
drm_plane_create_zpos_property(plane, zpos, 1, 254); * OVERLAY planes can be below or above the PRIMARY, but cannot
* be above the CURSOR plane.
*/
unsigned int zpos = primary_zpos + 1 + drm_plane_index(plane);
drm_plane_create_zpos_property(plane, zpos, 0, 254);
} else if (plane->type == DRM_PLANE_TYPE_CURSOR) { } else if (plane->type == DRM_PLANE_TYPE_CURSOR) {
drm_plane_create_zpos_immutable_property(plane, 255); drm_plane_create_zpos_immutable_property(plane, 255);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment