All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
To: intel-gfx@lists.freedesktop.org
Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/display/psr: Calculate Trancoder's SU rect and plane's SF rect
Date: Fri, 27 Nov 2020 12:50:38 +0200	[thread overview]
Message-ID: <20201127105041.2793779-2-gwan-gyeong.mun@intel.com> (raw)
In-Reply-To: <20201127105041.2793779-1-gwan-gyeong.mun@intel.com>

It implements calculating of Selective Update area for transcoder.
SU follows crtc geometry.
the logic handles the following cases.
 1. plane has moved
 2. plane's alpha value has changed
 3. plane's visibility has changed
 4. plane's damage clips exist
 5. plane's fb has flipped, but there were no damaged clips

And it generates a Selective Fetch area for the plane.
Each SF area follows plane geometry.
SF rect is calculated by intersecting a plane's dst rect and SU rect.
in order to follow the plane's src geometry, the intersected rect
is converted to the plane's src geometry.

The current implementation does not handle a fully obscured plane area.
In order to optimize calculating of SU area, it needs to subtract
the accumulated SU area from the visible area.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.h |   9 +
 drivers/gpu/drm/i915/display/intel_psr.c     | 248 +++++++++++++++----
 2 files changed, 211 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 5e0d42d82c11..b2969d8ff625 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -465,6 +465,15 @@ enum phy_fia {
 	     (__i)++) \
 		for_each_if(plane)
 
+#define for_each_oldnew_intel_plane_in_state_reverse(__state, plane, old_plane_state, new_plane_state, __i) \
+	for ((__i) = (__state)->base.dev->mode_config.num_total_plane - 1; \
+	     (__i) >= 0 && \
+		     ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
+		      (old_plane_state) = to_intel_plane_state((__state)->base.planes[__i].old_state), \
+		      (new_plane_state) = to_intel_plane_state((__state)->base.planes[__i].new_state), 1); \
+	     (__i)--) \
+		for_each_if(plane)
+
 #define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
 	for ((__i) = 0; \
 	     (__i) < (__state)->base.dev->mode_config.num_crtc && \
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index d9a395c486d3..f314f550b809 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1249,75 +1249,231 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
 	crtc_state->psr2_man_track_ctl = val;
 }
 
-static void clip_area_update(struct drm_rect *overlap_damage_area,
-			     struct drm_rect *damage_area)
+/* calculate and update selective update rect with update rect */
+static void
+su_rect_update(struct drm_rect *su_rect, struct drm_rect *update_rect)
 {
-	if (overlap_damage_area->y1 == -1) {
-		overlap_damage_area->y1 = damage_area->y1;
-		overlap_damage_area->y2 = damage_area->y2;
+	if (drm_rect_height(update_rect) <= 0)
 		return;
+
+	if (!drm_rect_height(su_rect)) {
+		/* when select update rect is empty */
+		su_rect->y1 = update_rect->y1;
+		su_rect->y2 = update_rect->y2;
+	} else {
+		su_rect->y1 = min(su_rect->y1, update_rect->y1);
+		su_rect->y2 = max(su_rect->y2, update_rect->y2);
 	}
+}
+
+static void
+plane_get_damage_rect(const struct drm_plane_state *state,
+		      struct drm_rect *damage_rect)
+{
+	struct drm_mode_rect *damage_clips;
+	int i;
+	u32 num_clips = drm_plane_get_damage_clips_count(state);
+
+
+	if (!num_clips)
+		return;
 
-	if (damage_area->y1 < overlap_damage_area->y1)
-		overlap_damage_area->y1 = damage_area->y1;
+	damage_clips = drm_plane_get_damage_clips(state);
 
-	if (damage_area->y2 > overlap_damage_area->y2)
-		overlap_damage_area->y2 = damage_area->y2;
+	/* initialize with first damage_clip */
+	damage_rect->x1 = damage_clips[0].x1;
+	damage_rect->y1 = damage_clips[0].y1;
+	damage_rect->x2 = damage_clips[0].x2;
+	damage_rect->y2 = damage_clips[0].y2;
+
+	for (i = 1; i < num_clips; i++) {
+		/* Selective Fetch has limitattion which only can have one rect */
+		damage_rect->x1 = min(damage_rect->x1, damage_clips[i].x1);
+		damage_rect->x2 = max(damage_rect->x2, damage_clips[i].x2);
+		damage_rect->y1 = min(damage_rect->y1, damage_clips[i].y1);
+		damage_rect->y2 = max(damage_rect->y2, damage_clips[i].y2);
+	}
 }
 
-int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
-				struct intel_crtc *crtc)
+/*
+ * Generate Selective Update area rect
+ * Todo: In order to optimize calculating of SU area, it should subtract
+ * accumulated SU area from the visible area.
+ */
+static void
+psr_generate_su_rect(struct intel_atomic_state *state,
+		     struct intel_crtc_state *crtc_state,
+		     struct drm_rect *su_rect)
 {
-	struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
 	struct intel_plane_state *new_plane_state, *old_plane_state;
-	struct drm_rect pipe_clip = { .y1 = -1 };
 	struct intel_plane *plane;
-	bool full_update = false;
-	int i, ret;
+	int i;
 
-	if (!crtc_state->enable_psr2_sel_fetch)
-		return 0;
+	for_each_oldnew_intel_plane_in_state_reverse(state, plane, old_plane_state,
+						     new_plane_state, i) {
+		bool old_alpha, new_alpha, alpha_change;
+		bool visible, visibility_change;
+		bool flip, move;
+		u32 num_clips;
 
-	ret = drm_atomic_add_affected_planes(&state->base, &crtc->base);
-	if (ret)
-		return ret;
+		if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc)
+			continue;
 
-	for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
-					     new_plane_state, i) {
-		struct drm_rect *sel_fetch_area, temp;
+		if (plane->id == PLANE_CURSOR)
+			continue;
 
-		if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc)
+		new_alpha = new_plane_state->uapi.alpha != DRM_BLEND_ALPHA_OPAQUE;
+		old_alpha = old_plane_state->uapi.alpha != DRM_BLEND_ALPHA_OPAQUE;
+		alpha_change = new_alpha != old_alpha;
+		visible = new_plane_state->uapi.visible;
+		visibility_change =
+			old_plane_state->uapi.visible != new_plane_state->uapi.visible;
+		flip = new_plane_state->uapi.fb != old_plane_state->uapi.fb;
+		move = !drm_rect_equals(&new_plane_state->uapi.dst,
+					&old_plane_state->uapi.dst);
+
+		/* 1. plane has moved */
+		if (move && !visibility_change && visible) {
+			su_rect_update(su_rect, &old_plane_state->uapi.dst);
+			su_rect_update(su_rect, &new_plane_state->uapi.dst);
 			continue;
+		}
 
