All of lore.kernel.org
 help / color / mirror / Atom feed
From: Leo Li <sunpeng.li@amd.com>
To: Hamza Mahfooz <hamza.mahfooz@amd.com>, amd-gfx@lists.freedesktop.org
Cc: "Yifan Zhang" <yifan1.zhang@amd.com>,
	"David Airlie" <airlied@linux.ie>,
	"Maíra Canal" <maira.canal@usp.br>,
	dri-devel@lists.freedesktop.org, "Pan,
	Xinhui" <Xinhui.Pan@amd.com>,
	"Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>,
	"Roman Li" <roman.li@amd.com>,
	"Joaquín Ignacio Aramendía" <samsagax@gmail.com>,
	"Nicholas Kazlauskas" <nicholas.kazlauskas@amd.com>,
	"Fangzhi Zuo" <Jerry.Zuo@amd.com>,
	"Aurabindo Pillai" <aurabindo.pillai@amd.com>,
	"Mario Limonciello" <mario.limonciello@amd.com>,
	"Daniel Vetter" <daniel@ffwll.ch>,
	"Alex Deucher" <alexander.deucher@amd.com>,
	"Dave Airlie" <airlied@redhat.com>,
	"Harry Wentland" <harry.wentland@amd.com>,
	"Christian König" <christian.koenig@amd.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] drm/amd/display: add FB_DAMAGE_CLIPS support
Date: Thu, 17 Nov 2022 12:31:01 -0500	[thread overview]
Message-ID: <8f0c640f-e093-3977-0203-52e69da6e59d@amd.com> (raw)
In-Reply-To: <20221115202413.283685-1-hamza.mahfooz@amd.com>



On 11/15/22 15:24, Hamza Mahfooz wrote:
> Currently, userspace doesn't have a way to communicate selective updates
> to displays. So, enable support for FB_DAMAGE_CLIPS for DCN ASICs newer
> than DCN301, convert DRM damage clips to dc dirty rectangles and fill
> them into dirty_rects in fill_dc_dirty_rects().
> 
> Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 91 +++++++++++--------
>   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  4 +
>   2 files changed, 58 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 185d09c760ba..18b710ba802d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -4842,6 +4842,31 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
>   	return 0;
>   }
>   
> +static inline void fill_dc_dirty_rect(struct drm_plane *plane,
> +				      struct rect *dirty_rect, int32_t x,
> +				      int32_t y, int32_t width, int32_t height,
> +				      int *i, bool ffu)
> +{
> +	WARN_ON(*i >= DC_MAX_DIRTY_RECTS);

Hi Hamza,

Since dc_flip_addrs->dirty_rects has a fixed length of 
DC_MAX_DIRTY_RECTS per pipe (a restriction by DMUB FW), I think it makes 
more sense to fallback to a full-frame-update (FFU) if num_clips > 
DC_MAX_DIRTY_RECTS. An alternative would be to reject the atomic commit, 
but that sounds heavy handed.


> +
> +	dirty_rect->x = x;
> +	dirty_rect->y = y;
> +	dirty_rect->width = width;
> +	dirty_rect->height = height;
> +
> +	if (ffu)
> +		drm_dbg(plane->dev,
> +			"[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
> +			plane->base.id, width, height);
> +	else
> +		drm_dbg(plane->dev,
> +			"[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)",
> +			plane->base.id, x, y, width, height);
> +
> +	(*i)++;
> +}
> +
> +
>   /**
>    * fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
>    *
> @@ -4862,10 +4887,6 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
>    * addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
>    * implicitly provide damage clips without any client support via the plane
>    * bounds.
> - *
> - * Today, amdgpu_dm only supports the MPO and cursor usecase.
> - *
> - * TODO: Also enable for FB_DAMAGE_CLIPS
>    */
>   static void fill_dc_dirty_rects(struct drm_plane *plane,
>   				struct drm_plane_state *old_plane_state,
> @@ -4876,12 +4897,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
>   	struct rect *dirty_rects = flip_addrs->dirty_rects;
>   	uint32_t num_clips;
> +	struct drm_mode_rect *clips;
>   	bool bb_changed;
>   	bool fb_changed;
>   	uint32_t i = 0;
>   
> -	flip_addrs->dirty_rect_count = 0;
> -
>   	/*
>   	 * Cursor plane has it's own dirty rect update interface. See
>   	 * dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
> @@ -4894,15 +4914,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	 * requested, and there is a plane update, do FFU.
>   	 */
>   	if (!dm_crtc_state->mpo_requested) {
> -		dirty_rects[0].x = 0;
> -		dirty_rects[0].y = 0;
> -		dirty_rects[0].width = dm_crtc_state->base.mode.crtc_hdisplay;
> -		dirty_rects[0].height = dm_crtc_state->base.mode.crtc_vdisplay;
> -		flip_addrs->dirty_rect_count = 1;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
> -				 new_plane_state->plane->base.id,
> -				 dm_crtc_state->base.mode.crtc_hdisplay,
> -				 dm_crtc_state->base.mode.crtc_vdisplay);
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[0], 0,
> +				   0, dm_crtc_state->base.mode.crtc_hdisplay,
> +				   dm_crtc_state->base.mode.crtc_vdisplay, &i,
> +				   true);
> +		flip_addrs->dirty_rect_count = i;
>   		return;
>   	}

