[PATCH v21 18/19] drm/i915: Reuse code from check_sprite for primary as well
Vidya Srinivas
vidya.srinivas at intel.com
Sat Apr 7 11:26:15 UTC 2018
Moved code from intel_check_sprite to
intel_atomic_helper_check_plane_state.
We use the same for both primary and sprites now.
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_atomic_plane.c | 182 ++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_display.c | 13 ++-
drivers/gpu/drm/i915/intel_drv.h | 7 ++
drivers/gpu/drm/i915/intel_sprite.c | 178 +++++------------------------
4 files changed, 223 insertions(+), 157 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
index 7481ce8..3ce808e 100644
--- a/drivers/gpu/drm/i915/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -107,6 +107,188 @@ intel_plane_destroy_state(struct drm_plane *plane,
drm_atomic_helper_plane_destroy_state(plane, state);
}
+int
+intel_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
+ const struct drm_crtc_state *crtc_state,
+ struct drm_plane *plane, int min_scale,
+ int max_scale, bool can_position,
+ bool can_scale, 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;
+ struct drm_i915_private *dev_priv = to_i915(plane->dev);
+ uint32_t src_x, src_y, src_w, src_h;
+ int crtc_x, crtc_y;
+ unsigned int crtc_w, crtc_h;
+
+ 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);
+
+ hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
+ vscale = drm_rect_calc_vscale_relaxed(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);
+
+ plane_state->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 (plane_state->visible) {
+ /* check again in case clipping clamped the results */
+ hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
+ if (hscale < 0) {
+ DRM_ERROR("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_ERROR("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, rotation);
+
+ /* sanity check to make sure the src viewport wasn't enlarged */
+ WARN_ON(src->x1 < (int)plane_state->src_x ||
+ src->y1 < (int)plane_state->src_y ||
+ (src->x2 >
+ (int)plane_state->src_x + plane_state->src_w) ||
+ (src->y2 >
+ (int)plane_state->src_y + plane_state->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)
+ plane_state->visible = false;
+ }
+ }
+
+ /* Check size restrictions when scaling */
+ if (plane_state->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)
+ plane_state->visible = false;
+
+ if (src_w < 3 || src_h < 3)
+ plane_state->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("Src dimensions exceed hw limit\n");
+ return -EINVAL;
+ }
+ }
+
+ if (plane_state->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 (!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;
+}
+
int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
struct intel_crtc_state *crtc_state,
const struct intel_plane_state *old_plane_state,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4c9a112..ca90fee 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12961,13 +12961,14 @@ intel_check_primary_plane(struct intel_plane *plane,
struct drm_crtc *crtc = state->base.crtc;
int min_scale = DRM_PLANE_HELPER_NO_SCALING;
int max_scale = DRM_PLANE_HELPER_NO_SCALING;
- bool can_position = false;
+ bool can_position = false, can_scale = false;
int ret;
uint32_t pixel_format = 0;
if (INTEL_GEN(dev_priv) >= 9) {
/* use scaler when colorkey is not required */
if (!state->ckey.flags) {
+ can_scale = true;
min_scale = 1;
if (state->base.fb)
pixel_format = state->base.fb->format->format;
@@ -12977,10 +12978,12 @@ 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_atomic_helper_check_plane_state(&state->base,
+ &crtc_state->base,
+ &plane->base,
+ min_scale, max_scale,
+ can_position, can_scale,
+ true);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9c58da0..e83e6a0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -2131,6 +2131,13 @@ struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
void intel_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state);
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
+int
+intel_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
+ const struct drm_crtc_state *crtc_state,
+ struct drm_plane *plane, int min_scale,
+ int max_scale, bool can_position,
+ bool can_scale,
+ bool can_update_disabled);
int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
struct intel_crtc_state *crtc_state,
const struct intel_plane_state *old_plane_state,
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index d5dad44..4f7fb9e 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -933,184 +933,58 @@ intel_check_sprite_plane(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 = {};
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
+ int min_scale = DRM_PLANE_HELPER_NO_SCALING;
+ int max_scale = DRM_PLANE_HELPER_NO_SCALING;
+ bool can_position = false, can_scale = false;
int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
- int hscale, vscale;
- int max_scale, min_scale;
- bool can_scale;
- int ret;
+ struct drm_framebuffer *fb = state->base.fb;
uint32_t pixel_format = 0;
-
- *src = drm_plane_state_src(&state->base);
- *dst = drm_plane_state_dest(&state->base);
-
- if (!fb) {
- state->base.visible = false;
- return 0;
- }
+ int ret;
/* Don't modify another pipe's plane */
- if (plane->pipe != crtc->pipe) {
+ if (plane->pipe != intel_crtc->pipe) {
DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
return -EINVAL;
}
/* FIXME check all gen limits */
- if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > max_stride) {
+ if (fb &&
+ (fb->width < 3 || fb->height < 3 || fb->pitches[0] > max_stride)) {
DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
return -EINVAL;
}
- /* setup can_scale, min_scale, max_scale */
if (INTEL_GEN(dev_priv) >= 9) {
- if (state->base.fb)
- pixel_format = state->base.fb->format->format;
/* use scaler when colorkey is not required */
if (!state->ckey.flags) {
- can_scale = 1;
+ can_scale = true;
min_scale = 1;
- max_scale =
- skl_max_scale(crtc, crtc_state, pixel_format);
- } else {
- can_scale = 0;
- min_scale = DRM_PLANE_HELPER_NO_SCALING;
- max_scale = DRM_PLANE_HELPER_NO_SCALING;
+ if (state->base.fb)
+ pixel_format = state->base.fb->format->format;
+ max_scale = skl_max_scale(intel_crtc,
+ crtc_state, pixel_format);
}
+ can_position = true;
} 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;
- }
+ ret = intel_atomic_helper_check_plane_state(&state->base,
+ &crtc_state->base,
+ &plane->base,
+ min_scale, max_scale,
+ can_position, can_scale,
+ true);
+ if (ret)
+ return ret;
- dst->x1 = crtc_x;
- dst->x2 = crtc_x + crtc_w;
- dst->y1 = crtc_y;
- dst->y2 = crtc_y + crtc_h;
+ if (!state->base.fb)
+ return 0;
if (INTEL_GEN(dev_priv) >= 9) {
ret = skl_check_plane_surface(crtc_state, state);
--
2.7.4
More information about the Intel-gfx-trybot
mailing list