drm/amd/display: add FB_DAMAGE_CLIPS support
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(). Reviewed-by: Leo Li <sunpeng.li@amd.com> Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
fed58c70bb
commit
30ebe41582
2 changed files with 87 additions and 45 deletions
|
@ -4869,6 +4869,35 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
|
||||||
return 0;
|
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)
|
||||||
|
{
|
||||||
|
if (*i > DC_MAX_DIRTY_RECTS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (*i == DC_MAX_DIRTY_RECTS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
out:
|
||||||
|
(*i)++;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
|
* fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
|
||||||
*
|
*
|
||||||
|
@ -4889,10 +4918,6 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
|
||||||
* addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
|
* addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
|
||||||
* implicitly provide damage clips without any client support via the plane
|
* implicitly provide damage clips without any client support via the plane
|
||||||
* bounds.
|
* 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,
|
static void fill_dc_dirty_rects(struct drm_plane *plane,
|
||||||
struct drm_plane_state *old_plane_state,
|
struct drm_plane_state *old_plane_state,
|
||||||
|
@ -4903,12 +4928,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 dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
|
||||||
struct rect *dirty_rects = flip_addrs->dirty_rects;
|
struct rect *dirty_rects = flip_addrs->dirty_rects;
|
||||||
uint32_t num_clips;
|
uint32_t num_clips;
|
||||||
|
struct drm_mode_rect *clips;
|
||||||
bool bb_changed;
|
bool bb_changed;
|
||||||
bool fb_changed;
|
bool fb_changed;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
flip_addrs->dirty_rect_count = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cursor plane has it's own dirty rect update interface. See
|
* Cursor plane has it's own dirty rect update interface. See
|
||||||
* dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
|
* dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
|
||||||
|
@ -4916,20 +4940,20 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
|
||||||
if (plane->type == DRM_PLANE_TYPE_CURSOR)
|
if (plane->type == DRM_PLANE_TYPE_CURSOR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
num_clips = drm_plane_get_damage_clips_count(new_plane_state);
|
||||||
* Today, we only consider MPO use-case for PSR SU. If MPO not
|
clips = drm_plane_get_damage_clips(new_plane_state);
|
||||||
* requested, and there is a plane update, do FFU.
|
|
||||||
*/
|
|
||||||
if (!dm_crtc_state->mpo_requested) {
|
if (!dm_crtc_state->mpo_requested) {
|
||||||
dirty_rects[0].x = 0;
|
if (!num_clips || num_clips > DC_MAX_DIRTY_RECTS)
|
||||||
dirty_rects[0].y = 0;
|
goto ffu;
|
||||||
dirty_rects[0].width = dm_crtc_state->base.mode.crtc_hdisplay;
|
|
||||||
dirty_rects[0].height = dm_crtc_state->base.mode.crtc_vdisplay;
|
for (; flip_addrs->dirty_rect_count < num_clips; clips++)
|
||||||
flip_addrs->dirty_rect_count = 1;
|
fill_dc_dirty_rect(new_plane_state->plane,
|
||||||
DRM_DEBUG_DRIVER("[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
|
&dirty_rects[i], clips->x1,
|
||||||
new_plane_state->plane->base.id,
|
clips->y1, clips->x2 - clips->x1,
|
||||||
dm_crtc_state->base.mode.crtc_hdisplay,
|
clips->y2 - clips->y1,
|
||||||
dm_crtc_state->base.mode.crtc_vdisplay);
|
&flip_addrs->dirty_rect_count,
|
||||||
|
false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4940,7 +4964,6 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
|
||||||
* If plane is moved or resized, also add old bounding box to dirty
|
* If plane is moved or resized, also add old bounding box to dirty
|
||||||
* rects.
|
* rects.
|
||||||
*/
|
*/
|
||||||
num_clips = drm_plane_get_damage_clips_count(new_plane_state);
|
|
||||||
fb_changed = old_plane_state->fb->base.id !=
|
fb_changed = old_plane_state->fb->base.id !=
|
||||||
new_plane_state->fb->base.id;
|
new_plane_state->fb->base.id;
|
||||||
bb_changed = (old_plane_state->crtc_x != new_plane_state->crtc_x ||
|
bb_changed = (old_plane_state->crtc_x != new_plane_state->crtc_x ||
|
||||||
|
@ -4948,36 +4971,51 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
|
||||||
old_plane_state->crtc_w != new_plane_state->crtc_w ||
|
old_plane_state->crtc_w != new_plane_state->crtc_w ||
|
||||||
old_plane_state->crtc_h != new_plane_state->crtc_h);
|
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",
|
drm_dbg(plane->dev,
|
||||||
|
"[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
|
||||||
new_plane_state->plane->base.id,
|
new_plane_state->plane->base.id,
|
||||||
bb_changed, fb_changed, num_clips);
|
bb_changed, fb_changed, num_clips);
|
||||||
|
|
||||||
if (num_clips || fb_changed || bb_changed) {
|
if (bb_changed) {
|
||||||
dirty_rects[i].x = new_plane_state->crtc_x;
|
fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
|
||||||
dirty_rects[i].y = new_plane_state->crtc_y;
|
new_plane_state->crtc_x,
|
||||||
dirty_rects[i].width = new_plane_state->crtc_w;
|
new_plane_state->crtc_y,
|
||||||
dirty_rects[i].height = new_plane_state->crtc_h;
|
new_plane_state->crtc_w,
|
||||||
DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
|
new_plane_state->crtc_h, &i, false);
|
||||||
new_plane_state->plane->base.id,
|
|
||||||
dirty_rects[i].x, dirty_rects[i].y,
|
|
||||||
dirty_rects[i].width, dirty_rects[i].height);
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add old plane bounding-box if plane is moved or resized */
|
/* Add old plane bounding-box if plane is moved or resized */
|
||||||
if (bb_changed) {
|
fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
|
||||||
dirty_rects[i].x = old_plane_state->crtc_x;
|
old_plane_state->crtc_x,
|
||||||
dirty_rects[i].y = old_plane_state->crtc_y;
|
old_plane_state->crtc_y,
|
||||||
dirty_rects[i].width = old_plane_state->crtc_w;
|
old_plane_state->crtc_w,
|
||||||
dirty_rects[i].height = old_plane_state->crtc_h;
|
old_plane_state->crtc_h, &i, false);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (num_clips) {
|
||||||
|
for (; i < num_clips; 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > DC_MAX_DIRTY_RECTS)
|
||||||
|
goto ffu;
|
||||||
|
|
||||||
flip_addrs->dirty_rect_count = i;
|
flip_addrs->dirty_rect_count = i;
|
||||||
|
return;
|
||||||
|
|
||||||
|
ffu:
|
||||||
|
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,
|
||||||
|
&flip_addrs->dirty_rect_count, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_stream_scaling_settings(const struct drm_display_mode *mode,
|
static void update_stream_scaling_settings(const struct drm_display_mode *mode,
|
||||||
|
|
|
@ -1600,6 +1600,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
|
||||||
drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
|
drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
|
||||||
supported_rotations);
|
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);
|
drm_plane_helper_add(plane, &dm_plane_helper_funcs);
|
||||||
|
|
||||||
#ifdef CONFIG_DRM_AMD_DC_HDR
|
#ifdef CONFIG_DRM_AMD_DC_HDR
|
||||||
|
|
Loading…
Add table
Reference in a new issue