Previously, we always do FFU on plane updates if no MPO has been 
requested. Now, since we want to look at user-provided DRM damage clips, 
this bit needs a bit of a rework.

In short, if there are valid clips for this plane 
(drm_plane_get_damage_clips_count() > 0), they should be added to 
dc_dirty_rects. Otherwise, fallback to old FFU logic.

With MPO, the damage clips are more interesting, since the entire 
plane's bounding box can be moved. I wonder if that is reflected in 
DRM's damage clips. Do you know if a plane bb change will be reflected 
in drm_plane_get_damage_clips()?

Thanks,
Leo
>   
> @@ -4914,6 +4930,7 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	 * rects.
>   	 */
>   	num_clips = drm_plane_get_damage_clips_count(new_plane_state);
> +	clips = drm_plane_get_damage_clips(new_plane_state);
>   	fb_changed = old_plane_state->fb->base.id !=
>   		     new_plane_state->fb->base.id;
>   	bb_changed = (old_plane_state->crtc_x != new_plane_state->crtc_x ||
> @@ -4921,33 +4938,33 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   		      old_plane_state->crtc_w != new_plane_state->crtc_w ||
>   		      old_plane_state->crtc_h != new_plane_state->crtc_h);
>   
> -	DRM_DEBUG_DRIVER("[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
> -			 new_plane_state->plane->base.id,
> -			 bb_changed, fb_changed, num_clips);
> +	drm_dbg(plane->dev,
> +		"[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
> +		new_plane_state->plane->base.id,
> +		bb_changed, fb_changed, num_clips);
>   
> -	if (num_clips || fb_changed || bb_changed) {
> -		dirty_rects[i].x = new_plane_state->crtc_x;
> -		dirty_rects[i].y = new_plane_state->crtc_y;
> -		dirty_rects[i].width = new_plane_state->crtc_w;
> -		dirty_rects[i].height = new_plane_state->crtc_h;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
> -				 new_plane_state->plane->base.id,
> -				 dirty_rects[i].x, dirty_rects[i].y,
> -				 dirty_rects[i].width, dirty_rects[i].height);
> -		i += 1;
> +	if (num_clips) {
> +		for (; i < num_clips; i++, clips++) {
> +			fill_dc_dirty_rect(new_plane_state->plane,
> +					   &dirty_rects[i], clips->x1,
> +					   clips->y1, clips->x2 - clips->x1,
> +					   clips->y2 - clips->y1, &i, false);
> +		}
> +	} else if (fb_changed || bb_changed) {
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
> +				   new_plane_state->crtc_x,
> +				   new_plane_state->crtc_y,
> +				   new_plane_state->crtc_w,
> +				   new_plane_state->crtc_h, &i, false);
>   	}
>   
>   	/* Add old plane bounding-box if plane is moved or resized */
>   	if (bb_changed) {
> -		dirty_rects[i].x = old_plane_state->crtc_x;
> -		dirty_rects[i].y = old_plane_state->crtc_y;
> -		dirty_rects[i].width = old_plane_state->crtc_w;
> -		dirty_rects[i].height = old_plane_state->crtc_h;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
> -				old_plane_state->plane->base.id,
> -				dirty_rects[i].x, dirty_rects[i].y,
> -				dirty_rects[i].width, dirty_rects[i].height);
> -		i += 1;
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
> +				   old_plane_state->crtc_x,
> +				   old_plane_state->crtc_y,
> +				   old_plane_state->crtc_w,
> +				   old_plane_state->crtc_h, &i, false);
>   	}
>   
>   	flip_addrs->dirty_rect_count = i;
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index e6854f7270a6..3c50b3ff7954 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1600,6 +1600,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
>   		drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
>   						   supported_rotations);
>   
> +	if (dm->adev->ip_versions[DCE_HWIP][0] > IP_VERSION(3, 0, 1) &&
> +	    plane->type != DRM_PLANE_TYPE_CURSOR)
> +		drm_plane_enable_fb_damage_clips(plane);
> +
>   	drm_plane_helper_add(plane, &dm_plane_helper_funcs);
>   
>   #ifdef CONFIG_DRM_AMD_DC_HDR

WARNING: multiple messages have this Message-ID (diff)
From: Leo Li <sunpeng.li@amd.com>
To: Hamza Mahfooz <hamza.mahfooz@amd.com>, amd-gfx@lists.freedesktop.org
Cc: "Yifan Zhang" <yifan1.zhang@amd.com>,
	"David Airlie" <airlied@linux.ie>,
	"Maíra Canal" <maira.canal@usp.br>,
	dri-devel@lists.freedesktop.org, "Pan,
	Xinhui" <Xinhui.Pan@amd.com>,
	"Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>,
	"Roman Li" <roman.li@amd.com>,
	"Joaquín Ignacio Aramendía" <samsagax@gmail.com>,
	"Nicholas Kazlauskas" <nicholas.kazlauskas@amd.com>,
	"Fangzhi Zuo" <Jerry.Zuo@amd.com>,
	"Aurabindo Pillai" <aurabindo.pillai@amd.com>,
	"Mario Limonciello" <mario.limonciello@amd.com>,
	"Alex Deucher" <alexander.deucher@amd.com>,
	"Dave Airlie" <airlied@redhat.com>,
	"Christian König" <christian.koenig@amd.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] drm/amd/display: add FB_DAMAGE_CLIPS support
Date: Thu, 17 Nov 2022 12:31:01 -0500	[thread overview]
Message-ID: <8f0c640f-e093-3977-0203-52e69da6e59d@amd.com> (raw)
In-Reply-To: <20221115202413.283685-1-hamza.mahfooz@amd.com>



