From patchwork Fri Nov 27 10:50:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gwan-gyeong Mun X-Patchwork-Id: 11935531 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A459C2D0E4 for ; Fri, 27 Nov 2020 10:52:11 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D549B206DF for ; Fri, 27 Nov 2020 10:52:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D549B206DF Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B981C6EB8A; Fri, 27 Nov 2020 10:52:09 +0000 (UTC) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1D69F6EB78 for ; Fri, 27 Nov 2020 10:52:00 +0000 (UTC) IronPort-SDR: ykPIrRtRtjy++S4Nc4bJW6DbNWubjckHeG/6croG8AEzW7VdEEU8AASd+gdaDV5sneQAAn3+lN vF5Cz4yh6Mow== X-IronPort-AV: E=McAfee;i="6000,8403,9817"; a="151634275" X-IronPort-AV: E=Sophos;i="5.78,374,1599548400"; d="scan'208";a="151634275" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Nov 2020 02:51:10 -0800 IronPort-SDR: OfIjHX3DFqYJRyI2F5ov/izX+Je7mlAj+js4Rnql++uYa1eTNaknTKAMN82PW2cKuxMbmu2WAt UaW4Wsiu3Tsg== X-IronPort-AV: E=Sophos;i="5.78,374,1599548400"; d="scan'208";a="537605103" Received: from helsinki.fi.intel.com ([10.237.66.162]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Nov 2020 02:51:08 -0800 From: Gwan-gyeong Mun To: intel-gfx@lists.freedesktop.org Date: Fri, 27 Nov 2020 12:50:38 +0200 Message-Id: <20201127105041.2793779-2-gwan-gyeong.mun@intel.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20201127105041.2793779-1-gwan-gyeong.mun@intel.com> References: <20201127105041.2793779-1-gwan-gyeong.mun@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v3 2/5] drm/i915/display/psr: Calculate Trancoder's SU rect and plane's SF rect X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" 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 Cc: Ville Syrjälä Cc: Juha-Pekka Heikkila Signed-off-by: Gwan-gyeong Mun --- 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; }