From patchwork Tue May 19 19:39:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Mader X-Patchwork-Id: 26784 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 CAFB6C32F4 for ; Tue, 19 May 2026 19:39:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DE5516302C; Tue, 19 May 2026 21:39:45 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=collabora.com header.i=robert.mader@collabora.com header.b="iP7CLjez"; dkim-atps=neutral Received: from sender4-pp-f112.zoho.com (sender4-pp-f112.zoho.com [136.143.188.112]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8B79263035 for ; Tue, 19 May 2026 21:39:41 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; t=1779219576; cv=none; d=zohomail.com; s=zohoarc; b=NwzCObXTwmRbLpNkFAGVOP1RsOIjAz+sKDLo3VsOwEZ/EFRXb73Kyee/Pu3jKeCOcfNafoLaCvC8Q+OqraWM7gUOcJCOuSlr7jjVkoQTf4qa3fxg/Cmkn37MbhPqR2Xi4HuBWzBjRpltYzdD3hyoCo+nrD2QLo7ayhC0vZvVtSg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779219576; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=2US6PQNWHOHw1P5M7cN6ib8CWzcdBXpsSJ5Gg/SjQXI=; b=NcI6+/iR3/tuyNUnIuwzrjI+QW8dpdRC1Sx7/CHQWhvLc25y4YkHhKlMyMROvtcPWIzfnNX4FUllTJUQg28eXPY6/GAwErN/n8aIfWMrvROt6nsjaFHoY0UES94LcuvzzaV8uJP3JEicSOjkoT1n46kTi/KNtov7Rz+BnMJMFgU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=collabora.com; spf=pass smtp.mailfrom=robert.mader@collabora.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1779219576; s=zohomail; d=collabora.com; i=robert.mader@collabora.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=2US6PQNWHOHw1P5M7cN6ib8CWzcdBXpsSJ5Gg/SjQXI=; b=iP7CLjezpTU2DibLL1tassqpVL6TbD+OUCGs1MjC2/pw9BODbLbFy7eP64At8qw0 AzLPwTdU7lIlI/Afv5X0lqyJacUEq0Ic16jhN035kTc7SqCNqO3ZREK72cyXJ1PpMfh mD4Y3meq+iQrBn6fOUfwBKGy+0eVZIm3PYn99PvQ= Received: by mx.zohomail.com with SMTPS id 1779219575945619.5835395482512; Tue, 19 May 2026 12:39:35 -0700 (PDT) From: Robert Mader To: libcamera-devel@lists.libcamera.org Cc: Robert Mader Subject: [PATCH v3 3/5] debayer_egl: Implement dmabuf import for input buffers Date: Tue, 19 May 2026 21:39:05 +0200 Message-ID: <20260519193907.86812-4-robert.mader@collabora.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260519193907.86812-1-robert.mader@collabora.com> References: <20260519193907.86812-1-robert.mader@collabora.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" In many cases we can import the GPU-ISP input buffers, dmabufs from v4l2, directly into EGL instead of mapping and uploading - i.e. copying - them. Doing so can have positive effects in multiple areas, including reducing memory bandwidth and CPU usage, as well as avoiding expensive dmabuf syncs and syscalls. The main reason direct imports may not work are the more demanding stride alignment requirements many GPUs have - often 128 or 256 bytes - compared to ISPs - apparently often closer to 32 bytes. Thus we first try to import buffers directly and - if that fails - fall back to the previous upload path. Failing imports should come at low cost as drivers know the limitations and can bail out early, without causing additional IO or context switches. In the future we might be able to request buffers with a matching stride from v4l2 drivers in many cases, making direct import the norm instead of a hit-or-miss. An optional kernel API for that exists, but doesn't seem to be implemented by any driver tested so far. While on it, add some minor code adjustments to make it easier to follow. Signed-off-by: Robert Mader --- src/libcamera/software_isp/debayer_egl.cpp | 40 ++++++++++++++-------- src/libcamera/software_isp/debayer_egl.h | 4 ++- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index a217e3798..750895d10 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -500,16 +500,32 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) return; } -int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams ¶ms) +int DebayerEGL::debayerGPU(FrameBuffer *input, std::optional *inputBufferDmaSyncer, FrameBuffer *output, const DebayerParams ¶ms) { /* eGL context switch */ egl_.makeCurrent(); - /* Create a standard texture input */ - egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); + /* Try to create texture for input buffer via dmabuf import */ + if (!dmabuf_import_failed_) { + if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) { + LOG(Debayer, Info) << "Importing input buffer with DMABuf import failed, falling back to upload"; + dmabuf_import_failed_ = true; + } + } + + /* Otherwise create texture for input buffer via upload from CPU */ + if (dmabuf_import_failed_) { + inputBufferDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); + if (!in.isValid()) { + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; + return -ENODEV; + } + egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); + } /* Generate the output render framebuffer as render to texture */ - egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd); + egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get()); setShaderVariableValues(params); glViewport(0, 0, width_, height_); @@ -531,23 +547,15 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output { bench_.startFrame(); - std::vector dmaSyncers; - - dmaSyncBegin(dmaSyncers, input, nullptr); - /* Copy metadata from the input buffer */ FrameMetadata &metadata = output->_d()->metadata(); metadata.status = input->metadata().status; metadata.sequence = input->metadata().sequence; metadata.timestamp = input->metadata().timestamp; - MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); - if (!in.isValid()) { - LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; - goto error; - } + std::optional inputBufferDmaSyncer; - if (debayerGPU(in, output->planes()[0].fd.get(), params)) { + if (debayerGPU(input, &inputBufferDmaSyncer, output, params)) { LOG(Debayer, Error) << "debayerGPU failed"; goto error; } @@ -557,8 +565,10 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output metadata.planes()[0].bytesused = output->planes()[0].length; /* Calculate stats for the whole frame */ + if (!inputBufferDmaSyncer && (frame % SwStatsCpu::kStatPerNumFrames) == 0) + inputBufferDmaSyncer.emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); stats_->processFrame(frame, 0, input); - dmaSyncers.clear(); + inputBufferDmaSyncer.reset(); outputBufferReady.emit(output); inputBufferReady.emit(input); diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 141fb288f..fd8c577d3 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -65,7 +65,7 @@ private: int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat); int getShaderVariableLocations(); void setShaderVariableValues(const DebayerParams ¶ms); - int debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams ¶ms); + int debayerGPU(FrameBuffer *input, std::optional *inputBufferDmaSyncer, FrameBuffer *output, const DebayerParams ¶ms); /* Shader program identifiers */ GLuint vertexShaderId_ = 0; @@ -109,6 +109,8 @@ private: GLint glFormat_; unsigned int bytesPerPixel_; uint32_t shaderStridePixels_; + + bool dmabuf_import_failed_; }; } /* namespace libcamera */