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

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.comAcked-by: default avatarJani Nikula <jani.nikula@intel.com>
parent f96bdf56
...@@ -935,21 +935,11 @@ intel_check_sprite_plane(struct intel_plane *plane, ...@@ -935,21 +935,11 @@ intel_check_sprite_plane(struct intel_plane *plane,
struct drm_i915_private *dev_priv = to_i915(plane->base.dev); struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
struct drm_framebuffer *fb = state->base.fb; 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 max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
int hscale, vscale;
int max_scale, min_scale; int max_scale, min_scale;
bool can_scale; bool can_scale;
int ret; int ret;
*src = drm_plane_state_src(&state->base);
*dst = drm_plane_state_dest(&state->base);
if (!fb) { if (!fb) {
state->base.visible = false; state->base.visible = false;
return 0; return 0;
...@@ -985,64 +975,19 @@ intel_check_sprite_plane(struct intel_plane *plane, ...@@ -985,64 +975,19 @@ intel_check_sprite_plane(struct intel_plane *plane,
min_scale = plane->can_scale ? 1 : (1 << 16); min_scale = plane->can_scale ? 1 : (1 << 16);
} }
/* ret = drm_atomic_helper_check_plane_state(&state->base,
* FIXME the following code does a bunch of fuzzy adjustments to the &crtc_state->base,
* coordinates and sizes. We probably need some way to decide whether min_scale, max_scale,
* more strict checking should be done instead. true, true);
*/ if (ret)
drm_rect_rotate(src, fb->width << 16, fb->height << 16, return ret;
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);
if (state->base.visible) { if (state->base.visible) {
/* check again in case clipping clamped the results */ struct drm_rect *src = &state->base.src;
hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); struct drm_rect *dst = &state->base.dst;
if (hscale < 0) { unsigned int crtc_w = drm_rect_width(dst);
DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); unsigned int crtc_h = drm_rect_height(dst);
drm_rect_debug_print("src: ", src, true); uint32_t src_x, src_y, src_w, src_h;
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);
/* /*
* Hardware doesn't handle subpixel coordinates. * Hardware doesn't handle subpixel coordinates.
...@@ -1055,58 +1000,39 @@ intel_check_sprite_plane(struct intel_plane *plane, ...@@ -1055,58 +1000,39 @@ intel_check_sprite_plane(struct intel_plane *plane,
src_y = src->y1 >> 16; src_y = src->y1 >> 16;
src_h = drm_rect_height(src) >> 16; src_h = drm_rect_height(src) >> 16;
if (intel_format_is_yuv(fb->format->format)) { src->x1 = src_x << 16;
src_x &= ~1; src->x2 = (src_x + src_w) << 16;
src_w &= ~1; src->y1 = src_y << 16;
src->y2 = (src_y + src_h) << 16;
/*
* Must keep src and dst the
* same if we can't scale.
*/
if (!can_scale)
crtc_w &= ~1;
if (crtc_w == 0) if (intel_format_is_yuv(fb->format->format) &&
state->base.visible = false; (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 */ /* 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; unsigned int width_bytes;
int cpp = fb->format->cpp[0]; int cpp = fb->format->cpp[0];
WARN_ON(!can_scale); WARN_ON(!can_scale);
/* FIXME interlacing min height is 6 */ width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
if (crtc_w < 3 || crtc_h < 3) /* FIXME interlacing min height is 6 */
state->base.visible = false; if (INTEL_GEN(dev_priv) < 9 && (
src_w < 3 || src_h < 3 ||
if (src_w < 3 || src_h < 3) src_w > 2048 || src_h > 2048 ||
state->base.visible = false; crtc_w < 3 || crtc_h < 3 ||
width_bytes > 4096 || fb->pitches[0] > 4096)) {
width_bytes = ((src_x * cpp) & 63) + src_w * cpp; DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
return -EINVAL;
if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 || }
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) { if (INTEL_GEN(dev_priv) >= 9) {
ret = skl_check_plane_surface(crtc_state, state); ret = skl_check_plane_surface(crtc_state, state);
if (ret) if (ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment