[Intel-gfx] [PATCH v6 2/5] drm/i915/display/psr: Use plane damage clips to calculate damaged area
Mun, Gwan-gyeong
gwan-gyeong.mun at intel.com
Wed Dec 16 10:29:46 UTC 2020
On Tue, 2020-12-15 at 05:14 -0800, Souza, Jose wrote:
> On Tue, 2020-12-15 at 13:02 +0000, Mun, Gwan-gyeong wrote:
> > On Mon, 2020-12-14 at 09:49 -0800, José Roberto de Souza wrote:
> > > Now using plane damage clips property to calcualte the damaged
> > > area.
> > > Selective fetch only supports one region to be fetched so
> > > software
> > > needs to calculate a bounding box around all damage clips.
> > >
> > > Now that we are not complete fetching each plane, there is
> > > another
> > > loop needed as all the plane areas that intersect with the pipe
> > > damaged area needs to be fetched from memory so the complete
> > > blending
> > > of all planes can happen.
> > >
> > Hi,
> > > v2:
> > > - do not shifthing new_plane_state->uapi.dst only src is in
> > > 16.16
> > Typo on commit message. shifthing -> shifting
> > > format
> > >
> > > v4:
> > > - setting plane selective fetch area using the whole pipe damage
> > > area
> > > - mark the whole plane area damaged if plane visibility or alpha
> > > changed
> > >
> > > v5:
> > > - taking in consideration src.y1 in the damage coordinates
> > > - adding to the pipe damaged area planes that were visible but
> > > are
> > > invisible in the new state
> > >
> > > v6:
> > > - consider old state plane coordinates when visibility changes or
> > > it
> > > moved to calculate damaged area
> > > - remove from damaged area the portion not in src clip
> > >
> > > Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> > > Cc: Gwan-gyeong Mun <gwan-gyeong.mun at intel.com>
> > > Signed-off-by: José Roberto de Souza <jose.souza at intel.com>
> > > ---
> > > drivers/gpu/drm/i915/display/intel_psr.c | 98
> > > +++++++++++++++++++++-
> > > --
> > > 1 file changed, 86 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/display/intel_psr.c
> > > b/drivers/gpu/drm/i915/display/intel_psr.c
> > > index d9a395c486d3..7daed098fa74 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_psr.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> > > @@ -1269,8 +1269,8 @@ 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 pipe_clip = { .x1 = 0, .y1 = -1, .x2 = INT_MAX,
> > > .y2 = -1 };
> > > 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;
> > > @@ -1282,9 +1282,17 @@ int intel_psr2_sel_fetch_update(struct
> > > intel_atomic_state *state,
> > > if (ret)
> > > return ret;
> > >
> > >
> > >
> > >
> > > + /*
> > > + * Calculate minimal selective fetch area of each plane and
> > > calculate
> > > + * the pipe damaged area.
> > > + * In the next loop the plane selective fetch area will
> > > actually be set
> > > + * using whole pipe damaged area.
> > > + */
> > > for_each_oldnew_intel_plane_in_state(state, plane,
> > > old_plane_state,
> > > new_plane_state, i) {
> > > - struct drm_rect *sel_fetch_area, temp;
> > > + struct drm_rect src, damaged_area = { .x1 = 0, .y1 =
> > > -1, .x2 = INT_MAX, .y2 = -1 };
> > > + struct drm_mode_rect *damaged_clips;
> > > + u32 num_clips, j;
> > >
> > >
> > >
> > >
> > > if (new_plane_state->uapi.crtc != crtc_state-
> > > > uapi.crtc)
> > > continue;
> > > @@ -1300,23 +1308,89 @@ int intel_psr2_sel_fetch_update(struct
> > > intel_atomic_state *state,
> > > break;
> > > }
> > >
> > >
> > >
> > >
> > > - if (!new_plane_state->uapi.visible)
> > > - continue;
> > > + drm_rect_convert_16_16_to_regular(&new_plane_state-
> > > > uapi.src, &src);
> > > + damaged_clips =
> > > drm_plane_get_damage_clips(&new_plane_state->uapi);
> > > + num_clips =
> > > drm_plane_get_damage_clips_count(&new_plane_state->uapi);
> > >
> > >
> > >
> > >
> > > /*
> > > - * For now doing a selective fetch in the whole plane
> > > area,
> > > - * optimizations will come in the future.
> > > + * If visibility or plane moved, mark the whole plane
> > > area as
> > > + * damaged as it needs to be complete redraw in the new
> > > and old
> > > + * position.
> > > */
> > > + if (new_plane_state->uapi.visible != old_plane_state-
> > > > uapi.visible ||
> > > + !drm_rect_equals(&new_plane_state->uapi.dst,
> > > + &old_plane_state->uapi.dst)) {
> > > + damaged_area.y1 = old_plane_state->uapi.src.y1
> > > > > 16;
> > > + damaged_area.y1 = old_plane_state->uapi.src.y2
> > > > > 16;
> > > + damaged_area.y1 += old_plane_state-
> > > > uapi.dst.y1;
> > > + damaged_area.y2 += old_plane_state-
> > > > uapi.dst.y1;
> > > + clip_area_update(&pipe_clip, &damaged_area);
> > > +
> > > + num_clips = 0;
> > > + damaged_area.y1 = src.y1;
> > > + damaged_area.y2 = src.y2;
> > 1. Visibility change case
> > The pipe damaged area (The Selective Update region) needs to
> > accumulate being visible plane's dst between old and new plane's
> > dst.
> >
> > if you are implementing this scenario, the code shoule be like
> > this,
> >
> > if (new_plane_state->uapi.visible != old_plane_state->uapi.visible)
> > {
> > if (new_plane_state->uapi.visible) {
> > damaged_area.y1 = new_plane_state->uapi.dst.y1;
> > damaged_area.y2 = new_plane_state->uapi.dst.y2;
> > } else {
> > damaged_area.y1 = old_plane_state->uapi.dst.y1;
> > damaged_area.y2 = old_plane_state->uapi.dst.y2;
> > }
> > clip_area_update(&pipe_clip, &damaged_area);
> > continue;
> > }
>
> The current code does exactly above but discards the clipped in
> uapi.src.
>
in order to accumlate the pipe damage area, we don't need to use and
calculate src coordinates on move and visibility change scenarios.
we can easily accumalates than additional calculation.
> > 2. Move case
> > The pipe damaged area (The Selective Update region) needs to
> > accumulate both old and new plane's dst
>
> same
>
> > if you are implementing this scenario, the code shoule be like
> > this,
> >
> > else if (!drm_rect_equals(&new_plane_state->uapi.dst,
> > &old_plane_state-
> > > uapi.dst)) {
> > damaged_area.y1 = new_plane_state->uapi.dst.y1;
> > damaged_area.y2 = new_plane_state->uapi.dst.y2;
> > clip_area_update(&pipe_clip, &damaged_area);
> >
> > damaged_area.y1 = old_plane_state->uapi.dst.y1;
> > damaged_area.y2 = old_plane_state->uapi.dst.y2;
> > clip_area_update(&pipe_clip, &damaged_area);
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > continue;
> > }
> > > + } else if (new_plane_state->uapi.alpha !=
> > > old_plane_state->uapi.alpha) {
> > > + num_clips = 0;
> > > + damaged_area.y1 = src.y1;
> > > + damaged_area.y2 = src.y2;
> > 3. alpha has changed ( because alpha handling section is not
> > optimized,
> > it can be treated with the move section)
>
Yes, you are right, there was a misunderstanding of the alpha scenario
of me.
> no need to handle like this for alpha, if the plane moved if will be
> handled in the "if" above with or without alpha change, if it did not
> moved but
> alpha change no need to add the old state coordinate to the pipe
> clip.
>
> > else if (new_plane_state->uapi.alpha != old_plane_state-
> > >uapi.alpha) {
> > damaged_area.y1 = new_plane_state->uapi.dst.y1;
> > damaged_area.y2 = new_plane_state->uapi.dst.y2;
> > clip_area_update(&pipe_clip, &damaged_area);
> >
> > damaged_area.y1 = old_plane_state->uapi.dst.y1;
> > damaged_area.y2 = old_plane_state->uapi.dst.y2;
> > clip_area_update(&pipe_clip, &damaged_area);
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > continue;
> > }
> > > + } else if (!num_clips &&
> > > + new_plane_state->uapi.fb != old_plane_state-
> > > > uapi.fb) {
> > > + /*
> > > + * If the plane don't have damage areas but the
> > > + * framebuffer changed, mark the whole plane
> > > area as
> > > + * damaged.
> > > + */
> > > + damaged_area.y1 = src.y1;
> > > + damaged_area.y2 = src.y2;
> > > + }
> > > +
> > else if (!num_clips && new_plane_state->uapi.fb != old_plane_state-
> > > uapi.fb) {
> > /*
> > * If the plane don't have damage areas but the
> > * framebuffer changed, mark the whole plane area as
> > * damaged.
> > */
> > damaged_area.y1 = new_plane_state->uapi.dst.y1;
> > damaged_area.y2 = new_plane_state->uapi.dst.y2;
> > clip_area_update(&pipe_clip, &damaged_area);
> > continue;
> > }
> > > + for (j = 0; j < num_clips; j++) {
> > > + struct drm_rect clip;
> > > +
> > > + clip.y1 = damaged_clips[j].y1;
> > > + clip.y2 = damaged_clips[j].y2;
> > > + clip_area_update(&damaged_area, &clip);
> > > + }
> > > +
> > > + if (!drm_rect_intersect(&damaged_area, &src))
> > > + continue;
> > > +
> > > + damaged_area.y1 += new_plane_state->uapi.dst.y1;
> > > + damaged_area.y2 += new_plane_state->uapi.dst.y1;
> > > + clip_area_update(&pipe_clip, &damaged_area);
> > > + }
> > > +
> > else if (num_clips) {
> > struct drm_rect plane_damaged_area;
> > plane_damaged_area.x1 = src.x1;
> > plane_damaged_area.x2 = src.x2;
> > plane_damaged_area.y1 = 0;
> > plane_damaged_area.y2 = 0;
> >
> > for (j = 0; j < num_clips; j++) {
> > struct drm_rect clip;
> >
> > clip.x1 = damaged_clips[j].x1;
> > clip.x2 = damaged_clips[j].x2;
> > clip.y1 = damaged_clips[j].y1;
> > clip.y2 = damaged_clips[j].y2;
> >
> > if (drm_rect_intersect(&clip, &src)) {
> > clip_area_update(&plane_damaged_area, &clip);
> > }
>
> Call intersect at every clip? that don't look optimized.
>
when the clip_area_update() is called it just accumulates the input
rects to one output rect.
it might lead to accumulating unneeded excessive update rect region
>
> > }
> >
> > if (drm_rect_visible(plane_damaged_area)) {
> > plane_damaged_area.y1 = plane_damaged_area.y1 - src.y1 +
> > new_plane_state->uapi.dst.y1;
> > plane_damaged_area.y2 = plane_damaged_area.y2 - src.y1 +
> > new_plane_state->uapi.dst.y1;
> >
> > clip_area_update(&pipe_clip, &plane_damaged_area);
> > continue;
> > }
> > }
>
> Current code sum all the damage clips, if the sum of the damage clips
> insect with the src area it is translated to pipe coordinates and
> called
> clip_area_update() to update pipe_clip.
>
> > the calculation and translating cooridinates is alreay implemented
> > here
> > (
> > https://patchwork.freedesktop.org/patch/404264/?series=84340&rev=1
> > it has commetns which explains scenarios.)
> > > + if (full_update)
> > > + goto skip_sel_fetch_set_loop;
> > > +
> > > + /*
> > > + * Now that we have the pipe damaged area check if it intersect
> > > with
> > > + * every plane, if it does set the plane selective fetch area.
> > > + */
> > > + for_each_oldnew_intel_plane_in_state(state, plane,
> > > old_plane_state,
> > > + new_plane_state, i) {
> > > + struct drm_rect *sel_fetch_area, inter, src;
> > > +
> > > + if (new_plane_state->uapi.crtc != crtc_state-
> > > >uapi.crtc
> > > + !new_plane_state->uapi.visible)
> > > + continue;
> > > +
> > > + inter = pipe_clip;
> > > + if (!drm_rect_intersect(&inter, &new_plane_state-
> > > > uapi.dst))
> > > + continue;
> > > +
> > > + drm_rect_convert_16_16_to_regular(&new_plane_state-
> > > > uapi.src, &src);
> > > +
> > > 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;
> > > + sel_fetch_area->y1 = inter.y1 - new_plane_state-
> > > > uapi.dst.y1;
> > > + sel_fetch_area->y2 = inter.y2 - new_plane_state-
> > > > uapi.dst.y1;
> > sel_fetch_area->y1 = inter.y1 - new_plane_state->uapi.dst.y1 +
> > src.y1;
> > sel_fetch_area->y2 = inter.y2 - new_plane_state->uapi.dst.y1 +
> > src.y1;
>
> sel_fetch_area->y1 = inter.y1 - new_plane_state->uapi.dst.y1; +
> drm_rect_intersect(sel_fetch_area, &src);
> does a the same job and is easier to understand(translation + clip)
>
when the src's x1 and y1 indicates over than 0, does it work?
> > > + sel_fetch_area->x1 = src.x1;
> > > + sel_fetch_area->x2 = src.x2;
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > > - 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);
> > > + drm_rect_intersect(sel_fetch_area, &src);
> > why this line is needed?
>
> explained above.
>
>
> > > }
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > > +skip_sel_fetch_set_loop:
> > > psr2_man_trk_ctl_calc(crtc_state, &pipe_clip, full_update);
> > > return 0;
> > > }
More information about the Intel-gfx
mailing list