diff mbox series

[v2,3/6] drm/i915/display/psr: Consider other planes to damaged area calculation

Message ID 20201027234526.33043-3-jose.souza@intel.com
State New, archived
Headers show
Series [v2,1/6] drm/i915/display/psr: Calculate selective fetch plane registers | expand

Commit Message

Souza, Jose Oct. 27, 2020, 11:45 p.m. UTC
Planes can individually have transparent, move or have visibility
changed if any of those happens, planes bellow it will be visible or
have more pixels of it visible than before.

This patch is taking care of this case for selective fetch by adding
to each plane damaged area all the intersections of planes above it
that matches with the characteristics described above.

There still some room from improvements here but at least this initial
version will take care of display what is expected saving some memory
reads.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
---
 drivers/gpu/drm/i915/display/intel_psr.c | 62 ++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 1c3330e096c7..96ee51484dd6 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1267,11 +1267,38 @@  static void clip_area_update(struct drm_rect *overlap_damage_area,
 		overlap_damage_area->y2 = damage_area->y2;
 }
 
+/* Update plane damage area if planes above moved or have alpha */
+static void pipe_dirty_areas_set(struct intel_plane_state *plane_state,
+				 struct intel_plane *plane,
+				 const struct drm_rect *pipe_dirty_areas,
+				 struct drm_rect *sel_fetch_area)
+{
+	enum plane_id i;
+
+	for (i = PLANE_CURSOR; i > plane->id; i--) {
+		int j;
+
+		for (j = 0; j < 2; j++) {
+			struct drm_rect r = pipe_dirty_areas[i * 2 + j];
+
+			if (!drm_rect_width(&r))
+				continue;
+			if (!drm_rect_intersect(&r, &plane_state->uapi.dst))
+				continue;
+
+			r.y1 -= plane_state->uapi.dst.y1;
+			r.y2 -= plane_state->uapi.dst.y1;
+			clip_area_update(sel_fetch_area, &r);
+		}
+	}
+}
+
 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 intel_plane_state *new_plane_state, *old_plane_state;
+	struct drm_rect pipe_dirty_areas[I915_MAX_PLANES * 2] = {};
 	struct drm_rect pipe_clip = { .y1 = -1 };
 	struct intel_plane *plane;
 	bool full_update = false;
@@ -1284,6 +1311,38 @@  int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
 	if (ret)
 		return ret;
 
+	/*
+	 * Mark all the areas where there is a plane that matches one of this:
+	 * - transparent
+	 * - moved
+	 * - visibility changed
+	 * In all those cases, planes bellow it will need to be redraw.
+	 */
+	for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
+					     new_plane_state, i) {
+		bool alpha, flip, dirty;
+
+		if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc)
+			continue;
+
+		alpha = new_plane_state->uapi.alpha != DRM_BLEND_ALPHA_OPAQUE;
+		alpha |= old_plane_state->uapi.alpha != DRM_BLEND_ALPHA_OPAQUE;
+		flip = new_plane_state->uapi.fb != old_plane_state->uapi.fb;
+		dirty = alpha && flip;
+
+		dirty |= !drm_rect_equals(&new_plane_state->uapi.dst,
+					  &old_plane_state->uapi.dst);
+		dirty |= new_plane_state->uapi.visible !=
+			 old_plane_state->uapi.visible;
+		if (!dirty)
+			continue;
+
+		if (old_plane_state->uapi.visible)
+			pipe_dirty_areas[plane->id * 2] = old_plane_state->uapi.dst;
+		if (new_plane_state->uapi.visible)
+			pipe_dirty_areas[plane->id * 2 + 1] = new_plane_state->uapi.dst;
+	}
+
 	for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
 					     new_plane_state, i) {
 		struct drm_rect *sel_fetch_area, temp;
@@ -1351,6 +1410,9 @@  int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
 			sel_fetch_area->y2 = 0;
 		}
 
+		pipe_dirty_areas_set(new_plane_state, plane, pipe_dirty_areas,
+				     sel_fetch_area);
+
 		/* Don't need to redraw plane damaged areas outside of screen */
 		j = sel_fetch_area->y2 + new_plane_state->uapi.dst.y1;
 		j = crtc_state->uapi.adjusted_mode.crtc_vdisplay - j;