[PATCH 1/2] drm/amd/display: Introduce overlay cursor mode

Harry Wentland harry.wentland at amd.com
Thu Mar 21 21:39:19 UTC 2024



On 2024-03-15 13:09, sunpeng.li at amd.com wrote:
> From: Leo Li <sunpeng.li at amd.com>
> 
> [Why]
> 
> DCN is the display hardware for amdgpu. DRM planes are backed by DCN
> hardware pipes, which carry pixel data from one end (memory), to the
> other (output encoder).
> 
> Each DCN pipe has the ability to blend in a cursor early on in the
> pipeline. In other words, there are no dedicated cursor planes in DCN,
> which makes cursor behavior somewhat unintuitive for compositors.
> 
> For example, if the cursor is in RGB format, but the top-most DRM plane
> is in YUV format, DCN will not be able to blend them. Because of this,
> amdgpu_dm rejects all configurations where a cursor needs to be enabled
> on top of a YUV formatted plane.
> 
> From a compositor's perspective, when computing an allocation for
> hardware plane offloading, this cursor-on-yuv configuration result in an
> atomic test failure. Since the failure reason is not obvious at all,
> compositors will likely fall back to full rendering, which is not ideal.
> 
> Instead, amdgpu_dm can try to accommodate the cursor-on-yuv
> configuration by opportunistically reserving a separate DCN pipe just
> for the cursor. We can refer to this as "overlay cursor mode". It is
> contrasted with "native cursor mode", where the native DCN per-pipe
> cursor is used.
> 
> [How]
> 
> On each crtc, compute whether the cursor plane should be enabled in
> overlay mode (which currently, is iff the immediate plane below has a
> YUV format). If it is, mark the CRTC as requesting overlay cursor mode.
> 
> During DC validation, attempt to enable a separate DCN pipe for the
> cursor if it's in overlay mode. If that fails, or if no overlay mode is
> requested, then fallback to native mode.
> 
> Signed-off-by: Leo Li <sunpeng.li at amd.com>

We should run this through our usual testing cycle, and I need to go over
it a bit more closely than I have, but I like it, so it's
Acked-by: Harry Wentland <harry.wentland at amd.com>

Harry

> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 309 +++++++++++++++---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   7 +
>  .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |   1 +
>  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  13 +-
>  4 files changed, 288 insertions(+), 42 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 21a61454c878..09ab330aed17 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -8359,8 +8359,19 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>  	 * Disable the cursor first if we're disabling all the planes.
>  	 * It'll remain on the screen after the planes are re-enabled
>  	 * if we don't.
> +	 *
> +	 * If the cursor is transitioning from native to overlay mode, the
> +	 * native cursor needs to be disabled first.
>  	 */
> -	if (acrtc_state->active_planes == 0)
> +	if (acrtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE &&
> +	    dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
> +		struct dc_cursor_position cursor_position = {0};
> +		dc_stream_set_cursor_position(acrtc_state->stream,
> +					      &cursor_position);
> +	}
> +
> +	if (acrtc_state->active_planes == 0 &&
> +	    dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
>  		amdgpu_dm_commit_cursors(state);
>  
>  	/* update planes when needed */
> @@ -8374,7 +8385,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>  		struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state);
>  
>  		/* Cursor plane is handled after stream updates */
> -		if (plane->type == DRM_PLANE_TYPE_CURSOR) {
> +		if (plane->type == DRM_PLANE_TYPE_CURSOR &&
> +		    acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
>  			if ((fb && crtc == pcrtc) ||
>  			    (old_plane_state->fb && old_plane_state->crtc == pcrtc))
>  				cursor_update = true;
> @@ -8727,7 +8739,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>  	 * This avoids redundant programming in the case where we're going
>  	 * to be disabling a single plane - those pipes are being disabled.
>  	 */
> -	if (acrtc_state->active_planes)
> +	if (acrtc_state->active_planes &&
> +	    acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
>  		amdgpu_dm_commit_cursors(state);
>  
>  cleanup:
> @@ -10039,7 +10052,8 @@ static bool should_reset_plane(struct drm_atomic_state *state,
>  {
>  	struct drm_plane *other;
>  	struct drm_plane_state *old_other_state, *new_other_state;
> -	struct drm_crtc_state *new_crtc_state;
> +	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
> +	struct dm_crtc_state *old_dm_crtc_state, *new_dm_crtc_state;
>  	struct amdgpu_device *adev = drm_to_adev(plane->dev);
>  	int i;
>  
> @@ -10061,10 +10075,24 @@ static bool should_reset_plane(struct drm_atomic_state *state,
>  
>  	new_crtc_state =
>  		drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
> +	old_crtc_state =
> +		drm_atomic_get_old_crtc_state(state, old_plane_state->crtc);
>  
>  	if (!new_crtc_state)
>  		return true;
>  
> +	/*
> +	 * A change in cursor mode means a new dc pipe needs to be acquired or
> +	 * released from the state
> +	 */
> +	old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
> +	new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
> +	if (plane->type == DRM_PLANE_TYPE_CURSOR &&
> +	    old_dm_crtc_state != NULL &&
> +	    old_dm_crtc_state->cursor_mode != new_dm_crtc_state->cursor_mode) {
> +		return true;
> +	}
> +
>  	/* CRTC Degamma changes currently require us to recreate planes. */
>  	if (new_crtc_state->color_mgmt_changed)
>  		return true;
> @@ -10216,6 +10244,68 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
>  	return 0;
>  }
>  
> +/*
> + * Helper function for checking the cursor in native mode
> + */
> +static int dm_check_native_cursor_state(struct drm_crtc *new_plane_crtc,
> +					struct drm_plane *plane,
> +					struct drm_plane_state *new_plane_state,
> +					bool enable)
> +{
> +
> +	struct amdgpu_crtc *new_acrtc;
> +	int ret;
> +
> +	if (!enable || !new_plane_crtc ||
> +	    drm_atomic_plane_disabling(plane->state, new_plane_state))
> +		return 0;
> +
> +	new_acrtc = to_amdgpu_crtc(new_plane_crtc);
> +
> +	if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
> +		DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
> +		return -EINVAL;
> +	}
> +
> +	if (new_plane_state->fb) {
> +		ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
> +						new_plane_state->fb);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static bool dm_should_update_native_cursor(struct drm_atomic_state *state,
> +					   struct drm_crtc *old_plane_crtc,
> +					   struct drm_crtc *new_plane_crtc,
> +					   bool enable)
> +{
> +	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
> +	struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
> +
> +	if (!enable) {
> +		if (old_plane_crtc == NULL)
> +			return true;
> +
> +		old_crtc_state = drm_atomic_get_old_crtc_state(
> +			state, old_plane_crtc);
> +		dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
> +
> +		return dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
> +	} else {
> +		if (new_plane_crtc == NULL)
> +			return true;
> +
> +		new_crtc_state = drm_atomic_get_new_crtc_state(
> +			state, new_plane_crtc);
> +		dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
> +
> +		return dm_new_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
> +	}
> +}
> +
>  static int dm_update_plane_state(struct dc *dc,
>  				 struct drm_atomic_state *state,
>  				 struct drm_plane *plane,
> @@ -10231,8 +10321,7 @@ static int dm_update_plane_state(struct dc *dc,
>  	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>  	struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
>  	struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
> -	struct amdgpu_crtc *new_acrtc;
> -	bool needs_reset;
> +	bool needs_reset, update_native_cursor;
>  	int ret = 0;
>  
>  
> @@ -10241,24 +10330,16 @@ static int dm_update_plane_state(struct dc *dc,
>  	dm_new_plane_state = to_dm_plane_state(new_plane_state);
>  	dm_old_plane_state = to_dm_plane_state(old_plane_state);
>  
> -	if (plane->type == DRM_PLANE_TYPE_CURSOR) {
> -		if (!enable || !new_plane_crtc ||
> -			drm_atomic_plane_disabling(plane->state, new_plane_state))
> -			return 0;
> -
> -		new_acrtc = to_amdgpu_crtc(new_plane_crtc);
> -
> -		if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
> -			DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
> -			return -EINVAL;
> -		}
> +	update_native_cursor = dm_should_update_native_cursor(state,
> +							      old_plane_crtc,
> +							      new_plane_crtc,
> +							      enable);
>  
> -		if (new_plane_state->fb) {
> -			ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
> -						 new_plane_state->fb);
> -			if (ret)
> -				return ret;
> -		}
> +	if (plane->type == DRM_PLANE_TYPE_CURSOR && update_native_cursor) {
> +		ret = dm_check_native_cursor_state(new_plane_crtc, plane,
> +					            new_plane_state, enable);
> +		if (ret)
> +			return ret;
>  
>  		return 0;
>  	}
> @@ -10285,16 +10366,17 @@ static int dm_update_plane_state(struct dc *dc,
>  				plane->base.id, old_plane_crtc->base.id);
>  
>  		ret = dm_atomic_get_state(state, &dm_state);
> -		if (ret)
> -			return ret;
> +		if (ret) {
> +			goto out;
> +		}
>  
>  		if (!dc_state_remove_plane(
>  				dc,
>  				dm_old_crtc_state->stream,
>  				dm_old_plane_state->dc_state,
>  				dm_state->context)) {
> -
> -			return -EINVAL;
> +			ret = -EINVAL;
> +			goto out;
>  		}
>  
>  		if (dm_old_plane_state->dc_state)
> @@ -10323,21 +10405,16 @@ static int dm_update_plane_state(struct dc *dc,
>  			return 0;
>  
>  		ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state);
> -		if (ret)
> -			return ret;
> +		if (ret) {
> +			goto out;
> +		}
>  
>  		WARN_ON(dm_new_plane_state->dc_state);
>  
>  		dc_new_plane_state = dc_create_plane_state(dc);
> -		if (!dc_new_plane_state)
> -			return -ENOMEM;
> -
> -		/* Block top most plane from being a video plane */
> -		if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
> -			if (amdgpu_dm_plane_is_video_format(new_plane_state->fb->format->format) && *is_top_most_overlay)
> -				return -EINVAL;
> -
> -			*is_top_most_overlay = false;
> +		if (!dc_new_plane_state) {
> +			ret = -ENOMEM;
> +			goto out;
>  		}
>  
>  		DRM_DEBUG_ATOMIC("Enabling DRM plane: %d on DRM crtc %d\n",
> @@ -10350,13 +10427,13 @@ static int dm_update_plane_state(struct dc *dc,
>  			new_crtc_state);
>  		if (ret) {
>  			dc_plane_state_release(dc_new_plane_state);
> -			return ret;
> +			goto out;
>  		}
>  
>  		ret = dm_atomic_get_state(state, &dm_state);
>  		if (ret) {
>  			dc_plane_state_release(dc_new_plane_state);
> -			return ret;
> +			goto out;
>  		}
>  
>  		/*
> @@ -10373,7 +10450,8 @@ static int dm_update_plane_state(struct dc *dc,
>  				dm_state->context)) {
>  
>  			dc_plane_state_release(dc_new_plane_state);
> -			return -EINVAL;
> +			ret = -EINVAL;
> +			goto out;
>  		}
>  
>  		dm_new_plane_state->dc_state = dc_new_plane_state;
> @@ -10388,6 +10466,16 @@ static int dm_update_plane_state(struct dc *dc,
>  		*lock_and_validation_needed = true;
>  	}
>  
> +out:
> +	/* If cursor overlay failed, attempt fallback to native mode */
> +	if (ret == -EINVAL && plane->type == DRM_PLANE_TYPE_CURSOR) {
> +		ret = dm_check_native_cursor_state(new_plane_crtc, plane,
> +						    new_plane_state, enable);
> +		if (ret) {
> +			return ret;
> +		}
> +		dm_new_crtc_state->cursor_mode = DM_CURSOR_NATIVE_MODE;
> +	}
>  
>  	return ret;
>  }
> @@ -10544,6 +10632,126 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
>  	return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_root->mst_mgr);
>  }
>  
> +/**
> + * DOC: Cursor Modes - Native vs Overlay
> + *
> + * In native mode, the cursor uses a integrated cursor pipe within each DCN hw
> + * plane. It does not require a dedicated hw plane to enable, but it is
> + * subjected to the same z-order and scaling as the hw plane. It also has format
> + * restrictions, a RGB cursor in native mode cannot be enabled within a non-RGB
> + * hw plane.
> + *
> + * In overlay mode, the cursor uses a separate DCN hw plane, and thus has its
> + * own scaling and z-pos. It also has no blending restrictions. It lends to a
> + * cursor behavior more akin to a DRM client's expectations. However, it does
> + * occupy an extra DCN plane, and therefore will only be used if a DCN plane is
> + * available.
> +*/
> +
> +/**
> + * Set whether the cursor should be enabled in native mode, or overlay mode, on
> + * the dm_crtc_state.
> + *
> + * The cursor should be enabled in overlay mode if the immediate underlying
> + * plane contains a video format.
> + *
> + * Since zpos info is required, drm_atomic_normalize_zpos must be called before
> + * calling this function.
> +*/
> +static int dm_crtc_set_cursor_mode(struct drm_atomic_state *state,
> +				    struct dm_crtc_state *dm_crtc_state)
> +{
> +	struct drm_plane_state *plane_state, *old_plane_state, *target_plane_state;
> +	struct drm_crtc_state *crtc_state = &dm_crtc_state->base;
> +	struct drm_plane *plane;
> +	bool consider_mode_change = false;
> +	bool cursor_changed = false;
> +	unsigned int target_zpos;
> +	unsigned int cursor_zpos;
> +	int i;
> +
> +	/*
> +	 * Cursor mode can change if a plane's format changes, is
> +	 * enabled/disabled, or z-order changes.
> +	 */
> +	for_each_oldnew_plane_in_state(state, plane, old_plane_state, plane_state, i) {
> +
> +		/* Only care about planes on this CRTC */
> +		if ((drm_plane_mask(plane) & crtc_state->plane_mask) == 0)
> +			continue;
> +
> +		if (plane->type == DRM_PLANE_TYPE_CURSOR)
> +			cursor_changed = true;
> +
> +		if (drm_atomic_plane_enabling(old_plane_state, plane_state) ||
> +		    drm_atomic_plane_disabling(old_plane_state, plane_state) ||
> +		    old_plane_state->fb->format != plane_state->fb->format) {
> +			consider_mode_change = true;
> +			break;
> +		}
> +	}
> +
> +	if (!consider_mode_change && !crtc_state->zpos_changed) {
> +		return 0;
> +	}
> +
> +	/*
> +	 * If no cursor change on this CRTC, and not enabled on this CRTC, then
> +	 * no need to set cursor mode. This avoids needlessly locking the cursor
> +	 * state.
> +	 */
> +	if (!cursor_changed &&
> +	    !(drm_plane_mask(crtc_state->crtc->cursor) & crtc_state->plane_mask)) {
> +		return 0;
> +	}
> +
> +	plane_state = drm_atomic_get_plane_state(state,
> +						 crtc_state->crtc->cursor);
> +	if (IS_ERR(plane_state))
> +		return PTR_ERR(plane_state);
> +
> +	/* Cursor is disabled */
> +	if (!plane_state->fb)
> +		return 0;
> +
> +	cursor_zpos = plane_state->normalized_zpos;
> +
> +	/* Get enabled plane immediately below cursor. */
> +	target_plane_state = NULL;
> +	target_zpos = 0;
> +	drm_for_each_plane_mask(plane, state->dev, crtc_state->plane_mask) {
> +		if (plane->type == DRM_PLANE_TYPE_CURSOR)
> +			continue;
> +
> +		plane_state = drm_atomic_get_plane_state(state, plane);
> +		if (IS_ERR(plane_state))
> +			return PTR_ERR(plane_state);
> +
> +		if (!plane_state->fb ||
> +		    plane_state->normalized_zpos >= cursor_zpos)
> +			continue;
> +
> +		if (plane_state->normalized_zpos >= target_zpos) {
> +			target_zpos = plane_state->normalized_zpos;
> +			target_plane_state = plane_state;
> +		}
> +	}
> +
> +	/* Nothing below cursor - use overlay mode */
> +	if (target_plane_state == NULL) {
> +		dm_crtc_state->cursor_mode = DM_CURSOR_OVERLAY_MODE;
> +		return 0;
> +	}
> +
> +	if (amdgpu_dm_plane_is_video_format(target_plane_state->fb->format->format)) {
> +		dm_crtc_state->cursor_mode = DM_CURSOR_OVERLAY_MODE;
> +	} else {
> +		dm_crtc_state->cursor_mode = DM_CURSOR_NATIVE_MODE;
> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
>   *
> @@ -10713,6 +10921,20 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>  		goto fail;
>  	}
>  
> +	/*
> +	 * Determine whether cursors on each CRTC should be enabled in native or
> +	 * overlay mode.
> +	 */
> +	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> +		dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
> +
> +		ret = dm_crtc_set_cursor_mode(state, dm_new_crtc_state);
> +		if (ret) {
> +			drm_dbg(dev, "Failed to determine cursor mode\n");
> +			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) {
>  		if (old_plane_state->fb && new_plane_state->fb &&
> @@ -10793,6 +11015,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
>  
>  	/* Check cursor planes scaling */
>  	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> +		/* Overlay cusor does not need scaling check */
> +		dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
> +		if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
> +			continue;
> +
>  		ret = dm_check_crtc_cursor(state, crtc, new_crtc_state);
>  		if (ret) {
>  			DRM_DEBUG_DRIVER("dm_check_crtc_cursor() failed\n");
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> index 09519b7abf67..b8d39fdd1e09 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
> @@ -822,6 +822,11 @@ struct dm_plane_state {
>  	enum amdgpu_transfer_function blend_tf;
>  };
>  
> +enum amdgpu_dm_cursor_mode {
> +	DM_CURSOR_NATIVE_MODE = 0,
> +	DM_CURSOR_OVERLAY_MODE,
> +};
> +
>  struct dm_crtc_state {
>  	struct drm_crtc_state base;
>  	struct dc_stream_state *stream;
> @@ -852,6 +857,8 @@ struct dm_crtc_state {
>  	 * encoding.
>  	 */
>  	enum amdgpu_transfer_function regamma_tf;
> +
> +	enum amdgpu_dm_cursor_mode cursor_mode;
>  };
>  
>  #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> index e23a0a276e33..67aea1d2feb9 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> @@ -304,6 +304,7 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
>  	state->regamma_tf = cur->regamma_tf;
>  	state->crc_skip_count = cur->crc_skip_count;
>  	state->mpo_requested = cur->mpo_requested;
> +	state->cursor_mode = cur->cursor_mode;
>  	/* TODO Duplicate dc_stream after objects are stream object is flattened */
>  
>  	return &state->base;
> 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 8a4c40b4c27e..ed1fc01f1649 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
> @@ -104,7 +104,7 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state
>  	*global_alpha = false;
>  	*global_alpha_value = 0xff;
>  
> -	if (plane_state->plane->type != DRM_PLANE_TYPE_OVERLAY)
> +	if (plane_state->plane->type == DRM_PLANE_TYPE_PRIMARY)
>  		return;
>  
>  	if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
> @@ -1175,10 +1175,21 @@ static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
>  static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
>  					      struct drm_atomic_state *state)
>  {
> +	struct drm_crtc_state *new_crtc_state;
> +	struct drm_plane_state *new_plane_state;
> +	struct dm_crtc_state *dm_new_crtc_state;
> +
>  	/* Only support async updates on cursor planes. */
>  	if (plane->type != DRM_PLANE_TYPE_CURSOR)
>  		return -EINVAL;
>  
> +	new_plane_state = drm_atomic_get_new_plane_state(state, plane);
> +	new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
> +	dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
> +	/* Reject overlay cursors for now*/
> +	if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
> +		return -EINVAL;
> +
>  	return 0;
>  }
>  



More information about the amd-gfx mailing list