On 11/15/22 15:24, Hamza Mahfooz wrote:
> Currently, userspace doesn't have a way to communicate selective updates
> to displays. So, enable support for FB_DAMAGE_CLIPS for DCN ASICs newer
> than DCN301, convert DRM damage clips to dc dirty rectangles and fill
> them into dirty_rects in fill_dc_dirty_rects().
> 
> Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 91 +++++++++++--------
>   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  4 +
>   2 files changed, 58 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 185d09c760ba..18b710ba802d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -4842,6 +4842,31 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
>   	return 0;
>   }
>   
> +static inline void fill_dc_dirty_rect(struct drm_plane *plane,
> +				      struct rect *dirty_rect, int32_t x,
> +				      int32_t y, int32_t width, int32_t height,
> +				      int *i, bool ffu)
> +{
> +	WARN_ON(*i >= DC_MAX_DIRTY_RECTS);

Hi Hamza,

Since dc_flip_addrs->dirty_rects has a fixed length of 
DC_MAX_DIRTY_RECTS per pipe (a restriction by DMUB FW), I think it makes 
more sense to fallback to a full-frame-update (FFU) if num_clips > 
DC_MAX_DIRTY_RECTS. An alternative would be to reject the atomic commit, 
but that sounds heavy handed.


> +
> +	dirty_rect->x = x;
> +	dirty_rect->y = y;
> +	dirty_rect->width = width;
> +	dirty_rect->height = height;
> +
> +	if (ffu)
> +		drm_dbg(plane->dev,
> +			"[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
> +			plane->base.id, width, height);
> +	else
> +		drm_dbg(plane->dev,
> +			"[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)",
> +			plane->base.id, x, y, width, height);
> +
> +	(*i)++;
> +}
> +
> +
>   /**
>    * fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
>    *
> @@ -4862,10 +4887,6 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
>    * addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
>    * implicitly provide damage clips without any client support via the plane
>    * bounds.
> - *
> - * Today, amdgpu_dm only supports the MPO and cursor usecase.
> - *
> - * TODO: Also enable for FB_DAMAGE_CLIPS
>    */
>   static void fill_dc_dirty_rects(struct drm_plane *plane,
>   				struct drm_plane_state *old_plane_state,
> @@ -4876,12 +4897,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
>   	struct rect *dirty_rects = flip_addrs->dirty_rects;
>   	uint32_t num_clips;
> +	struct drm_mode_rect *clips;
>   	bool bb_changed;
>   	bool fb_changed;
>   	uint32_t i = 0;
>   
> -	flip_addrs->dirty_rect_count = 0;
> -
>   	/*
>   	 * Cursor plane has it's own dirty rect update interface. See
>   	 * dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
> @@ -4894,15 +4914,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	 * requested, and there is a plane update, do FFU.
>   	 */
>   	if (!dm_crtc_state->mpo_requested) {
> -		dirty_rects[0].x = 0;
> -		dirty_rects[0].y = 0;
> -		dirty_rects[0].width = dm_crtc_state->base.mode.crtc_hdisplay;
> -		dirty_rects[0].height = dm_crtc_state->base.mode.crtc_vdisplay;
> -		flip_addrs->dirty_rect_count = 1;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
> -				 new_plane_state->plane->base.id,
> -				 dm_crtc_state->base.mode.crtc_hdisplay,
> -				 dm_crtc_state->base.mode.crtc_vdisplay);
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[0], 0,
> +				   0, dm_crtc_state->base.mode.crtc_hdisplay,
> +				   dm_crtc_state->base.mode.crtc_vdisplay, &i,
> +				   true);
> +		flip_addrs->dirty_rect_count = i;
>   		return;
>   	}

Previously, we always do FFU on plane updates if no MPO has been 
requested. Now, since we want to look at user-provided DRM damage clips, 
this bit needs a bit of a rework.

In short, if there are valid clips for this plane 
(drm_plane_get_damage_clips_count() > 0), they should be added to 
dc_dirty_rects. Otherwise, fallback to old FFU logic.

With MPO, the damage clips are more interesting, since the entire 
plane's bounding box can be moved. I wonder if that is reflected in 
DRM's damage clips. Do you know if a plane bb change will be reflected 
in drm_plane_get_damage_clips()?

