From patchwork Wed Oct 7 00:02:47 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Matt Roper X-Patchwork-Id: 7340851 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id D5C9A9F1B9 for ; Wed, 7 Oct 2015 00:08:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C9236203AC for ; Wed, 7 Oct 2015 00:08:06 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 054C6206B7 for ; Wed, 7 Oct 2015 00:08:05 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0A8646E1A9; Tue, 6 Oct 2015 17:08:04 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTP id 9F9056E1A9 for ; Tue, 6 Oct 2015 17:08:02 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga103.fm.intel.com with ESMTP; 06 Oct 2015 17:08:02 -0700 X-ExtLoopCount2: 2 from 10.1.134.215 X-IronPort-AV: E=Sophos;i="5.17,646,1437462000"; d="scan'208";a="820991448" Received: from mdroper-hswdev.fm.intel.com (HELO mdroper-hswdev) ([10.1.134.215]) by fmsmga002.fm.intel.com with ESMTP; 06 Oct 2015 17:08:02 -0700 Received: from mattrope by mdroper-hswdev with local (Exim 4.84) (envelope-from ) id 1ZjcH4-0007S9-5b for dri-devel@lists.freedesktop.org; Tue, 06 Oct 2015 17:08:02 -0700 Resent-From: Matt Roper Resent-Date: Tue, 6 Oct 2015 17:08:02 -0700 Resent-Message-ID: <20151007000802.GA4868@intel.com> Resent-To: dri-devel@lists.freedesktop.org Received: from orsmga003.jf.intel.com (10.7.209.27) by fmsmsx104-2.cps.intel.com (10.18.124.211) with Microsoft SMTP Server id 14.3.248.2; Tue, 6 Oct 2015 17:03:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.17,646,1437462000"; d="scan'208";a="659223906" Received: from mdroper-hswdev.fm.intel.com (HELO mdroper-hswdev) ([10.1.134.215]) by orsmga003.jf.intel.com with ESMTP; 06 Oct 2015 17:03:28 -0700 Received: from mattrope by mdroper-hswdev with local (Exim 4.84) (envelope-from ) id 1ZjcCd-0007NT-Sv; Tue, 06 Oct 2015 17:03:27 -0700 From: Matt Roper To: Subject: [PATCH] drm: Check fb against plane size rather than CRTC mode for pageflip Date: Tue, 6 Oct 2015 17:02:47 -0700 Message-ID: <1444176167-28319-1-git-send-email-matthew.d.roper@intel.com> X-Mailer: git-send-email 2.1.4 X-MS-Exchange-Organization-AuthSource: fmsmsx104.amr.corp.intel.com X-MS-Exchange-Organization-AuthAs: Internal X-MS-Exchange-Organization-AuthMechanism: 10 X-MS-Exchange-Organization-AVStamp-Mailbox: NAI;57086624;0;novirus MIME-Version: 1.0 Cc: Tvrtko Ursulin X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The legacy pageflip ioctl calls drm_crtc_check_viewport() to determine whether the framebuffer being flipped is big enough to fill the display it is being flipped to. However some drivers support "windowing" of their primary planes (i.e., a primary plane that does not cover the entire CRTC dimensions); in such situations we can wind up rejecting valid pageflips of buffers that are smaller than the display mode, but still large enough to fill the entire primary plane. What we really want to be comparing against for pageflips is the size of the primary plane, which can be found in crtc->primary->state for atomic drivers (and drivers in the process of transitioning to atomic). There are no non-atomic drivers that support primary plane windowing at the moment, so we'll continue to use the current behavior of looking at the CRTC mode size on drivers that don't have a crtc->primary->state. We'll also continue to use the existing logic for SetCrtc, which is the other callsite for drm_crtc_check_viewport(), since legacy modesets reprogram the primary plane and remove windowing. Note that the existing code was checking a crtc->invert_dimensions field to determine whether the width/height of the mode needed to be swapped. A bonus of checking plane size is that the source width/height we get already take rotation into account so that check is no longer necessary when using the plane size. Testcase: igt/universal-plane-gen9-features-pipe-# Reported-by: Tvrtko Ursulin Cc: Tvrtko Ursulin Cc: Ville Syrjälä Signed-off-by: Matt Roper --- drivers/gpu/drm/drm_crtc.c | 87 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e600a5f..35cd4dc 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2534,9 +2534,76 @@ void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, } EXPORT_SYMBOL(drm_crtc_get_hv_timing); +static int check_viewport(int hdisplay, + int vdisplay, + int x, + int y, + bool invert_dimensions, + const struct drm_framebuffer *fb) +{ + if (invert_dimensions) + swap(hdisplay, vdisplay); + + if (hdisplay > fb->width || + vdisplay > fb->height || + x > fb->width - hdisplay || + y > fb->height - vdisplay) { + DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", + fb->width, fb->height, hdisplay, vdisplay, x, y, + invert_dimensions ? " (inverted)" : ""); + return -ENOSPC; + } + + return 0; +} + +/** + * drm_plane_check_viewport - Checks that a framebuffer is big enough for the + * plane's viewport + * @plane: Plane that framebuffer will be displayed on + * @x: x panning + * @y: y panning + * @fb: framebuffer to check size of + * + * Atomic drivers (or transitioning drivers that support proper plane state) + * may call this function on any plane. Non-atomic drivers may only call this + * for the primary plane while the CRTC is active (we'll assume that the + * primary plane covers the entire CRTC in that case). + */ +int drm_plane_check_viewport(const struct drm_plane *plane, + int x, + int y, + const struct drm_framebuffer *fb) + +{ + struct drm_crtc *crtc = plane->crtc; + int hdisplay, vdisplay; + + if (WARN_ON(plane->state == NULL && + plane->type != DRM_PLANE_TYPE_PRIMARY)) + return -EINVAL; + + /* + * Non-atomic drivers may not have valid plane state to look at. But + * those drivers also don't support windowing of the primary plane, so + * we can fall back to looking at the mode of the owning CRTC. + */ + if (plane->state) { + hdisplay = plane->state->src_w >> 16; + vdisplay = plane->state->src_h >> 16; + } else if (WARN_ON(!crtc)) { + hdisplay = vdisplay = 0; + } else { + drm_crtc_get_hv_timing(&crtc->mode, &hdisplay, &vdisplay); + } + + return check_viewport(hdisplay, vdisplay, x, y, false, fb); +} +EXPORT_SYMBOL(drm_plane_check_viewport); + /** * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the - * CRTC viewport + * CRTC viewport when running in the specified mode * @crtc: CRTC that framebuffer will be displayed on * @x: x panning * @y: y panning @@ -2553,20 +2620,8 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); - if (crtc->invert_dimensions) - swap(hdisplay, vdisplay); - - if (hdisplay > fb->width || - vdisplay > fb->height || - x > fb->width - hdisplay || - y > fb->height - vdisplay) { - DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", - fb->width, fb->height, hdisplay, vdisplay, x, y, - crtc->invert_dimensions ? " (inverted)" : ""); - return -ENOSPC; - } - - return 0; + return check_viewport(hdisplay, vdisplay, x, y, + crtc->invert_dimensions, fb); } EXPORT_SYMBOL(drm_crtc_check_viewport); @@ -5181,7 +5236,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, goto out; } - ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb); + ret = drm_plane_check_viewport(crtc->primary, crtc->x, crtc->y, fb); if (ret) goto out;