Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c1659eb authored by Maarten Lankhorst's avatar Maarten Lankhorst
Browse files

drm/i915: Do not adjust scale when out of bounds, v2.



With the previous patch drm_atomic_helper_check_plane_state correctly
calculates clipping and the xf86-video-intel ddx is fixed to fall back
to GPU correctly when SetPlane fails, we can remove the hack where
we try to pan/zoom when out of min/max scaling range. This was already
poor behavior where the screen didn't show what was requested, and now
instead we reject it outright. This simplifies check_sprite_plane a lot.

Changes since v1:
- Set crtc_h to the height correctly.
- Reject < 3x3 rectangles instead of making them invisible for <gen9.
  For gen9+ skl_update_scaler_plane will reject them.

Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180503112217.37292-4-maarten.lankhorst@linux.intel.com


Acked-by: default avatarJani Nikula <jani.nikula@intel.com>
parent f96bdf56
Loading
Loading
Loading
Loading
+35 −109
Original line number Diff line number Diff line
@@ -935,21 +935,11 @@ intel_check_sprite_plane(struct intel_plane *plane,
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
	struct drm_framebuffer *fb = state->base.fb;
	int crtc_x, crtc_y;
	unsigned int crtc_w, crtc_h;
	uint32_t src_x, src_y, src_w, src_h;
	struct drm_rect *src = &state->base.src;
	struct drm_rect *dst = &state->base.dst;
	struct drm_rect clip = {};
	int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
	int hscale, vscale;
	int max_scale, min_scale;
	bool can_scale;
	int ret;

	*src = drm_plane_state_src(&state->base);
	*dst = drm_plane_state_dest(&state->base);

	if (!fb) {
		state->base.visible = false;
		return 0;
@@ -985,64 +975,19 @@ intel_check_sprite_plane(struct intel_plane *plane,
		min_scale = plane->can_scale ? 1 : (1 << 16);
	}

	/*
	 * FIXME the following code does a bunch of fuzzy adjustments to the
	 * coordinates and sizes. We probably need some way to decide whether
	 * more strict checking should be done instead.
	 */
	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
			state->base.rotation);

	hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
	BUG_ON(hscale < 0);

	vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
	BUG_ON(vscale < 0);

	if (crtc_state->base.enable)
		drm_mode_get_hv_timing(&crtc_state->base.mode,
				       &clip.x2, &clip.y2);

	state->base.visible = drm_rect_clip_scaled(src, dst, &clip);

	crtc_x = dst->x1;
	crtc_y = dst->y1;
	crtc_w = drm_rect_width(dst);
	crtc_h = drm_rect_height(dst);
	ret = drm_atomic_helper_check_plane_state(&state->base,
						  &crtc_state->base,
						  min_scale, max_scale,
						  true, true);
	if (ret)
		return ret;

	if (state->base.visible) {
		/* check again in case clipping clamped the results */
		hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
		if (hscale < 0) {
			DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
			drm_rect_debug_print("src: ", src, true);
			drm_rect_debug_print("dst: ", dst, false);

			return hscale;
		}

		vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
		if (vscale < 0) {
			DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
			drm_rect_debug_print("src: ", src, true);
			drm_rect_debug_print("dst: ", dst, false);

			return vscale;
		}

		/* 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));

		drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
				    state->base.rotation);

		/* sanity check to make sure the src viewport wasn't enlarged */
		WARN_ON(src->x1 < (int) state->base.src_x ||
			src->y1 < (int) state->base.src_y ||
			src->x2 > (int) state->base.src_x + state->base.src_w ||
			src->y2 > (int) state->base.src_y + state->base.src_h);
		struct drm_rect *src = &state->base.src;
		struct drm_rect *dst = &state->base.dst;
		unsigned int crtc_w = drm_rect_width(dst);
		unsigned int crtc_h = drm_rect_height(dst);
		uint32_t src_x, src_y, src_w, src_h;

		/*
		 * Hardware doesn't handle subpixel coordinates.
@@ -1055,58 +1000,39 @@ intel_check_sprite_plane(struct intel_plane *plane,
		src_y = src->y1 >> 16;
		src_h = drm_rect_height(src) >> 16;

		if (intel_format_is_yuv(fb->format->format)) {
			src_x &= ~1;
			src_w &= ~1;

			/*
			 * Must keep src and dst the
			 * same if we can't scale.
			 */
			if (!can_scale)
				crtc_w &= ~1;
		src->x1 = src_x << 16;
		src->x2 = (src_x + src_w) << 16;
		src->y1 = src_y << 16;
		src->y2 = (src_y + src_h) << 16;

			if (crtc_w == 0)
				state->base.visible = false;
		}
		if (intel_format_is_yuv(fb->format->format) &&
		    (src_x % 2 || src_w % 2)) {
			DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
				      src_x, src_w);
			return -EINVAL;
		}

		/* Check size restrictions when scaling */
	if (state->base.visible && (src_w != crtc_w || src_h != crtc_h)) {
		if (src_w != crtc_w || src_h != crtc_h) {
			unsigned int width_bytes;
			int cpp = fb->format->cpp[0];

			WARN_ON(!can_scale);

		/* FIXME interlacing min height is 6 */

		if (crtc_w < 3 || crtc_h < 3)
			state->base.visible = false;

		if (src_w < 3 || src_h < 3)
			state->base.visible = false;

			width_bytes = ((src_x * cpp) & 63) + src_w * cpp;

		if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
			/* FIXME interlacing min height is 6 */
			if (INTEL_GEN(dev_priv) < 9 && (
			     src_w < 3 || src_h < 3 ||
			     src_w > 2048 || src_h > 2048 ||
			     crtc_w < 3 || crtc_h < 3 ||
			     width_bytes > 4096 || fb->pitches[0] > 4096)) {
				DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
				return -EINVAL;
			}
		}

	if (state->base.visible) {
		src->x1 = src_x << 16;
		src->x2 = (src_x + src_w) << 16;
		src->y1 = src_y << 16;
		src->y2 = (src_y + src_h) << 16;
	}

	dst->x1 = crtc_x;
	dst->x2 = crtc_x + crtc_w;
	dst->y1 = crtc_y;
	dst->y2 = crtc_y + crtc_h;

	if (INTEL_GEN(dev_priv) >= 9) {
		ret = skl_check_plane_surface(crtc_state, state);
		if (ret)