[PATCH v1 5/6] drm/i915: Do not do fb src adjustments for NV12

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Wed Apr 11 10:38:29 UTC 2018


Op 11-04-18 om 11:09 schreef Vidya Srinivas:
> We skip src trunction/adjustments for
> NV12 case and handle the sizes directly.
> Without this, pipe fifo underruns are seen on APL/KBL.
>
> Credits-to: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Signed-off-by: Vidya Srinivas <vidya.srinivas at intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 88 ++++++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_sprite.c  | 10 +++-
>  2 files changed, 92 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ebb3f8e..e4cf7a6 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12951,6 +12951,86 @@ skl_max_scale(struct intel_crtc *intel_crtc,
>  }
>  
>  static int
> +intel_primary_plane_state(struct drm_plane_state *plane_state,
> +			  const struct drm_crtc_state *crtc_state,
> +			  int min_scale, int max_scale,
> +			  bool can_position, bool can_update_disabled)
> +{
> +	struct drm_framebuffer *fb = plane_state->fb;
> +	struct drm_rect *src = &plane_state->src;
> +	struct drm_rect *dst = &plane_state->dst;
> +	unsigned int rotation = plane_state->rotation;
> +	struct drm_rect clip = {};
> +	int hscale, vscale;
> +
> +	WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
> +
> +	*src = drm_plane_state_src(plane_state);
> +	*dst = drm_plane_state_dest(plane_state);
> +
> +	if (!fb) {
> +		plane_state->visible = false;
> +		return 0;
> +	}
> +
> +	/* crtc should only be NULL when disabling (i.e., !fb) */
> +	if (WARN_ON(!plane_state->crtc)) {
> +		plane_state->visible = false;
> +		return 0;
> +	}
> +
> +	if (!crtc_state->enable && !can_update_disabled) {
> +		DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
> +		return -EINVAL;
> +	}
> +
> +	drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
> +
> +	/* Check scaling */
> +	hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
> +	vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
> +	if (hscale < 0 || vscale < 0) {
> +		DRM_DEBUG_KMS("Invalid scaling of plane\n");
> +		drm_rect_debug_print("src: ", &plane_state->src, true);
> +		drm_rect_debug_print("dst: ", &plane_state->dst, false);
> +		return -ERANGE;
> +	}
> +
> +	if (crtc_state->enable)
> +		drm_mode_get_hv_timing(&crtc_state->mode, &clip.x2, &clip.y2);
> +
> +	if (fb->format->format == DRM_FORMAT_NV12) {
> +		plane_state->visible = true;
> +		goto skip_clip;
> +	}
> +
> +	plane_state->visible =
> +		drm_rect_clip_scaled(src, dst, &clip, hscale, vscale);
The real problem is that it needs to be a multiple of 4. I think the clipping here is harmless, we should just adjust intel_check_sprite_plane for >= SKL.
This will make it so we don't have to duplicate its checks.

For NV12 we still want to call clip_rect_scaled, but then adjust all coordinates by dividing by 4 on before the check, and multiplying with 4 after?

~Maarten

> +skip_clip:
> +	drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
> +
> +	if (!plane_state->visible)
> +		/*
> +		 * Plane isn't visible; some drivers can handle this
> +		 * so we just return success here.  Drivers that can't
> +		 * (including those that use the primary plane helper's
> +		 * update function) will return an error from their
> +		 * update_plane handler.
> +		 */
> +		return 0;
> +
> +	if (!can_position && !drm_rect_equals(dst, &clip)) {
> +		DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
> +		drm_rect_debug_print("dst: ", dst, false);
> +		drm_rect_debug_print("clip: ", &clip, false);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
>  intel_check_primary_plane(struct intel_plane *plane,
>  			  struct intel_crtc_state *crtc_state,
>  			  struct intel_plane_state *state)
> @@ -12975,10 +13055,10 @@ intel_check_primary_plane(struct intel_plane *plane,
>  		can_position = true;
>  	}
>  
> -	ret = drm_atomic_helper_check_plane_state(&state->base,
> -						  &crtc_state->base,
> -						  min_scale, max_scale,
> -						  can_position, true);
> +	ret = intel_primary_plane_state(&state->base,
> +					&crtc_state->base,
> +					min_scale, max_scale,
> +					can_position, true);

>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index d5dad44..1e47b97 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -1035,11 +1035,14 @@ intel_check_sprite_plane(struct intel_plane *plane,
>  			return vscale;
>  		}
>  
> +		if (state->base.fb && fb->format->format == DRM_FORMAT_NV12)
> +			goto skip_adjust;
> +
>  		/* Make the source viewport size an exact multiple of the scaling factors. */
>  		drm_rect_adjust_size(src,
>  				     drm_rect_width(dst) * hscale - drm_rect_width(src),
>  				     drm_rect_height(dst) * vscale - drm_rect_height(src));
> -
> +skip_adjust:
>  		drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
>  				    state->base.rotation);
>  
> @@ -1100,6 +1103,9 @@ intel_check_sprite_plane(struct intel_plane *plane,
>  		}
>  	}
>  
> +	if (state->base.fb && fb->format->format == DRM_FORMAT_NV12)
> +		goto out;
> +
>  	if (state->base.visible) {
>  		src->x1 = src_x << 16;
>  		src->x2 = (src_x + src_w) << 16;
> @@ -1111,7 +1117,7 @@ intel_check_sprite_plane(struct intel_plane *plane,
>  	dst->x2 = crtc_x + crtc_w;
>  	dst->y1 = crtc_y;
>  	dst->y2 = crtc_y + crtc_h;
> -
> +out:
>  	if (INTEL_GEN(dev_priv) >= 9) {
>  		ret = skl_check_plane_surface(crtc_state, state);
>  		if (ret)




More information about the Intel-gfx-trybot mailing list