From patchwork Wed Apr 30 17:11:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Roper X-Patchwork-Id: 4095251 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 83C59BFF02 for ; Wed, 30 Apr 2014 17:11:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 89322202DD for ; Wed, 30 Apr 2014 17:11:09 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 4D214202BE for ; Wed, 30 Apr 2014 17:11:08 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 332936E1E3; Wed, 30 Apr 2014 10:11:07 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga03.intel.com (mga03.intel.com [143.182.124.21]) by gabe.freedesktop.org (Postfix) with ESMTP id 08F4B6E1E3 for ; Wed, 30 Apr 2014 10:11:05 -0700 (PDT) Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 30 Apr 2014 10:11:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,959,1389772800"; d="scan'208";a="426010160" Received: from mdroper-hswdev.fm.intel.com (HELO mdroper-hswdev) ([10.1.134.215]) by azsmga001.ch.intel.com with ESMTP; 30 Apr 2014 10:11:04 -0700 Received: from mattrope by mdroper-hswdev with local (Exim 4.82) (envelope-from ) id 1WfY2Q-0004Ra-LF; Wed, 30 Apr 2014 10:11:18 -0700 From: Matt Roper To: intel-gfx@lists.freedesktop.org Date: Wed, 30 Apr 2014 10:11:08 -0700 Message-Id: <1398877871-17046-1-git-send-email-matthew.d.roper@intel.com> X-Mailer: git-send-email 1.8.5.1 Subject: [Intel-gfx] [PATCH i-g-t 1/4] kms: Add universal plane support X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 Add support for universal planes. This involves revamping the existing plane handling a bit to allow primary & cursor planes to come from the DRM plane list, rather than always being manually added. Also, eliminate the hard-coded position of primary & cursor in the plane list since the DRM could return them in any order. To minimize impact for existing tests, we add a new igt_display_use_universal_commits() call to toggle between universal and legacy API's for programming the primary and cursor planes. Signed-off-by: Matt Roper --- lib/igt_kms.c | 132 +++++++++++++++++++++++++++++++++++++++++++++------------- lib/igt_kms.h | 5 +++ 2 files changed, 107 insertions(+), 30 deletions(-) diff --git a/lib/igt_kms.c b/lib/igt_kms.c index d00250d..97e329b 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -500,27 +500,24 @@ void igt_display_init(igt_display_t *display, int drm_fd) */ display->n_pipes = resources->count_crtcs; + drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); plane_resources = drmModeGetPlaneResources(display->drm_fd); igt_assert(plane_resources); for (i = 0; i < display->n_pipes; i++) { igt_pipe_t *pipe = &display->pipes[i]; - igt_plane_t *plane; - int p, j; + igt_plane_t *plane = NULL; + int p = 0, j; pipe->display = display; pipe->pipe = i; - /* primary plane */ - p = IGT_PLANE_PRIMARY; - plane = &pipe->planes[p]; - plane->pipe = pipe; - plane->index = p; - plane->is_primary = true; - /* add the planes that can be used with that pipe */ for (j = 0; j < plane_resources->count_planes; j++) { drmModePlane *drm_plane; + drmModeObjectPropertiesPtr proplist; + drmModePropertyPtr prop; + int k; drm_plane = drmModeGetPlane(display->drm_fd, plane_resources->planes[j]); @@ -531,21 +528,67 @@ void igt_display_init(igt_display_t *display, int drm_fd) continue; } - p++; plane = &pipe->planes[p]; plane->pipe = pipe; - plane->index = p; + plane->index = p++; plane->drm_plane = drm_plane; + + prop = NULL; + proplist = drmModeObjectGetProperties(display->drm_fd, + plane_resources->planes[j], + DRM_MODE_OBJECT_PLANE); + for (k = 0; k < proplist->count_props; k++) { + prop = drmModeGetProperty(display->drm_fd, proplist->props[k]); + if (!prop) + continue; + + if (strcmp(prop->name, "type") != 0) { + drmModeFreeProperty(prop); + continue; + } + + switch (proplist->prop_values[k]) { + case DRM_PLANE_TYPE_PRIMARY: + plane->is_primary = 1; + display->has_universal_planes = 1; + break; + case DRM_PLANE_TYPE_CURSOR: + plane->is_cursor = 1; + pipe->has_cursor = 1; + display->has_universal_planes = 1; + break; + } + + drmModeFreeProperty(prop); + break; + } + } - /* cursor plane */ - p++; - plane = &pipe->planes[p]; - plane->pipe = pipe; - plane->index = p; - plane->is_cursor = true; + /* + * Add a drm_plane-less primary plane for kernels without + * universal plane support. + */ + if (!display->has_universal_planes) { + plane = &pipe->planes[p]; + plane->pipe = pipe; + plane->index = p++; + plane->is_primary = true; + } - pipe->n_planes = ++p; + /* + * Add drm_plane-less cursor plane for kernels that don't + * expose a universal cursor plane. + */ + if (!pipe->has_cursor) { + /* cursor plane */ + plane = &pipe->planes[p]; + plane->pipe = pipe; + plane->index = p++; + plane->is_cursor = true; + } + + pipe->n_planes = p; /* make sure we don't overflow the plane array */ igt_assert(pipe->n_planes <= IGT_MAX_PLANES); @@ -700,16 +743,29 @@ static igt_plane_t *igt_pipe_get_plane(igt_pipe_t *pipe, enum igt_plane plane) { int idx; - /* Cursor plane is always the upper plane */ - if (plane == IGT_PLANE_CURSOR) - idx = pipe->n_planes - 1; - else { - igt_assert_f(plane >= 0 && plane < (pipe->n_planes), - "plane=%d\n", plane); - idx = plane; + for (idx = 0; idx < pipe->n_planes; idx++) { + switch (plane) { + case IGT_PLANE_PRIMARY: + if (pipe->planes[idx].is_primary) + return &pipe->planes[idx]; + break; + case IGT_PLANE_CURSOR: + if (pipe->planes[idx].is_cursor) + return &pipe->planes[idx]; + break; + case IGT_PLANE_2: + if (!pipe->planes[idx].is_primary && + !pipe->planes[idx].is_cursor) + return &pipe->planes[idx]; + default: + if (!pipe->planes[idx].is_primary && + !pipe->planes[idx].is_cursor) + /* Consume this overlay and keep searching for another */ + plane--; + } } - return &pipe->planes[idx]; + return NULL; } static uint32_t igt_plane_get_fb_id(igt_plane_t *plane) @@ -761,6 +817,8 @@ static int igt_drm_plane_commit(igt_plane_t *plane, igt_output_t *output) uint32_t fb_id, crtc_id; int ret; + igt_assert(plane->drm_plane); + fb_id = igt_plane_get_fb_id(plane); crtc_id = output->config.crtc->crtc_id; pipe = igt_output_get_driving_pipe(output); @@ -820,7 +878,11 @@ static int igt_drm_plane_commit(igt_plane_t *plane, igt_output_t *output) static int igt_plane_commit(igt_plane_t *plane, igt_output_t *output) { - if (plane->is_cursor) { + struct igt_display *display = plane->pipe->display; + + if (display->commit_universal && plane->drm_plane) { + igt_drm_plane_commit(plane, output); + } else if (plane->is_cursor) { igt_cursor_commit(plane, output); } else if (plane->is_primary) { /* state updated by SetCrtc */ @@ -838,8 +900,8 @@ static int igt_output_commit(igt_output_t *output) int i; pipe = igt_output_get_driving_pipe(output); - if (pipe->need_set_crtc) { - igt_plane_t *primary = &pipe->planes[0]; + if (pipe->need_set_crtc && !display->commit_universal) { + igt_plane_t *primary = igt_pipe_get_plane(pipe, IGT_PLANE_PRIMARY); drmModeModeInfo *mode; uint32_t fb_id, crtc_id; int ret; @@ -889,7 +951,7 @@ static int igt_output_commit(igt_output_t *output) primary->fb_changed = false; } - if (pipe->need_set_cursor) { + if (pipe->need_set_cursor && !display->commit_universal) { igt_plane_t *cursor; uint32_t gem_handle, crtc_id; int ret; @@ -940,6 +1002,16 @@ static int igt_output_commit(igt_output_t *output) return 0; } +/* + * Indicate whether future display commits should use universal plane API's + * or legacy API's. + */ +void igt_display_use_universal_commits(igt_display_t *display, + bool use_universal) +{ + display->commit_universal = use_universal; +} + int igt_display_commit(igt_display_t *display) { int i; diff --git a/lib/igt_kms.h b/lib/igt_kms.h index 8e80d4b..4955fc8 100644 --- a/lib/igt_kms.h +++ b/lib/igt_kms.h @@ -121,6 +121,7 @@ struct igt_pipe { unsigned int need_set_crtc : 1; unsigned int need_set_cursor : 1; unsigned int need_wait_for_vblank : 1; + unsigned int has_cursor : 1; #define IGT_MAX_PLANES 4 int n_planes; igt_plane_t planes[IGT_MAX_PLANES]; @@ -143,6 +144,8 @@ struct igt_display { unsigned long pipes_in_use; igt_output_t *outputs; igt_pipe_t pipes[I915_MAX_PIPES]; + bool has_universal_planes; + bool commit_universal; }; /* set vt into graphics mode, required to prevent fbcon from interfering */ @@ -150,6 +153,8 @@ void igt_set_vt_graphics_mode(void); void igt_display_init(igt_display_t *display, int drm_fd); void igt_display_fini(igt_display_t *display); +void igt_display_use_universal_commits(igt_display_t *display, + bool use_universal); int igt_display_commit(igt_display_t *display); int igt_display_get_n_pipes(igt_display_t *display);