Message ID | 20180525192740.41927-1-frkoenig@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, May 25, 2018 at 12:27:40PM -0700, Fritz Koenig wrote: > YUV planes need to be multiples of 2 to scan out. This was > handled correctly for planes other than the primary in the > intel_check_sprite_plane, where the code fixes up the plane > and makes it compliant. Move this code into a location that > allows the primary check to access it as well. intel_check_sprite_plane() is not something we should be spreading. It's doing way too many platform specific things. I think where I want to go instead is per-platform plane .check() functions instead. To that end I think you should just add the relevant checks to eg. skl_check_plane_surface() for now. We especially don't want to be moving large chunks of code from intel_sprite.c to intel_display.c. I'm actually trying to do the exact opposite and move all the plane code into intel_sprite.c (or maybe even introduce a new file for the skl+ plane code entirely). > Signed-off-by: Fritz Koenig <frkoenig@google.com> > --- > drivers/gpu/drm/i915/intel_display.c | 170 +++++++++++++++++++++++++++ > drivers/gpu/drm/i915/intel_drv.h | 2 + > drivers/gpu/drm/i915/intel_sprite.c | 154 +----------------------- > 3 files changed, 175 insertions(+), 151 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 5f03af455047..e1eb0fb988a6 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -12856,6 +12856,170 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state > return max_scale; > } > > +int > +intel_clip_src_rect(struct intel_plane *plane, > + struct intel_crtc_state *crtc_state, > + struct intel_plane_state *state) > +{ > + 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 hscale, vscale; > + int max_scale, min_scale; > + bool can_scale; > + > + *src = drm_plane_state_src(&state->base); > + *dst = drm_plane_state_dest(&state->base); > + > + /* setup can_scale, min_scale, max_scale */ > + if (INTEL_GEN(dev_priv) >= 9) { > + /* use scaler when colorkey is not required */ > + if (!state->ckey.flags) { > + can_scale = 1; > + min_scale = 1; > + max_scale = skl_max_scale(crtc, crtc_state); > + } else { > + can_scale = 0; > + min_scale = DRM_PLANE_HELPER_NO_SCALING; > + max_scale = DRM_PLANE_HELPER_NO_SCALING; > + } > + } else { > + can_scale = plane->can_scale; > + max_scale = plane->max_downscale << 16; > + 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, hscale, vscale); > + > + crtc_x = dst->x1; > + crtc_y = dst->y1; > + crtc_w = drm_rect_width(dst); > + crtc_h = drm_rect_height(dst); > + > + 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); > + > + /* > + * Hardware doesn't handle subpixel coordinates. > + * Adjust to (macro)pixel boundary, but be careful not to > + * increase the source viewport size, because that could > + * push the downscaling factor out of bounds. > + */ > + src_x = src->x1 >> 16; > + src_w = drm_rect_width(src) >> 16; > + 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; > + > + if (crtc_w == 0) > + state->base.visible = false; > + } > + } > + > + /* Check size restrictions when scaling */ > + if (state->base.visible && (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 || > + 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; > + > + return 0; > +} > + > static int > intel_check_primary_plane(struct intel_plane *plane, > struct intel_crtc_state *crtc_state, > @@ -12887,6 +13051,12 @@ intel_check_primary_plane(struct intel_plane *plane, > if (!state->base.fb) > return 0; > > + if (intel_format_is_yuv(state->base.fb->format->format)) { > + ret = intel_clip_src_rect(plane, crtc_state, state); > + if (ret) > + return ret; > + } > + > if (INTEL_GEN(dev_priv) >= 9) { > ret = skl_check_plane_surface(crtc_state, state); > if (ret) > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index a80fbad9be0f..43847927a927 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -1591,6 +1591,8 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, > > int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); > int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); > +int intel_clip_src_rect(struct intel_plane *plane, > + struct intel_crtc_state *crtc_state, struct intel_plane_state *state); > > static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state) > { > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c > index dbdcf85032df..892d3247ed69 100644 > --- a/drivers/gpu/drm/i915/intel_sprite.c > +++ b/drivers/gpu/drm/i915/intel_sprite.c > @@ -935,21 +935,9 @@ 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; > @@ -967,145 +955,9 @@ intel_check_sprite_plane(struct intel_plane *plane, > return -EINVAL; > } > > - /* setup can_scale, min_scale, max_scale */ > - if (INTEL_GEN(dev_priv) >= 9) { > - /* use scaler when colorkey is not required */ > - if (!state->ckey.flags) { > - can_scale = 1; > - min_scale = 1; > - max_scale = skl_max_scale(crtc, crtc_state); > - } else { > - can_scale = 0; > - min_scale = DRM_PLANE_HELPER_NO_SCALING; > - max_scale = DRM_PLANE_HELPER_NO_SCALING; > - } > - } else { > - can_scale = plane->can_scale; > - max_scale = plane->max_downscale << 16; > - 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, hscale, vscale); > - > - crtc_x = dst->x1; > - crtc_y = dst->y1; > - crtc_w = drm_rect_width(dst); > - crtc_h = drm_rect_height(dst); > - > - 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); > - > - /* > - * Hardware doesn't handle subpixel coordinates. > - * Adjust to (macro)pixel boundary, but be careful not to > - * increase the source viewport size, because that could > - * push the downscaling factor out of bounds. > - */ > - src_x = src->x1 >> 16; > - src_w = drm_rect_width(src) >> 16; > - 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; > - > - if (crtc_w == 0) > - state->base.visible = false; > - } > - } > - > - /* Check size restrictions when scaling */ > - if (state->base.visible && (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 || > - 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; > + ret = intel_clip_src_rect(plane, crtc_state, state); > + if (ret) > + return ret; > > if (INTEL_GEN(dev_priv) >= 9) { > ret = skl_check_plane_surface(crtc_state, state); > -- > 2.17.0.921.gf22659ad46-goog > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5f03af455047..e1eb0fb988a6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12856,6 +12856,170 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state return max_scale; } +int +intel_clip_src_rect(struct intel_plane *plane, + struct intel_crtc_state *crtc_state, + struct intel_plane_state *state) +{ + 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 hscale, vscale; + int max_scale, min_scale; + bool can_scale; + + *src = drm_plane_state_src(&state->base); + *dst = drm_plane_state_dest(&state->base); + + /* setup can_scale, min_scale, max_scale */ + if (INTEL_GEN(dev_priv) >= 9) { + /* use scaler when colorkey is not required */ + if (!state->ckey.flags) { + can_scale = 1; + min_scale = 1; + max_scale = skl_max_scale(crtc, crtc_state); + } else { + can_scale = 0; + min_scale = DRM_PLANE_HELPER_NO_SCALING; + max_scale = DRM_PLANE_HELPER_NO_SCALING; + } + } else { + can_scale = plane->can_scale; + max_scale = plane->max_downscale << 16; + 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, hscale, vscale); + + crtc_x = dst->x1; + crtc_y = dst->y1; + crtc_w = drm_rect_width(dst); + crtc_h = drm_rect_height(dst); + + 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); + + /* + * Hardware doesn't handle subpixel coordinates. + * Adjust to (macro)pixel boundary, but be careful not to + * increase the source viewport size, because that could + * push the downscaling factor out of bounds. + */ + src_x = src->x1 >> 16; + src_w = drm_rect_width(src) >> 16; + 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; + + if (crtc_w == 0) + state->base.visible = false; + } + } + + /* Check size restrictions when scaling */ + if (state->base.visible && (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 || + 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; + + return 0; +} + static int intel_check_primary_plane(struct intel_plane *plane, struct intel_crtc_state *crtc_state, @@ -12887,6 +13051,12 @@ intel_check_primary_plane(struct intel_plane *plane, if (!state->base.fb) return 0; + if (intel_format_is_yuv(state->base.fb->format->format)) { + ret = intel_clip_src_rect(plane, crtc_state, state); + if (ret) + return ret; + } + if (INTEL_GEN(dev_priv) >= 9) { ret = skl_check_plane_surface(crtc_state, state); if (ret) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a80fbad9be0f..43847927a927 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1591,6 +1591,8 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); +int intel_clip_src_rect(struct intel_plane *plane, + struct intel_crtc_state *crtc_state, struct intel_plane_state *state); static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state) { diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index dbdcf85032df..892d3247ed69 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -935,21 +935,9 @@ 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; @@ -967,145 +955,9 @@ intel_check_sprite_plane(struct intel_plane *plane, return -EINVAL; } - /* setup can_scale, min_scale, max_scale */ - if (INTEL_GEN(dev_priv) >= 9) { - /* use scaler when colorkey is not required */ - if (!state->ckey.flags) { - can_scale = 1; - min_scale = 1; - max_scale = skl_max_scale(crtc, crtc_state); - } else { - can_scale = 0; - min_scale = DRM_PLANE_HELPER_NO_SCALING; - max_scale = DRM_PLANE_HELPER_NO_SCALING; - } - } else { - can_scale = plane->can_scale; - max_scale = plane->max_downscale << 16; - 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, hscale, vscale); - - crtc_x = dst->x1; - crtc_y = dst->y1; - crtc_w = drm_rect_width(dst); - crtc_h = drm_rect_height(dst); - - 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); - - /* - * Hardware doesn't handle subpixel coordinates. - * Adjust to (macro)pixel boundary, but be careful not to - * increase the source viewport size, because that could - * push the downscaling factor out of bounds. - */ - src_x = src->x1 >> 16; - src_w = drm_rect_width(src) >> 16; - 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; - - if (crtc_w == 0) - state->base.visible = false; - } - } - - /* Check size restrictions when scaling */ - if (state->base.visible && (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 || - 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; + ret = intel_clip_src_rect(plane, crtc_state, state); + if (ret) + return ret; if (INTEL_GEN(dev_priv) >= 9) { ret = skl_check_plane_surface(crtc_state, state);
YUV planes need to be multiples of 2 to scan out. This was handled correctly for planes other than the primary in the intel_check_sprite_plane, where the code fixes up the plane and makes it compliant. Move this code into a location that allows the primary check to access it as well. Signed-off-by: Fritz Koenig <frkoenig@google.com> --- drivers/gpu/drm/i915/intel_display.c | 170 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_sprite.c | 154 +----------------------- 3 files changed, 175 insertions(+), 151 deletions(-)