Thanks,
Leo
>   
> @@ -4914,6 +4930,7 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	 * rects.
>   	 */
>   	num_clips = drm_plane_get_damage_clips_count(new_plane_state);
> +	clips = drm_plane_get_damage_clips(new_plane_state);
>   	fb_changed = old_plane_state->fb->base.id !=
>   		     new_plane_state->fb->base.id;
>   	bb_changed = (old_plane_state->crtc_x != new_plane_state->crtc_x ||
> @@ -4921,33 +4938,33 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   		      old_plane_state->crtc_w != new_plane_state->crtc_w ||
>   		      old_plane_state->crtc_h != new_plane_state->crtc_h);
>   
> -	DRM_DEBUG_DRIVER("[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
> -			 new_plane_state->plane->base.id,
> -			 bb_changed, fb_changed, num_clips);
> +	drm_dbg(plane->dev,
> +		"[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
> +		new_plane_state->plane->base.id,
> +		bb_changed, fb_changed, num_clips);
>   
> -	if (num_clips || fb_changed || bb_changed) {
> -		dirty_rects[i].x = new_plane_state->crtc_x;
> -		dirty_rects[i].y = new_plane_state->crtc_y;
> -		dirty_rects[i].width = new_plane_state->crtc_w;
> -		dirty_rects[i].height = new_plane_state->crtc_h;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
> -				 new_plane_state->plane->base.id,
> -				 dirty_rects[i].x, dirty_rects[i].y,
> -				 dirty_rects[i].width, dirty_rects[i].height);
> -		i += 1;
> +	if (num_clips) {
> +		for (; i < num_clips; i++, clips++) {
> +			fill_dc_dirty_rect(new_plane_state->plane,
> +					   &dirty_rects[i], clips->x1,
> +					   clips->y1, clips->x2 - clips->x1,
> +					   clips->y2 - clips->y1, &i, false);
> +		}
> +	} else if (fb_changed || bb_changed) {
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
> +				   new_plane_state->crtc_x,
> +				   new_plane_state->crtc_y,
> +				   new_plane_state->crtc_w,
> +				   new_plane_state->crtc_h, &i, false);
>   	}
>   
>   	/* Add old plane bounding-box if plane is moved or resized */
>   	if (bb_changed) {
> -		dirty_rects[i].x = old_plane_state->crtc_x;
> -		dirty_rects[i].y = old_plane_state->crtc_y;
> -		dirty_rects[i].width = old_plane_state->crtc_w;
> -		dirty_rects[i].height = old_plane_state->crtc_h;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
> -				old_plane_state->plane->base.id,
> -				dirty_rects[i].x, dirty_rects[i].y,
> -				dirty_rects[i].width, dirty_rects[i].height);
> -		i += 1;
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
> +				   old_plane_state->crtc_x,
> +				   old_plane_state->crtc_y,
> +				   old_plane_state->crtc_w,
> +				   old_plane_state->crtc_h, &i, false);
>   	}
>   
>   	flip_addrs->dirty_rect_count = i;
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index e6854f7270a6..3c50b3ff7954 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1600,6 +1600,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
>   		drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
>   						   supported_rotations);
>   
> +	if (dm->adev->ip_versions[DCE_HWIP][0] > IP_VERSION(3, 0, 1) &&
> +	    plane->type != DRM_PLANE_TYPE_CURSOR)
> +		drm_plane_enable_fb_damage_clips(plane);
> +
>   	drm_plane_helper_add(plane, &dm_plane_helper_funcs);
>   
>   #ifdef CONFIG_DRM_AMD_DC_HDR

WARNING: multiple messages have this Message-ID (diff)
From: Leo Li <sunpeng.li@amd.com>
To: Hamza Mahfooz <hamza.mahfooz@amd.com>, amd-gfx@lists.freedesktop.org
Cc: "Harry Wentland" <harry.wentland@amd.com>,
	"Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>,
	"Alex Deucher" <alexander.deucher@amd.com>,
	"Christian König" <christian.koenig@amd.com>,
	"Pan, Xinhui" <Xinhui.Pan@amd.com>,
	"David Airlie" <airlied@linux.ie>,
	"Daniel Vetter" <daniel@ffwll.ch>,
	"Nicholas Kazlauskas" <nicholas.kazlauskas@amd.com>,
	"Roman Li" <roman.li@amd.com>, "Fangzhi Zuo" <Jerry.Zuo@amd.com>,
	"Aurabindo Pillai" <aurabindo.pillai@amd.com>,
	"Joaquín Ignacio Aramendía" <samsagax@gmail.com>,
	"Mario Limonciello" <mario.limonciello@amd.com>,
	"Maíra Canal" <maira.canal@usp.br>,
	"Dave Airlie" <airlied@redhat.com>,
	"Yifan Zhang" <yifan1.zhang@amd.com>,
	dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] drm/amd/display: add FB_DAMAGE_CLIPS support
Date: Thu, 17 Nov 2022 12:31:01 -0500	[thread overview]
Message-ID: <8f0c640f-e093-3977-0203-52e69da6e59d@amd.com> (raw)
In-Reply-To: <20221115202413.283685-1-hamza.mahfooz@amd.com>



