[Intel-gfx] [PATCH] drm: Check fb against plane size rather than CRTC mode for pageflip

Ville Syrjälä ville.syrjala at linux.intel.com
Wed Oct 7 05:02:53 PDT 2015


On Tue, Oct 06, 2015 at 05:02:47PM -0700, Matt Roper wrote:
> The legacy pageflip ioctl calls drm_crtc_check_viewport() to determine
> whether the framebuffer being flipped is big enough to fill the display
> it is being flipped to.  However some drivers support "windowing" of
> their primary planes (i.e., a primary plane that does not cover the
> entire CRTC dimensions); in such situations we can wind up rejecting
> valid pageflips of buffers that are smaller than the display mode, but
> still large enough to fill the entire primary plane.
> 
> What we really want to be comparing against for pageflips is the size of
> the primary plane, which can be found in crtc->primary->state for atomic
> drivers (and drivers in the process of transitioning to atomic).  There
> are no non-atomic drivers that support primary plane windowing at the
> moment, so we'll continue to use the current behavior of looking at the
> CRTC mode size on drivers that don't have a crtc->primary->state.  We'll
> also continue to use the existing logic for SetCrtc, which is the other
> callsite for drm_crtc_check_viewport(), since legacy modesets reprogram
> the primary plane and remove windowing.
> 
> Note that the existing code was checking a crtc->invert_dimensions field
> to determine whether the width/height of the mode needed to be swapped.
> A bonus of checking plane size is that the source width/height we get
> already take rotation into account so that check is no longer necessary
> when using the plane size.
> 
> Testcase: igt/universal-plane-gen9-features-pipe-#
> Reported-by: Tvrtko Ursulin <tvrtko.ursulin at linux.intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin at linux.intel.com>
> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
> ---
>  drivers/gpu/drm/drm_crtc.c | 87 +++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 71 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index e600a5f..35cd4dc 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -2534,9 +2534,76 @@ void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
>  }
>  EXPORT_SYMBOL(drm_crtc_get_hv_timing);
>  
> +static int check_viewport(int hdisplay,
> +			  int vdisplay,
> +			  int x,
> +			  int y,
> +			  bool invert_dimensions,
> +			  const struct drm_framebuffer *fb)
> +{
> +	if (invert_dimensions)
> +		swap(hdisplay, vdisplay);
> +
> +	if (hdisplay > fb->width ||
> +	    vdisplay > fb->height ||
> +	    x > fb->width - hdisplay ||
> +	    y > fb->height - vdisplay) {
> +		DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
> +			      fb->width, fb->height, hdisplay, vdisplay, x, y,
> +			      invert_dimensions ? " (inverted)" : "");
> +		return -ENOSPC;
> +	}
> +
> +	return 0;
> +}

I think I'd rather pull the limit check code from the setplane path to a
separate function, and call that with the src coordinates derived from
either the plane state or the mode depending on the use case. That way
the invert_dimensions crap can stay only in the codepath that actually
needs it.

> +
> +/**
> + * drm_plane_check_viewport - Checks that a framebuffer is big enough for the
> + *     plane's viewport
> + * @plane: Plane that framebuffer will be displayed on
> + * @x: x panning
> + * @y: y panning
> + * @fb: framebuffer to check size of
> + *
> + * Atomic drivers (or transitioning drivers that support proper plane state)
> + * may call this function on any plane.  Non-atomic drivers may only call this
> + * for the primary plane while the CRTC is active (we'll assume that the
> + * primary plane covers the entire CRTC in that case).
> + */
> +int drm_plane_check_viewport(const struct drm_plane *plane,
> +			     int x,
> +			     int y,
> +			     const struct drm_framebuffer *fb)
> +
> +{
> +	struct drm_crtc *crtc = plane->crtc;
> +	int hdisplay, vdisplay;
> +
> +	if (WARN_ON(plane->state == NULL &&
> +		    plane->type != DRM_PLANE_TYPE_PRIMARY))
> +		return -EINVAL;
> +
> +	/*
> +	 * Non-atomic drivers may not have valid plane state to look at.  But
> +	 * those drivers also don't support windowing of the primary plane, so
> +	 * we can fall back to looking at the mode of the owning CRTC.
> +	 */
> +	if (plane->state) {
> +		hdisplay = plane->state->src_w >> 16;
> +		vdisplay = plane->state->src_h >> 16;

You shouldn't truncate these.

> +	} else if (WARN_ON(!crtc)) {
> +		hdisplay = vdisplay = 0;
> +	} else {
> +		drm_crtc_get_hv_timing(&crtc->mode, &hdisplay, &vdisplay);
> +	}
> +
> +	return check_viewport(hdisplay, vdisplay, x, y, false, fb);
> +}
> +EXPORT_SYMBOL(drm_plane_check_viewport);
> +
>  /**
>   * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
> - *     CRTC viewport
> + *     CRTC viewport when running in the specified mode
>   * @crtc: CRTC that framebuffer will be displayed on
>   * @x: x panning
>   * @y: y panning
> @@ -2553,20 +2620,8 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc,
>  
>  	drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
>  
> -	if (crtc->invert_dimensions)
> -		swap(hdisplay, vdisplay);
> -
> -	if (hdisplay > fb->width ||
> -	    vdisplay > fb->height ||
> -	    x > fb->width - hdisplay ||
> -	    y > fb->height - vdisplay) {
> -		DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
> -			      fb->width, fb->height, hdisplay, vdisplay, x, y,
> -			      crtc->invert_dimensions ? " (inverted)" : "");
> -		return -ENOSPC;
> -	}
> -
> -	return 0;
> +	return check_viewport(hdisplay, vdisplay, x, y,
> +			      crtc->invert_dimensions, fb);
>  }
>  EXPORT_SYMBOL(drm_crtc_check_viewport);
>  
> @@ -5181,7 +5236,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
>  		goto out;
>  	}
>  
> -	ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
> +	ret = drm_plane_check_viewport(crtc->primary, crtc->x, crtc->y, fb);
>  	if (ret)
>  		goto out;
>  
> -- 
> 2.1.4

-- 
Ville Syrjälä
Intel OTC


More information about the Intel-gfx mailing list