From patchwork Mon Sep 6 22:56:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13686 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 4935EBE175 for ; Mon, 6 Sep 2021 22:57:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DDC2569174; Tue, 7 Sep 2021 00:57:45 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DRqXsUMT"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2FB6969175 for ; Tue, 7 Sep 2021 00:57:08 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B4E3B891; Tue, 7 Sep 2021 00:57:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630969027; bh=bqyQIZd68Xh74j2UCky+WnVOGaSWdFIBWkZ5Es1xQRg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DRqXsUMTDvSNIKKg3sr98rKOaFe0sSHzyS9uXYhCoNhm3JlE+XtSh5XLWjSkd+MRH dz4BM0Ff51kelN0fPFaRvD9+zYCav06tVmF2ve+z2Jie+TYjqO9xZ6RCheFNCFON02 Vp04x9oV7UpTWkNlnElH+W/lFaT67HWBTO3mFn2U= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 7 Sep 2021 01:56:29 +0300 Message-Id: <20210906225636.14683-23-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906225420.13275-1-laurent.pinchart@ideasonboard.com> References: <20210906225420.13275-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 23/30] cam: drm: Support per-plane stride values X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The stride is not always identical for all planes for multi-planar formats. Semi-planar YUV formats without horizontal subsampling often have a chroma stride equal to twice the luma stride, and tri-planar YUV formats with a 1/2 horizontal subsampling often have a chroma stride equal to half the luma stride. This isn't correctly taken into account when creating a DRM frame buffer, as the same stride is set for all planes. libcamera doesn't report per-plane stride values yet, but uses chroma strides that match the above description for all currently supported platforms. Calculation the chrome strides appropriately in the KMSSink class, and pass them to DRM::createFrameBuffer(). Signed-off-by: Laurent Pinchart Reviewed-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham --- src/cam/drm.cpp | 7 +++---- src/cam/drm.h | 5 ++++- src/cam/kms_sink.cpp | 28 +++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/cam/drm.cpp b/src/cam/drm.cpp index da317e27cb19..ac47b8bd3287 100644 --- a/src/cam/drm.cpp +++ b/src/cam/drm.cpp @@ -595,12 +595,12 @@ const Object *Device::object(uint32_t id) std::unique_ptr Device::createFrameBuffer( const libcamera::FrameBuffer &buffer, const libcamera::PixelFormat &format, - const libcamera::Size &size, unsigned int stride) + const libcamera::Size &size, + const std::array &strides) { std::unique_ptr fb{ new FrameBuffer(this) }; uint32_t handles[4] = {}; - uint32_t pitches[4] = {}; uint32_t offsets[4] = {}; int ret; @@ -623,13 +623,12 @@ std::unique_ptr Device::createFrameBuffer( fb->planes_.push_back({ handle }); handles[i] = handle; - pitches[i] = stride; offsets[i] = 0; /* TODO */ ++i; } ret = drmModeAddFB2(fd_, size.width, size.height, format.fourcc(), handles, - pitches, offsets, &fb->id_, 0); + strides.data(), offsets, &fb->id_, 0); if (ret < 0) { ret = -errno; std::cerr diff --git a/src/cam/drm.h b/src/cam/drm.h index ee2304025208..00f7e798b771 100644 --- a/src/cam/drm.h +++ b/src/cam/drm.h @@ -7,9 +7,11 @@ #ifndef __CAM_DRM_H__ #define __CAM_DRM_H__ +#include #include #include #include +#include #include #include @@ -298,7 +300,8 @@ public: std::unique_ptr createFrameBuffer( const libcamera::FrameBuffer &buffer, const libcamera::PixelFormat &format, - const libcamera::Size &size, unsigned int stride); + const libcamera::Size &size, + const std::array &strides); libcamera::Signal requestComplete; diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp index 8c0b79c63922..658192efc105 100644 --- a/src/cam/kms_sink.cpp +++ b/src/cam/kms_sink.cpp @@ -7,10 +7,12 @@ #include "kms_sink.h" +#include #include #include #include #include +#include #include #include @@ -65,8 +67,32 @@ KMSSink::KMSSink(const std::string &connectorName) void KMSSink::mapBuffer(libcamera::FrameBuffer *buffer) { + std::array strides = {}; + + /* \todo Should libcamera report per-plane strides ? */ + unsigned int uvStrideMultiplier; + + switch (format_) { + case libcamera::formats::NV24: + case libcamera::formats::NV42: + uvStrideMultiplier = 4; + break; + case libcamera::formats::YUV420: + case libcamera::formats::YVU420: + case libcamera::formats::YUV422: + uvStrideMultiplier = 1; + break; + default: + uvStrideMultiplier = 2; + break; + } + + strides[0] = stride_; + for (unsigned int i = 1; i < buffer->planes().size(); ++i) + strides[i] = stride_ * uvStrideMultiplier / 2; + std::unique_ptr drmBuffer = - dev_.createFrameBuffer(*buffer, format_, size_, stride_); + dev_.createFrameBuffer(*buffer, format_, size_, strides); if (!drmBuffer) return;