On 11/15/22 15:24, Hamza Mahfooz wrote:
> Currently, userspace doesn't have a way to communicate selective updates
> to displays. So, enable support for FB_DAMAGE_CLIPS for DCN ASICs newer
> than DCN301, convert DRM damage clips to dc dirty rectangles and fill
> them into dirty_rects in fill_dc_dirty_rects().
> 
> Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
> ---
>   .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 91 +++++++++++--------
>   .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  4 +
>   2 files changed, 58 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 185d09c760ba..18b710ba802d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -4842,6 +4842,31 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
>   	return 0;
>   }
>   
> +static inline void fill_dc_dirty_rect(struct drm_plane *plane,
> +				      struct rect *dirty_rect, int32_t x,
> +				      int32_t y, int32_t width, int32_t height,
> +				      int *i, bool ffu)
> +{
> +	WARN_ON(*i >= DC_MAX_DIRTY_RECTS);

Hi Hamza,

Since dc_flip_addrs->dirty_rects has a fixed length of 
DC_MAX_DIRTY_RECTS per pipe (a restriction by DMUB FW), I think it makes 
more sense to fallback to a full-frame-update (FFU) if num_clips > 
DC_MAX_DIRTY_RECTS. An alternative would be to reject the atomic commit, 
but that sounds heavy handed.


> +
> +	dirty_rect->x = x;
> +	dirty_rect->y = y;
> +	dirty_rect->width = width;
> +	dirty_rect->height = height;
> +
> +	if (ffu)
> +		drm_dbg(plane->dev,
> +			"[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
> +			plane->base.id, width, height);
> +	else
> +		drm_dbg(plane->dev,
> +			"[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)",
> +			plane->base.id, x, y, width, height);
> +
> +	(*i)++;
> +}
> +
> +
>   /**
>    * fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
>    *
> @@ -4862,10 +4887,6 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
>    * addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
>    * implicitly provide damage clips without any client support via the plane
>    * bounds.
> - *
> - * Today, amdgpu_dm only supports the MPO and cursor usecase.
> - *
> - * TODO: Also enable for FB_DAMAGE_CLIPS
>    */
>   static void fill_dc_dirty_rects(struct drm_plane *plane,
>   				struct drm_plane_state *old_plane_state,
> @@ -4876,12 +4897,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
>   	struct rect *dirty_rects = flip_addrs->dirty_rects;
>   	uint32_t num_clips;
> +	struct drm_mode_rect *clips;
>   	bool bb_changed;
>   	bool fb_changed;
>   	uint32_t i = 0;
>   
> -	flip_addrs->dirty_rect_count = 0;
> -
>   	/*
>   	 * Cursor plane has it's own dirty rect update interface. See
>   	 * dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
> @@ -4894,15 +4914,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	 * requested, and there is a plane update, do FFU.
>   	 */
>   	if (!dm_crtc_state->mpo_requested) {
> -		dirty_rects[0].x = 0;
> -		dirty_rects[0].y = 0;
> -		dirty_rects[0].width = dm_crtc_state->base.mode.crtc_hdisplay;
> -		dirty_rects[0].height = dm_crtc_state->base.mode.crtc_vdisplay;
> -		flip_addrs->dirty_rect_count = 1;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
> -				 new_plane_state->plane->base.id,
> -				 dm_crtc_state->base.mode.crtc_hdisplay,
> -				 dm_crtc_state->base.mode.crtc_vdisplay);
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[0], 0,
> +				   0, dm_crtc_state->base.mode.crtc_hdisplay,
> +				   dm_crtc_state->base.mode.crtc_vdisplay, &i,
> +				   true);
> +		flip_addrs->dirty_rect_count = i;
>   		return;
>   	}

Previously, we always do FFU on plane updates if no MPO has been 
requested. Now, since we want to look at user-provided DRM damage clips, 
this bit needs a bit of a rework.

In short, if there are valid clips for this plane 
(drm_plane_get_damage_clips_count() > 0), they should be added to 
dc_dirty_rects. Otherwise, fallback to old FFU logic.

With MPO, the damage clips are more interesting, since the entire 
plane's bounding box can be moved. I wonder if that is reflected in 
DRM's damage clips. Do you know if a plane bb change will be reflected 
in drm_plane_get_damage_clips()?