-		/*
-		 * TODO: Not clear how to handle planes with negative position,
-		 * also planes are not updated if they have a negative X
-		 * position so for now doing a full update in this cases
-		 */
-		if (new_plane_state->uapi.dst.y1 < 0 ||
-		    new_plane_state->uapi.dst.x1 < 0) {
-			full_update = true;
-			break;
+		/* 2. plane's alpha value has changed */
+		if (alpha_change && !visibility_change && visible) {
+			su_rect_update(su_rect, &new_plane_state->uapi.dst);
+			continue;
+		}
+
+		/* 3. plane's visibility has changed */
+		if (visibility_change) {
+			if (visible)
+				su_rect_update(su_rect, &new_plane_state->uapi.dst);
+			else
+				su_rect_update(su_rect, &old_plane_state->uapi.dst);
+			continue;
+		}
+
+		num_clips = drm_plane_get_damage_clips_count(&new_plane_state->uapi);
+		/* 4. plane's damage clips exist */
+		if (num_clips && visible) {
+			struct drm_rect damage_rect, src_rect;
+
+			drm_rect_init(&damage_rect, 0, 0, 0, 0);
+			plane_get_damage_rect(&new_plane_state->uapi, &damage_rect);
+			/* convert fixed point float to int */
+			src_rect.x1 = new_plane_state->uapi.src.x1 >> 16;
+			src_rect.x2 = new_plane_state->uapi.src.x2 >> 16;
+			src_rect.y1 = new_plane_state->uapi.src.y1 >> 16;
+			src_rect.y2 = new_plane_state->uapi.src.y2 >> 16;
+
+			/* damage rect is based on src geometry */
+			if (drm_rect_intersect(&damage_rect, &src_rect)) {
+				/*
+				 * su rect is based on dst geometry
+				 * convert damage_rect's src geometry to dst geometry
+				 */
+				damage_rect.x1 =
+					damage_rect.x1 - src_rect.x1 +
+					new_plane_state->uapi.dst.x1;
+				damage_rect.x2 =
+					damage_rect.x2 - src_rect.x1 +
+					new_plane_state->uapi.dst.x1;
+				damage_rect.y1 =
+					damage_rect.y1 - src_rect.y1 +
+					new_plane_state->uapi.dst.y1;
+				damage_rect.y2 =
+					damage_rect.y2 - src_rect.y1 +
+					new_plane_state->uapi.dst.y1;
+
+				su_rect_update(su_rect, &damage_rect);
+			}
+			continue;
+		}
+
+		/* 5. plane's fb has flipped, but there were no damaged clips */
+		if (flip && visible) {
+			su_rect_update(su_rect, &new_plane_state->uapi.dst);
+			continue;
 		}
+	}
+}
+
+/*
+ * Generate Plane's Selective Fetch rect from intersected area between
+ * Selective Update area rect and plane's dst rect.
+ * Todo: Consider to handle a fully obscured plane.
+ */
+static void
+psr_generate_plane_sf_rect(struct intel_atomic_state *state,
+			   struct intel_crtc_state *crtc_state,
+			   const struct drm_rect *su_rect)
+{
+	struct intel_plane_state *new_plane_state, *old_plane_state;
+	struct intel_plane *plane;
+	int i;
+
+	for_each_oldnew_intel_plane_in_state_reverse(state, plane, old_plane_state,
+						     new_plane_state, i) {
+
+		struct drm_rect sf_rect = new_plane_state->uapi.dst;
+
+		if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc)
+			continue;
+
+		if (plane->id == PLANE_CURSOR)
+			continue;
 
 		if (!new_plane_state->uapi.visible)
 			continue;
 
-		/*
-		 * For now doing a selective fetch in the whole plane area,
-		 * optimizations will come in the future.
-		 */
-		sel_fetch_area = &new_plane_state->psr2_sel_fetch_area;
-		sel_fetch_area->y1 = new_plane_state->uapi.src.y1 >> 16;
-		sel_fetch_area->y2 = new_plane_state->uapi.src.y2 >> 16;
-
-		temp = *sel_fetch_area;
-		temp.y1 += new_plane_state->uapi.dst.y1;
-		temp.y2 += new_plane_state->uapi.dst.y2;
-		clip_area_update(&pipe_clip, &temp);
+		if (drm_rect_intersect(&sf_rect, su_rect)) {
+			/*
+			 * su rect is based on dst geometry and sf rect should
+			 * follow src geometry. convert sf rect's dst geometry
+			 * to dst geometry
+			 */
+			sf_rect.x1 = sf_rect.x1 - new_plane_state->uapi.dst.x1 +
+				     (new_plane_state->uapi.src.x1 >> 16);
+			sf_rect.x2 = sf_rect.x2 - new_plane_state->uapi.dst.x1 +
+				     (new_plane_state->uapi.src.x1 >> 16);
+			sf_rect.y1 = sf_rect.y1 - new_plane_state->uapi.dst.y1 +
+				     (new_plane_state->uapi.src.y1 >> 16);
+			sf_rect.y2 = sf_rect.y2 - new_plane_state->uapi.dst.y1 +
+				     (new_plane_state->uapi.src.y1 >> 16);
+
+			new_plane_state->psr2_sel_fetch_area = sf_rect;
+		}
 	}
