[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