Thanks,
Leo
>   
> @@ -4914,6 +4930,7 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   	 * rects.
>   	 */
>   	num_clips = drm_plane_get_damage_clips_count(new_plane_state);
> +	clips = drm_plane_get_damage_clips(new_plane_state);
>   	fb_changed = old_plane_state->fb->base.id !=
>   		     new_plane_state->fb->base.id;
>   	bb_changed = (old_plane_state->crtc_x != new_plane_state->crtc_x ||
> @@ -4921,33 +4938,33 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
>   		      old_plane_state->crtc_w != new_plane_state->crtc_w ||
>   		      old_plane_state->crtc_h != new_plane_state->crtc_h);
>   
> -	DRM_DEBUG_DRIVER("[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
> -			 new_plane_state->plane->base.id,
> -			 bb_changed, fb_changed, num_clips);
> +	drm_dbg(plane->dev,
> +		"[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
> +		new_plane_state->plane->base.id,
> +		bb_changed, fb_changed, num_clips);
>   
> -	if (num_clips || fb_changed || bb_changed) {
> -		dirty_rects[i].x = new_plane_state->crtc_x;
> -		dirty_rects[i].y = new_plane_state->crtc_y;
> -		dirty_rects[i].width = new_plane_state->crtc_w;
> -		dirty_rects[i].height = new_plane_state->crtc_h;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
> -				 new_plane_state->plane->base.id,
> -				 dirty_rects[i].x, dirty_rects[i].y,
> -				 dirty_rects[i].width, dirty_rects[i].height);
> -		i += 1;
> +	if (num_clips) {
> +		for (; i < num_clips; i++, clips++) {
> +			fill_dc_dirty_rect(new_plane_state->plane,
> +					   &dirty_rects[i], clips->x1,
> +					   clips->y1, clips->x2 - clips->x1,
> +					   clips->y2 - clips->y1, &i, false);
> +		}
> +	} else if (fb_changed || bb_changed) {
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
> +				   new_plane_state->crtc_x,
> +				   new_plane_state->crtc_y,
> +				   new_plane_state->crtc_w,
> +				   new_plane_state->crtc_h, &i, false);
>   	}
>   
>   	/* Add old plane bounding-box if plane is moved or resized */
>   	if (bb_changed) {
> -		dirty_rects[i].x = old_plane_state->crtc_x;
> -		dirty_rects[i].y = old_plane_state->crtc_y;
> -		dirty_rects[i].width = old_plane_state->crtc_w;
> -		dirty_rects[i].height = old_plane_state->crtc_h;
> -		DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
> -				old_plane_state->plane->base.id,
> -				dirty_rects[i].x, dirty_rects[i].y,
> -				dirty_rects[i].width, dirty_rects[i].height);
> -		i += 1;
> +		fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
> +				   old_plane_state->crtc_x,
> +				   old_plane_state->crtc_y,
> +				   old_plane_state->crtc_w,
> +				   old_plane_state->crtc_h, &i, false);
>   	}
>   
>   	flip_addrs->dirty_rect_count = i;
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index e6854f7270a6..3c50b3ff7954 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1600,6 +1600,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
>   		drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
>   						   supported_rotations);
>   
> +	if (dm->adev->ip_versions[DCE_HWIP][0] > IP_VERSION(3, 0, 1) &&
> +	    plane->type != DRM_PLANE_TYPE_CURSOR)
> +		drm_plane_enable_fb_damage_clips(plane);
> +
>   	drm_plane_helper_add(plane, &dm_plane_helper_funcs);
>   
>   #ifdef CONFIG_DRM_AMD_DC_HDR

  reply	other threads:[~2022-11-17 17:31 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-15 20:24 [PATCH] drm/amd/display: add FB_DAMAGE_CLIPS support Hamza Mahfooz
2022-11-15 20:24 ` Hamza Mahfooz
2022-11-15 20:24 ` Hamza Mahfooz
2022-11-17 17:31 ` Leo Li [this message]
2022-11-17 17:31   ` Leo Li
2022-11-17 17:31   ` Leo Li
2022-11-18 15:07   ` Hamza Mahfooz
2022-11-18 15:07     ` Hamza Mahfooz
2022-11-18 15:07     ` Hamza Mahfooz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8f0c640f-e093-3977-0203-52e69da6e59d@amd.com \
    --to=sunpeng.li@amd.com \
    --cc=Jerry.Zuo@amd.com \
    --cc=Rodrigo.Siqueira@amd.com \
    --cc=Xinhui.Pan@amd.com \
    --cc=airlied@linux.ie \
    --cc=airlied@redhat.com \
    --cc=alexander.deucher@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=aurabindo.pillai@amd.com \
    --cc=christian.koenig@amd.com \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hamza.mahfooz@amd.com \
    --cc=harry.wentland@amd.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maira.canal@usp.br \
    --cc=mario.limonciello@amd.com \
    --cc=nicholas.kazlauskas@amd.com \
    --cc=roman.li@amd.com \
    --cc=samsagax@gmail.com \
    --cc=yifan1.zhang@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.