+}
+
+int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
+				struct intel_crtc *crtc)
+{
+	struct intel_crtc_state *crtc_state =
+		intel_atomic_get_new_crtc_state(state, crtc);
+	struct drm_rect su_rect;
+	bool full_update = false;
+	int ret;
+
+	if (!crtc_state->enable_psr2_sel_fetch)
+		return 0;
+
+	ret = drm_atomic_add_affected_planes(&state->base, &crtc->base);
+	if (ret)
+		return ret;
+
+	/*
+	 * Generate Selective Update area rect
+	 * Todo: In order to optimize calculating of SU area, it should subtract
+	 * accumulated SU area from the visible area.
+	 */
+	drm_rect_init(&su_rect, 0, 0,
+		      crtc_state->uapi.adjusted_mode.crtc_hdisplay, 0);
+	psr_generate_su_rect(state, crtc_state, &su_rect);
+	psr_generate_plane_sf_rect(state, crtc_state, &su_rect);
+	psr2_man_trk_ctl_calc(crtc_state, &su_rect, full_update);
 
-	psr2_man_trk_ctl_calc(crtc_state, &pipe_clip, full_update);
 	return 0;
 }
 
-- 
2.25.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2020-11-27 10:52 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-27 10:50 [Intel-gfx] [PATCH v3 1/5] drm/i915/display/psr: Calculate selective fetch plane registers Gwan-gyeong Mun
2020-11-27 10:50 ` Gwan-gyeong Mun [this message]
2020-11-27 10:50 ` [Intel-gfx] [PATCH v3 3/5] drm/i915/display: Split and export main surface calculation from skl_check_main_surface() Gwan-gyeong Mun
2020-11-27 14:10   ` Souza, Jose
2020-11-27 10:50 ` [Intel-gfx] [PATCH v3 4/5] drm/i915/display/psr: Program Plane's calculated offset to Plane SF register Gwan-gyeong Mun
2020-11-27 10:50 ` [Intel-gfx] [PATCH v3 5/5] HAX/DO_NOT_MERGE_IT: drm/i915/display: Enable PSR2 selective fetch for testing Gwan-gyeong Mun
2020-11-27 13:46 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for series starting with [v3,1/5] drm/i915/display/psr: Calculate selective fetch plane registers Patchwork
2020-11-27 13:48 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2020-11-27 14:17 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201127105041.2793779-2-gwan-gyeong.mun@intel.com \
    --to=gwan-gyeong.mun@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.