From patchwork Mon Sep 14 12:38:32 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 28242 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 94269C3226 for ; Mon, 14 Sep 2026 12:38:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 324616869A; Mon, 14 Sep 2026 14:38:38 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rMP8yyrI"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E26266868B for ; Mon, 14 Sep 2026 14:38:35 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DCD69981; Mon, 14 Sep 2026 14:36:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789389416; bh=CLtVuHNvisDdpih1F+SmPlZuFsWSnlK55yNK3bbxPZg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rMP8yyrIcXbI14HyevEj9pjvvlOaA33Ml0pB8+Mm87A2B8WnMS7Oq1XH6QD4UiisI jxsdGDM0aRWvDne47RQERapG6C0sJ6ws9bCbB7q7BJmBuM/rx1rA1/Jh0+AJEo1Dr9 NszB07ZWwRqgVdKdjM5VQb5hJHbw1sPcdcuGZ8/A= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v3 1/2] libcamera: matrix: Add a transpose() function Date: Mon, 14 Sep 2026 15:38:32 +0300 Message-ID: <20260914123833.2724712-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914123833.2724712-1-laurent.pinchart@ideasonboard.com> References: <20260914123833.2724712-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 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 Matrix class has a member function to invert a matrix, but no function to transpose it. We already have one open-coded transpose operation in the software ISP implementation, and more would likely be added. Add a transpose() member function to the Matrix class to cover this need. Signed-off-by: Laurent Pinchart Reviewed-by: Barnabás Pőcze --- Changes since v2: - Inline the implementation - Add a function template argument to support optional type conversion - Use int and unsigned int in the unit test Changes since v1: - Add and use nonc-const data() - Add unit test --- include/libcamera/internal/matrix.h | 19 +++++++++++++++++++ src/libcamera/matrix.cpp | 20 +++++++++++++++++++- test/matrix.cpp | 9 +++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/matrix.h b/include/libcamera/internal/matrix.h index f74cda103c72..45ce0000a4cf 100644 --- a/include/libcamera/internal/matrix.h +++ b/include/libcamera/internal/matrix.h @@ -76,6 +76,8 @@ public: constexpr std::span data() const { return data_; } + constexpr std::span data() { return data_; } + constexpr std::span operator[](size_t i) const { return std::span{ &data_.data()[i * Cols], Cols }; @@ -115,6 +117,23 @@ public: return inverse; } + template + [[nodiscard]] + constexpr Matrix transpose() const + { + static_assert(std::is_convertible_v); + + Matrix transposed; + std::span data = transposed.data(); + + for (unsigned int r = 0; r < Rows; ++r) { + for (unsigned int c = 0; c < Cols; ++c) + data[c * Rows + r] = data_[r * Cols + c]; + } + + return transposed; + } + private: /* * \todo The initializer is only necessary for the constructor to be diff --git a/src/libcamera/matrix.cpp b/src/libcamera/matrix.cpp index 9cb0885b3b54..cbaaaa9634e8 100644 --- a/src/libcamera/matrix.cpp +++ b/src/libcamera/matrix.cpp @@ -69,7 +69,7 @@ LOG_DEFINE_CATEGORY(Matrix) */ /** - * \fn Matrix::data() + * \fn Matrix::data() const * \brief Access the matrix data as a linear array * * Access the contents of the matrix as a one-dimensional linear array of @@ -79,6 +79,11 @@ LOG_DEFINE_CATEGORY(Matrix) * \return A span referencing the matrix data as a linear array */ +/** + * \fn Matrix::data() + * \copydoc Matrix::data() const + */ + /** * \fn std::span Matrix::operator[](size_t i) const * \brief Index to a row in the matrix @@ -107,6 +112,19 @@ LOG_DEFINE_CATEGORY(Matrix) * \return The inverse of the matrix */ +/** + * \fn Matrix::transpose() const + * \brief Compute the transpose of the matrix + * \tparam U Type of the numerical values in the tranposed matrix + * + * This function computes the transpose of the matrix. The optional template + * parameter \a U specifies the type of the numerical values in the result. It + * defaults to \a T, and can be specified manually to convert to a different + * data type while transposing. + * + * \return The transpose of the matrix + */ + /** * \fn Matrix::operator[](size_t i) * \copydoc Matrix::operator[](size_t i) const diff --git a/test/matrix.cpp b/test/matrix.cpp index 4afae2da7866..9c69554bd1ee 100644 --- a/test/matrix.cpp +++ b/test/matrix.cpp @@ -46,6 +46,15 @@ protected: ASSERT_EQ(m5[1][0], 0.0); ASSERT_EQ(m5[1][1], 1.0); + Matrix m6({ 1, 2, 3, 4, 5, 6 }); + Matrix m7 = m6.transpose(); + ASSERT_EQ(m7[0][0], 1); + ASSERT_EQ(m7[0][1], 4); + ASSERT_EQ(m7[1][0], 2); + ASSERT_EQ(m7[1][1], 5); + ASSERT_EQ(m7[2][0], 3); + ASSERT_EQ(m7[2][1], 6); + return TestPass; } }; From patchwork Mon Sep 14 12:38:33 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 28243 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 DD2B4BDCB7 for ; Mon, 14 Sep 2026 12:38:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6FB6B686A1; Mon, 14 Sep 2026 14:38:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="mm6BdD+E"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3CCA06868D for ; Mon, 14 Sep 2026 14:38:37 +0200 (CEST) Received: from killaraus.ideasonboard.com (2001-14ba-70f3-e800--a06.rev.dnainternet.fi [IPv6:2001:14ba:70f3:e800::a06]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2815A9A4; Mon, 14 Sep 2026 14:36:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789389417; bh=6eXWSyxS2FoISF87xLf/Yq0CYVYcWE+4m8H8qSUc8x0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mm6BdD+EZDICtSIY9OtTBZUqoCFAt7RbMeNOhUbZ2hiNjLekt+8H3sxL0UfKwdLsK fMh3ldHWnrIuQvkYD26OYMz4ciel6prvAX/2vdxQxlmrcf9rhC1otWWO/bR3jrtOiR hdykBeGHtPHASPWQjoGQhEWNzTp9h2A9GXnMox3M= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v3 2/2] libcamera: software_isp: debayer_egl: Use Matrix::transpose() Date: Mon, 14 Sep 2026 15:38:33 +0300 Message-ID: <20260914123833.2724712-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914123833.2724712-1-laurent.pinchart@ideasonboard.com> References: <20260914123833.2724712-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 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" Replace the manual matrix transposition code with a call to Matrix::transpose(). Signed-off-by: Laurent Pinchart Reviewed-by: Barnabás Pőcze --- src/libcamera/software_isp/debayer_egl.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 3536b5c51ffa..4477c928342f 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -460,21 +460,10 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara << " textureUniformStep_.y " << Step[1] << " textureUniformStrideFactor_ " << Stride << " textureUniformProjMatrix_ " << textureUniformProjMatrix_; - /* - * Pre-transpose matrix for GLES 2.0 - */ - GLfloat ccm[9] = { - params.combinedMatrix[0][0], - params.combinedMatrix[1][0], - params.combinedMatrix[2][0], - params.combinedMatrix[0][1], - params.combinedMatrix[1][1], - params.combinedMatrix[2][1], - params.combinedMatrix[0][2], - params.combinedMatrix[1][2], - params.combinedMatrix[2][2], - }; - glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm); + + /* Pre-transpose matrix for GLES 2.0. */ + Matrix ccm = params.combinedMatrix.transpose(); + glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm.data().data()); LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix; /*