From 093a6b017bd0f2f42edc7377f0262a674e5d7e75 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Wed, 27 May 2026 10:56:32 +0200 Subject: [PATCH] temp/libcamera: update downstream patch to merged version Replace the dmabuf import patch with the two series that it grow into during upstreaming, shipping in the next libcamera release. This will: 1. Improve performance for all devices using the GPU-ISP, including those not able to use dmabuf import. 2. Simplify debugging. 3. Ensure the patches get enough testing before the upstream release. While on it backport some additional patches: 1. A follow-up patch adding the last required step to allow dmabuf import for input buffers to work in almost all cases *if* the V4L2 driver handles custom bytesperline requests for bayer formats. 2. A small logging fix 3. A fix for bad bottom lines of pixels seen on some devices. This is the only patch with visual impact - and a quite desirable one. 4. A patch to log the used driver for easier debugging. This leaves us with only two downstream patches, both specific to the PinePhone (OG). Finally, add a "py3-$pkgname-pyc:pyc" subpackage in order to stay in sync with the upstream package. Part-of: --- ...ude-stats-computation-into-benchmark.patch | 44 ++++ ...-output-buffers-after-processing-sta.patch | 147 ++++++++++++ ...ment-DMABuf-import-for-input-buffers.patch | 212 ------------------ ...at-parameter-to-eGLImage-constructor.patch | 122 ++++++++++ ...some-parameters-from-createTexture2D.patch | 92 ++++++++ ...-flag-to-remember-dmabuf-import-fail.patch | 48 ++++ ...s_cpu-Take-MappedFrameBuffer-in-proc.patch | 83 +++++++ ...ement-dmabuf-import-for-input-buffer.patch | 210 +++++++++++++++++ ...re_isp-debayer_egl-Demote-unsupporte.patch | 54 +++++ ...ayer_egl-Request-input-buffer-alignm.patch | 196 ++++++++++++++++ .../0010-egl-Log-the-GL-driver.patch | 37 +++ ...ayer_egl-Consider-border-for-scaling.patch | 72 ++++++ ...le-Enable-softISP-for-the-Pinephone.patch} | 6 +- ...Skip-hwISP-formats-if-swISP-is-acti.patch} | 7 +- temp/libcamera/APKBUILD | 35 ++- 15 files changed, 1140 insertions(+), 225 deletions(-) create mode 100644 temp/libcamera/0001-debayer_egl-Include-stats-computation-into-benchmark.patch create mode 100644 temp/libcamera/0002-debayer_egl-Sync-output-buffers-after-processing-sta.patch delete mode 100644 temp/libcamera/0003-RFC-egl-Implement-DMABuf-import-for-input-buffers.patch create mode 100644 temp/libcamera/0003-egl-Add-GL-format-parameter-to-eGLImage-constructor.patch create mode 100644 temp/libcamera/0004-egl-Remove-some-parameters-from-createTexture2D.patch create mode 100644 temp/libcamera/0005-egl-eGLImage-Add-flag-to-remember-dmabuf-import-fail.patch create mode 100644 temp/libcamera/0006-libcamera-swstats_cpu-Take-MappedFrameBuffer-in-proc.patch create mode 100644 temp/libcamera/0007-debayer_egl-Implement-dmabuf-import-for-input-buffer.patch create mode 100644 temp/libcamera/0008-libcamera-software_isp-debayer_egl-Demote-unsupporte.patch create mode 100644 temp/libcamera/0009-software_isp-debayer_egl-Request-input-buffer-alignm.patch create mode 100644 temp/libcamera/0010-egl-Log-the-GL-driver.patch create mode 100644 temp/libcamera/0011-software_isp-debayer_egl-Consider-border-for-scaling.patch rename temp/libcamera/{0001-libcamera-simple-Enable-softISP-for-the-Pinephone.patch => 0012-libcamera-simple-Enable-softISP-for-the-Pinephone.patch} (86%) rename temp/libcamera/{0002-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch => 0013-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch} (87%) diff --git a/temp/libcamera/0001-debayer_egl-Include-stats-computation-into-benchmark.patch b/temp/libcamera/0001-debayer_egl-Include-stats-computation-into-benchmark.patch new file mode 100644 index 000000000..7f1df83fb --- /dev/null +++ b/temp/libcamera/0001-debayer_egl-Include-stats-computation-into-benchmark.patch @@ -0,0 +1,44 @@ +From 5a53056f12094b5077453e1393640b979fc40fde Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Tue, 26 May 2026 10:06:38 +0200 +Subject: [PATCH 01/13] debayer_egl: Include stats computation into benchmark + +The following commit will allow debayering on the GPU and stats +computation on the CPU to happen in parallel, requiring this change in +order to keep the benchmark meaningful. + +Do the change first in order to make before/after comparisons simpler. + +Signed-off-by: Robert Mader +Reviewed-by: Kieran Bingham +Reviewed-by: Bryan O'Donoghue +Signed-off-by: Kieran Bingham +(cherry picked from commit 1556025bae58b9e02625587728af349b987a14fa) +--- + src/libcamera/software_isp/debayer_egl.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index 8f0c229fd..565aee9f1 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -547,14 +547,14 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output + goto error; + } + +- bench_.finishFrame(); +- + metadata.planes()[0].bytesused = output->planes()[0].length; + + /* Calculate stats for the whole frame */ + stats_->processFrame(frame, 0, input); + dmaSyncers.clear(); + ++ bench_.finishFrame(); ++ + outputBufferReady.emit(output); + inputBufferReady.emit(input); + +-- +2.54.0 + diff --git a/temp/libcamera/0002-debayer_egl-Sync-output-buffers-after-processing-sta.patch b/temp/libcamera/0002-debayer_egl-Sync-output-buffers-after-processing-sta.patch new file mode 100644 index 000000000..e8fcee9f3 --- /dev/null +++ b/temp/libcamera/0002-debayer_egl-Sync-output-buffers-after-processing-sta.patch @@ -0,0 +1,147 @@ +From e2dcad90def08cd7f2ba34018ce72162ddc957d8 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Tue, 26 May 2026 10:06:39 +0200 +Subject: [PATCH 02/13] debayer_egl: Sync output buffers after processing stats + +Instead of waiting for the GPU to finish output buffers *before* computing +stats, do so afterwards. This allows work to happen in parallel on the GPU +and CPU, improving throughput and reducing latency on various devices as +shown below. + +On order for this to work well we need to flush all GL commands to the +GPU before doing heavy CPU work - thus add a corresponding function. + +Below are some benchmark results. All where done using postmarketOS edge +with updates from 21th May 2026 (Mesa 26.1.1). The mentioned pipelines +where run five times each, with the mean value included here, which should +be quite representive as the variance was rather small. All devices +where using the powersave governor. + +Notes: +1. We only expect changes for frames where stats get computed, currently + every fourth frame (see kStatPerNumFrames) - and the improvements indeed + have been observed to increase when computing stats more often. +2. At least the qcom/freedreno devices have been found to be affected by a + performance issue *without* this patch. This issue can be worked + around by calling `glFlush()` directly before `glFinish()` - as done + in v1 of this series - or by running with `GALLIUM_THREAD=0`. The + benchmarks below show the performance gains *with* those workarounds + applied in order to not inflate the impact of this patch. See + https://gitlab.freedesktop.org/mesa/mesa/-/work_items/15516 for more + context. + +cam -c /base/soc@0/cci@ac4a000/i2c-bus@0/camera@1a -s width=1920,height=1080 --capture=60 +Before: 33596 us/frame +After: 30179 us/frame + +cam -c /base/soc@0/cci@ac4a000/i2c-bus@1/camera@1a -s width=1920,height=1080 --capture=60 +Before: 14922 us/frame +After: 14304 us/frame + +cam -c /base/soc@0/cci@ac4b000/i2c-bus@1/camera@10 -s width=1920,height=1080 --capture=60 +Before: 26106 us/frame +After: 23312 us/frame + +cam -c /base/soc@0/cci@ac4a000/i2c-bus@1/camera@29 -s width=1920,height=1080 --capture=60 +Before: 15897 us/frame +After: 14791 us/frame + +cam -c /base/soc@0/cci@ac4a000/i2c-bus@1/camera@10 -s width=1920,height=1080 --capture=60 +Before: 25721 us/frame +After: 23625 us/frame + +cam -c /base/soc@0/cci@ac4a000/i2c-bus@0/camera@10 -s width=1920,height=1080 --capture=60 +Before: 34124 us/frame +After: 29471 us/frame + +cam -c /base/soc@0/cci@ac4a000/i2c-bus@0/camera@1a -s width=1920,height=1080 --capture=60 +Before: 23707 us/frame +After: 21890 us/frame + +cam -c /base/soc@0/bus@30800000/i2c@30a40000/camera@20 -s width=1280,height=720 --capture=60 +Before: 91649 us/frame +After: 83233 us/frame + +cam -c /base/soc@0/bus@30800000/i2c@30a50000/camera@2d -s width=1280,height=720 --capture=60 +Before: 76956 us/frame +After: 69569 us/frame + +cam -c /base/i2c-csi/front-camera@3c -s width=1280,height=720 --capture=60 +Before: 188500 us/frame +After: 173764 us/frame + +cam -c /base/i2c-csi/rear-camera@4c -s width=1280,height=720 --capture=60 +Before: 190222 us/frame +After: 177251 us/frame + +Signed-off-by: Robert Mader +Reviewed-by: Bryan O'Donoghue +Reviewed-by: Kieran Bingham +Signed-off-by: Kieran Bingham +(cherry picked from commit 2bace926b0f4854bc3508a9805d53e47a273e789) +--- + include/libcamera/internal/egl.h | 1 + + src/libcamera/egl.cpp | 13 +++++++++++++ + src/libcamera/software_isp/debayer_egl.cpp | 3 ++- + 3 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h +index 0ad2320b1..0ec8ea6ec 100644 +--- a/include/libcamera/internal/egl.h ++++ b/include/libcamera/internal/egl.h +@@ -119,6 +119,7 @@ public: + void useProgram(GLuint programId); + void deleteProgram(GLuint programId); + void syncOutput(); ++ void flushOutput(); + + private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL) +diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp +index f65929470..0ababa361 100644 +--- a/src/libcamera/egl.cpp ++++ b/src/libcamera/egl.cpp +@@ -98,6 +98,19 @@ void eGL::syncOutput() + glFinish(); + } + ++/** ++ * \brief Flush the rendering pipeline ++ * ++ * Calls glFlush(). ++ * ++ */ ++void eGL::flushOutput() ++{ ++ ASSERT(tid_ == Thread::currentId()); ++ ++ glFlush(); ++} ++ + /** + * \brief Create a DMA-BUF backed 2D texture + * \param[in,out] eglImage EGL image to associate with the DMA-BUF +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index 565aee9f1..dd6b64be2 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -516,7 +516,7 @@ int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParam + LOG(eGL, Error) << "Drawing scene fail " << err; + return -ENODEV; + } else { +- egl_.syncOutput(); ++ egl_.flushOutput(); + } + + return 0; +@@ -553,6 +553,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output + stats_->processFrame(frame, 0, input); + dmaSyncers.clear(); + ++ egl_.syncOutput(); + bench_.finishFrame(); + + outputBufferReady.emit(output); +-- +2.54.0 + diff --git a/temp/libcamera/0003-RFC-egl-Implement-DMABuf-import-for-input-buffers.patch b/temp/libcamera/0003-RFC-egl-Implement-DMABuf-import-for-input-buffers.patch deleted file mode 100644 index 07975ced7..000000000 --- a/temp/libcamera/0003-RFC-egl-Implement-DMABuf-import-for-input-buffers.patch +++ /dev/null @@ -1,212 +0,0 @@ -From 08b9cc8401e57b05cd8b73e1dd1d7bf0691a048b Mon Sep 17 00:00:00 2001 -From: Robert Mader -Date: Fri, 19 Dec 2025 20:31:16 +0100 -Subject: [PATCH 3/3] RFC: egl: Implement DMABuf import for input buffers - -In many cases we can import the GPU-ISP input buffer, a dmabuf from v4l2, -directly into EGL instead of mapping and uploading - i.e. copying - it. -This reduces memory bandwith usage and can even slightly improve -latency. -This main reason this doesn't work in many cases is the stride -alignment, as GPUs often have stricter requirements (often 128 or even -256 bytes) than hardware ISPs. - -Thus try to import buffer directly and - if that fails - fall back to -the previous upload path. To do so, adjust some function parameters and -turn down error messages. 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. - -Signed-off-by: Robert Mader ---- - include/libcamera/internal/egl.h | 4 +-- - src/libcamera/egl.cpp | 37 +++++++++++++++++----- - src/libcamera/software_isp/debayer_egl.cpp | 21 ++++++------ - src/libcamera/software_isp/debayer_egl.h | 2 +- - 4 files changed, 44 insertions(+), 20 deletions(-) - -diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h -index 0ad2320b1..bb97b0c7c 100644 ---- a/include/libcamera/internal/egl.h -+++ b/include/libcamera/internal/egl.h -@@ -101,7 +101,7 @@ public: - - int initEGLContext(); - -- int createInputDMABufTexture2D(eGLImage &eglImage, int fd); -+ int createInputDMABufTexture2D(eGLImage &eglImage, int fd, GLint format, uint32_t width, uint32_t height); - int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); - void createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint32_t height, void *data); - -@@ -133,7 +133,7 @@ private: - unsigned int shaderDataLen, - Span shaderEnv); - -- int createDMABufTexture2D(eGLImage &eglImage, int fd, bool output); -+ int createDMABufTexture2D(eGLImage &eglImage, int fd, uint32_t drm_format, uint32_t width, uint32_t height, bool output); - - PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; - PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; -diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp -index f65929470..febfd4bba 100644 ---- a/src/libcamera/egl.cpp -+++ b/src/libcamera/egl.cpp -@@ -19,6 +19,7 @@ - - #include - -+#include - #include - - namespace libcamera { -@@ -102,6 +103,9 @@ void eGL::syncOutput() - * \brief Create a DMA-BUF backed 2D texture - * \param[in,out] eglImage EGL image to associate with the DMA-BUF - * \param[in] fd DMA-BUF file descriptor -+ * \param[in] drm_format the DRM fourcc -+ * \param[in] width the buffer width -+ * \param[in] height the buffer height - * \param[in] output If true, create framebuffer for render target - * - * Internal implementation for creating DMA-BUF textures. Creates an EGL -@@ -110,15 +114,15 @@ void eGL::syncOutput() - * - * \return 0 on success, or -ENODEV on failure - */ --int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) -+int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, uint32_t drm_format, uint32_t width, uint32_t height, bool output) - { - ASSERT(tid_ == Thread::currentId()); - - // clang-format off - EGLint image_attrs[] = { -- EGL_WIDTH, (EGLint)eglImage.width_, -- EGL_HEIGHT, (EGLint)eglImage.height_, -- EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, -+ EGL_WIDTH, (EGLint)width, -+ EGL_HEIGHT, (EGLint)height, -+ EGL_LINUX_DRM_FOURCC_EXT, (EGLint)drm_format, - EGL_DMA_BUF_PLANE0_FD_EXT, fd, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, - EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)eglImage.stride_, -@@ -133,7 +137,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) - NULL, image_attrs); - - if (image == EGL_NO_IMAGE_KHR) { -- LOG(eGL, Error) << "eglCreateImageKHR fail"; -+ LOG(eGL, Debug) << "eglCreateImageKHR fail"; - return -ENODEV; - } - -@@ -172,6 +176,9 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) - * \brief Create an input DMA-BUF backed texture - * \param[in,out] eglImage EGL image to associate with the DMA-BUF - * \param[in] fd DMA-BUF file descriptor -+ * \param[in] format the GL format -+ * \param[in] width the buffer width -+ * \param[in] height the buffer height - * - * Creates an EGL image from a DMA-BUF file descriptor and binds it to - * a 2D texture for use as an input texture in shaders. The texture is -@@ -179,11 +186,25 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) - * - * \return 0 on success, or -ENODEV on failure - */ --int eGL::createInputDMABufTexture2D(eGLImage &eglImage, int fd) -+int eGL::createInputDMABufTexture2D(eGLImage &eglImage, int fd, GLint format, uint32_t width, uint32_t height) - { -+ EGLint drm_format; -+ - ASSERT(tid_ == Thread::currentId()); - -- return createDMABufTexture2D(eglImage, fd, false); -+ switch (format) { -+ case GL_LUMINANCE: -+ drm_format = DRM_FORMAT_R8; -+ break; -+ case GL_RG: -+ drm_format = DRM_FORMAT_RG88; -+ break; -+ default: -+ LOG(eGL, Error) << "unhandled GL format"; -+ return -ENODEV; -+ } -+ -+ return createDMABufTexture2D(eglImage, fd, drm_format, width, height, false); - } - - /** -@@ -202,7 +223,7 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) - { - ASSERT(tid_ == Thread::currentId()); - -- return createDMABufTexture2D(eglImage, fd, true); -+ return createDMABufTexture2D(eglImage, fd, DRM_FORMAT_ARGB8888, eglImage.width_, eglImage.height_, true); - } - - /** -diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp -index 8f0c229fd..f4fc2a6f9 100644 ---- a/src/libcamera/software_isp/debayer_egl.cpp -+++ b/src/libcamera/software_isp/debayer_egl.cpp -@@ -495,13 +495,22 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) - return; - } - --int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams ¶ms) -+int DebayerEGL::debayerGPU(FrameBuffer *input, int out_fd, const DebayerParams ¶ms) - { - /* eGL context switch */ - egl_.makeCurrent(); - - /* Create a standard texture input */ -- egl_.createTexture2D(*eglImageBayerIn_, glFormat_, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data()); -+ if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get(), glFormat_, inputConfig_.stride / bytesPerPixel_, height_) != 0) { -+ MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); -+ if (!in.isValid()) { -+ LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; -+ return -ENODEV; -+ } -+ -+ LOG(Debayer, Debug) << "Importing input buffer with DMABuf import failed, falling back to upload"; -+ egl_.createTexture2D(*eglImageBayerIn_, glFormat_, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data()); -+ } - - /* Generate the output render framebuffer as render to texture */ - egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd); -@@ -536,13 +545,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output - 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; -- } -- -- if (debayerGPU(in, output->planes()[0].fd.get(), params)) { -+ if (debayerGPU(input, output->planes()[0].fd.get(), params)) { - LOG(Debayer, Error) << "debayerGPU failed"; - goto error; - } -diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h -index fcd281f4c..5a1e4dfe3 100644 ---- a/src/libcamera/software_isp/debayer_egl.h -+++ b/src/libcamera/software_isp/debayer_egl.h -@@ -66,7 +66,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, int out_fd, const DebayerParams ¶ms); - - /* Shader program identifiers */ - GLuint vertexShaderId_ = 0; --- -2.54.0 - diff --git a/temp/libcamera/0003-egl-Add-GL-format-parameter-to-eGLImage-constructor.patch b/temp/libcamera/0003-egl-Add-GL-format-parameter-to-eGLImage-constructor.patch new file mode 100644 index 000000000..e427ee917 --- /dev/null +++ b/temp/libcamera/0003-egl-Add-GL-format-parameter-to-eGLImage-constructor.patch @@ -0,0 +1,122 @@ +From 7d7f39be4c7583a7f936cd77c7a4f4822f407b06 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Wed, 27 May 2026 10:15:30 +0200 +Subject: [PATCH 03/13] egl: Add GL format parameter to eGLImage constructor + +In preparation for the following commits. This requires a minor +reordering in DebayerEGL::start() as the value for the input texture is +only known after initBayerShaders(). + +Signed-off-by: Robert Mader +Reviewed-by: Bryan O'Donoghue +Signed-off-by: Kieran Bingham +(cherry picked from commit 6e23162ddcae7fdeb8f41a054dda2e8c19300d98) +--- + include/libcamera/internal/egl.h | 6 ++++-- + src/libcamera/egl.cpp | 22 +++++++++++++++++++++- + src/libcamera/software_isp/debayer_egl.cpp | 10 +++++----- + 3 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h +index 0ec8ea6ec..825240dbb 100644 +--- a/include/libcamera/internal/egl.h ++++ b/include/libcamera/internal/egl.h +@@ -51,14 +51,15 @@ class eGLImage + public: + /** + * \brief Construct an eGLImage with explicit stride ++ * \param[in] format Image GL format + * \param[in] width Image width in pixels + * \param[in] height Image height in pixels + * \param[in] stride Row stride in bytes + * \param[in] texture_unit OpenGL texture unit + * \param[in] texture_unit_uniform_id Shader uniform ID + */ +- eGLImage(uint32_t width, uint32_t height, uint32_t stride, GLenum texture_unit, uint32_t texture_unit_uniform_id) +- : width_(width), height_(height), stride_(stride), ++ eGLImage(GLint format, uint32_t width, uint32_t height, uint32_t stride, GLenum texture_unit, uint32_t texture_unit_uniform_id) ++ : format_(format), width_(width), height_(height), stride_(stride), + framesize_(stride * height), + texture_unit_uniform_id_(texture_unit_uniform_id), + texture_unit_(texture_unit) +@@ -79,6 +80,7 @@ public: + glDeleteTextures(1, &texture_); + } + ++ GLint format_; /**< Image GL format */ + uint32_t width_; /**< Image width in pixels */ + uint32_t height_; /**< Image height in pixels */ + uint32_t stride_; /**< Row stride in bytes */ +diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp +index 0ababa361..882bfa656 100644 +--- a/src/libcamera/egl.cpp ++++ b/src/libcamera/egl.cpp +@@ -21,6 +21,8 @@ + + #include + ++#include ++ + namespace libcamera { + + LOG_DEFINE_CATEGORY(eGL) +@@ -125,13 +127,31 @@ void eGL::flushOutput() + */ + int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) + { ++ EGLint drm_format; ++ + ASSERT(tid_ == Thread::currentId()); + ++ switch (eglImage.format_) { ++ case GL_RED: ++ case GL_LUMINANCE: ++ drm_format = DRM_FORMAT_R8; ++ break; ++ case GL_RG: ++ drm_format = DRM_FORMAT_RG88; ++ break; ++ case GL_RGBA: ++ drm_format = DRM_FORMAT_ARGB8888; ++ break; ++ default: ++ LOG(eGL, Error) << "unhandled GL format"; ++ return -ENODEV; ++ } ++ + // clang-format off + EGLint image_attrs[] = { + EGL_WIDTH, (EGLint)eglImage.width_, + EGL_HEIGHT, (EGLint)eglImage.height_, +- EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, ++ EGL_LINUX_DRM_FOURCC_EXT, drm_format, + EGL_DMA_BUF_PLANE0_FD_EXT, fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_DMA_BUF_PLANE0_PITCH_EXT, (EGLint)eglImage.stride_, +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index dd6b64be2..741d9d6f1 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -578,14 +578,14 @@ int DebayerEGL::start() + + LOG(Debayer, Debug) << "Available fragment shader texture units " << maxTextureImageUnits; + ++ if (initBayerShaders(inputPixelFormat_, outputPixelFormat_)) ++ return -EINVAL; ++ + /* Raw bayer input as texture */ +- eglImageBayerIn_ = std::make_unique(width_, height_, inputConfig_.stride, GL_TEXTURE0, 0); ++ eglImageBayerIn_ = std::make_unique(glFormat_, width_, height_, inputConfig_.stride, GL_TEXTURE0, 0); + + /* Texture we will render to */ +- eglImageBayerOut_ = std::make_unique(outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); +- +- if (initBayerShaders(inputPixelFormat_, outputPixelFormat_)) +- return -EINVAL; ++ eglImageBayerOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); + + return 0; + } +-- +2.54.0 + diff --git a/temp/libcamera/0004-egl-Remove-some-parameters-from-createTexture2D.patch b/temp/libcamera/0004-egl-Remove-some-parameters-from-createTexture2D.patch new file mode 100644 index 000000000..94c3929e6 --- /dev/null +++ b/temp/libcamera/0004-egl-Remove-some-parameters-from-createTexture2D.patch @@ -0,0 +1,92 @@ +From 97baff1439fe171fe80b081a021af71fb7617876 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Wed, 27 May 2026 10:15:31 +0200 +Subject: [PATCH 04/13] egl: Remove some parameters from createTexture2D() + +And use the values set in the constructor instead, bringing the +function in line with createInputDMABufTexture2D() and +createOutputDMABufTexture2D(). + +Adopt the value passed into the constructor accordingly, which +previously was never used. + +Signed-off-by: Robert Mader +Reviewed-by: Bryan O'Donoghue +Signed-off-by: Kieran Bingham +(cherry picked from commit fb312741ed936c69d6a773323a2e76d8e645c077) +--- + include/libcamera/internal/egl.h | 2 +- + src/libcamera/egl.cpp | 7 ++----- + src/libcamera/software_isp/debayer_egl.cpp | 4 ++-- + 3 files changed, 5 insertions(+), 8 deletions(-) + +diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h +index 825240dbb..bcf09b475 100644 +--- a/include/libcamera/internal/egl.h ++++ b/include/libcamera/internal/egl.h +@@ -105,7 +105,7 @@ public: + + int createInputDMABufTexture2D(eGLImage &eglImage, int fd); + int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); +- void createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint32_t height, void *data); ++ void createTexture2D(eGLImage &eglImage, void *data); + + void pushEnv(std::vector &shaderEnv, const char *str); + void makeCurrent(); +diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp +index 882bfa656..789ffe2c1 100644 +--- a/src/libcamera/egl.cpp ++++ b/src/libcamera/egl.cpp +@@ -241,9 +241,6 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) + /** + * \brief Create a 2D texture from a memory buffer + * \param[in,out] eglImage EGL image to associate with the texture +- * \param[in] format OpenGL internal format (e.g., GL_RGB, GL_RGBA) +- * \param[in] width Texture width in pixels +- * \param[in] height Texture height in pixels + * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture + * + * Creates a 2D texture from a CPU-accessible memory buffer. The texture +@@ -251,7 +248,7 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) + * is useful for uploading static data like lookup tables or uniform color + * matrices to the GPU. + */ +-void eGL::createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint32_t height, void *data) ++void eGL::createTexture2D(eGLImage &eglImage, void *data) + { + ASSERT(tid_ == Thread::currentId()); + +@@ -259,7 +256,7 @@ void eGL::createTexture2D(eGLImage &eglImage, GLint format, uint32_t width, uint + glBindTexture(GL_TEXTURE_2D, eglImage.texture_); + + // Generate texture, bind, associate image to texture, configure, unbind +- glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); ++ glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data); + + // Nearest filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index 741d9d6f1..3606ec6eb 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -501,7 +501,7 @@ int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParam + egl_.makeCurrent(); + + /* Create a standard texture input */ +- egl_.createTexture2D(*eglImageBayerIn_, glFormat_, inputConfig_.stride / bytesPerPixel_, height_, in.planes()[0].data()); ++ egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); + + /* Generate the output render framebuffer as render to texture */ + egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd); +@@ -582,7 +582,7 @@ int DebayerEGL::start() + return -EINVAL; + + /* Raw bayer input as texture */ +- eglImageBayerIn_ = std::make_unique(glFormat_, width_, height_, inputConfig_.stride, GL_TEXTURE0, 0); ++ eglImageBayerIn_ = std::make_unique(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0); + + /* Texture we will render to */ + eglImageBayerOut_ = std::make_unique(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1); +-- +2.54.0 + diff --git a/temp/libcamera/0005-egl-eGLImage-Add-flag-to-remember-dmabuf-import-fail.patch b/temp/libcamera/0005-egl-eGLImage-Add-flag-to-remember-dmabuf-import-fail.patch new file mode 100644 index 000000000..a6f08a2f4 --- /dev/null +++ b/temp/libcamera/0005-egl-eGLImage-Add-flag-to-remember-dmabuf-import-fail.patch @@ -0,0 +1,48 @@ +From 3f83705c45cfc34d508030194117207306feb850 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Wed, 27 May 2026 10:15:32 +0200 +Subject: [PATCH 05/13] egl: eGLImage: Add flag to remember dmabuf import fails + +In preparation of a following commit where we will start trying dmabuf +import for input buffers. +Also turn down error log in order to avoid flodding logs going +forward. + +Signed-off-by: Robert Mader +Reviewed-by: Bryan O'Donoghue +Signed-off-by: Kieran Bingham +(cherry picked from commit 7b5f651f5200df67f8f0cb4331d051711913de6a) +--- + include/libcamera/internal/egl.h | 1 + + src/libcamera/egl.cpp | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h +index bcf09b475..57f90d93f 100644 +--- a/include/libcamera/internal/egl.h ++++ b/include/libcamera/internal/egl.h +@@ -90,6 +90,7 @@ public: + GLenum texture_unit_; /**< Texture unit associated with this image eg (GL_TEXTURE0) */ + GLuint texture_; /**< OpenGL texture object ID */ + GLuint fbo_; /**< OpenGL frame buffer object ID */ ++ bool dmabuf_import_failed_ = false; /**< Previous image import failed */ + + private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(eGLImage) +diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp +index 789ffe2c1..7689d7983 100644 +--- a/src/libcamera/egl.cpp ++++ b/src/libcamera/egl.cpp +@@ -166,7 +166,8 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) + NULL, image_attrs); + + if (image == EGL_NO_IMAGE_KHR) { +- LOG(eGL, Error) << "eglCreateImageKHR fail"; ++ LOG(eGL, Debug) << "eglCreateImageKHR fail"; ++ eglImage.dmabuf_import_failed_ = true; + return -ENODEV; + } + +-- +2.54.0 + diff --git a/temp/libcamera/0006-libcamera-swstats_cpu-Take-MappedFrameBuffer-in-proc.patch b/temp/libcamera/0006-libcamera-swstats_cpu-Take-MappedFrameBuffer-in-proc.patch new file mode 100644 index 000000000..824ce1579 --- /dev/null +++ b/temp/libcamera/0006-libcamera-swstats_cpu-Take-MappedFrameBuffer-in-proc.patch @@ -0,0 +1,83 @@ +From 1e02c409a29c5c32360a4e57e57d995321496a9f Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Wed, 27 May 2026 10:15:33 +0200 +Subject: [PATCH 06/13] libcamera: swstats_cpu: Take MappedFrameBuffer in + processFrame() + +As the only current user - DebayerEGL::process() - already has the buffer +mapped. Currently this shouldn't impact performance as the kernel should +already avoid remapping the dmabuf - i.e. we implicitly benefit from the +fact that the mentioned function holds its mapping during the runtime of +processFrame(). In a following commit DebayerEGL::process() will change +in a way that would make keeping the mapping counter-intuitive. Thus +this change ensures we'll not accidentally start mapping the buffer +twice per frame. + +Signed-off-by: Robert Mader +Reviewed-by: Kieran Bingham +Signed-off-by: Kieran Bingham +(cherry picked from commit a34ee2274e0ea66757b012e104520405b915e058) +--- + include/libcamera/internal/software_isp/swstats_cpu.h | 2 +- + src/libcamera/software_isp/debayer_egl.cpp | 2 +- + src/libcamera/software_isp/swstats_cpu.cpp | 11 ++--------- + 3 files changed, 4 insertions(+), 11 deletions(-) + +diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h +index 802370bdb..3faa040b8 100644 +--- a/include/libcamera/internal/software_isp/swstats_cpu.h ++++ b/include/libcamera/internal/software_isp/swstats_cpu.h +@@ -56,7 +56,7 @@ public: + void setWindow(const Rectangle &window); + void startFrame(uint32_t frame); + void finishFrame(uint32_t frame, uint32_t bufferId); +- void processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input); ++ void processFrame(uint32_t frame, uint32_t bufferId, MappedFrameBuffer &input); + + void processLine0(uint32_t frame, unsigned int y, const uint8_t *src[], unsigned int statsBufferIndex = 0) + { +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index 3606ec6eb..067333c03 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -550,7 +550,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output + metadata.planes()[0].bytesused = output->planes()[0].length; + + /* Calculate stats for the whole frame */ +- stats_->processFrame(frame, 0, input); ++ stats_->processFrame(frame, 0, in); + dmaSyncers.clear(); + + egl_.syncOutput(); +diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp +index 5366e019f..60fcebc40 100644 +--- a/src/libcamera/software_isp/swstats_cpu.cpp ++++ b/src/libcamera/software_isp/swstats_cpu.cpp +@@ -537,7 +537,7 @@ void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in) + * + * This may only be called after a successful setWindow() call. + */ +-void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input) ++void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, MappedFrameBuffer &input) + { + if (frame % kStatPerNumFrames) { + finishFrame(frame, bufferId); +@@ -546,14 +546,7 @@ void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *in + + bench_.startFrame(); + startFrame(frame); +- +- MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); +- if (!in.isValid()) { +- LOG(SwStatsCpu, Error) << "mmap-ing buffer(s) failed"; +- return; +- } +- +- (this->*processFrame_)(in); ++ (this->*processFrame_)(input); + finishFrame(frame, bufferId); + bench_.finishFrame(); + } +-- +2.54.0 + diff --git a/temp/libcamera/0007-debayer_egl-Implement-dmabuf-import-for-input-buffer.patch b/temp/libcamera/0007-debayer_egl-Implement-dmabuf-import-for-input-buffer.patch new file mode 100644 index 000000000..d83ffe67d --- /dev/null +++ b/temp/libcamera/0007-debayer_egl-Implement-dmabuf-import-for-input-buffer.patch @@ -0,0 +1,210 @@ +From 7f354e1d4fa942a7f79f1d34c0b8b2bc86a4c1c5 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Wed, 27 May 2026 10:15:34 +0200 +Subject: [PATCH 07/13] debayer_egl: Implement dmabuf import for input buffers + +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. + +Note that passing around MappedFrameBuffer and DmaSyncer variables ensures +we don't do unnecessary mappings and dmabuf syncs. + +Below are some benchmark results. All where done using postmarketOS edge +with updates from 21th May 2026 (Mesa 26.1.1). The mentioned pipelines +where run five times each, with the mean value included here, which should +be quite representive as the variance was rather small. All devices +where using the powersave governor. + +- FairPhone 5 + +-- Back camera +cam -c /base/soc@0/cci@ac4a000/i2c-bus@1/camera@29 -s width=1920,height=1080 --capture=60 +Before: 14027 us/frame +After: 12122 us/frame + +- OnePlus 6 + +-- Back camera (imx519) +cam -c /base/soc@0/cci@ac4a000/i2c-bus@0/camera@10 -s width=1920,height=1080 --capture=60 +Before: 30091 us/frame +After: 19878 us/frame + +- Librem 5 + +-- Back camera +cam -c /base/soc@0/bus@30800000/i2c@30a50000/camera@2d -s width=1280,height=720 --capture=60 +Before: 69092 us/frame +After: 41250 us/frame + +- PinePhone + +-- Front Camera +cam -c /base/i2c-csi/front-camera@3c -s width=1280,height=720 --capture=60 +Before: 173769 us/frame +After: 143274 us/frame + +-- Back camera +cam -c /base/i2c-csi/rear-camera@4c -s width=1280,height=720 --capture=60 +Before: 174833 us/frame +After: 144476 us/frame + +There is one case where performance regresses: + +- Pixel 3a + +-- Back camera +cam -c /base/soc@0/cci@ac4a000/i2c-bus@1/camera@1a -s width=1920,height=1080 --capture=60 +Before: 14257 us/frame +After: 15161 us/frame + +To my knowledge this is likely caused by bad sampling performance from +linear buffers. IMO this is a driver issue - if a copy to tiled format +makes sampling faster, drivers should do so implicitly (like e.g. v3d +already does). + +Signed-off-by: Robert Mader +Reviewed-by: Bryan O'Donoghue +Signed-off-by: Kieran Bingham +(cherry picked from commit 93f0db167a8dfb9bc58cb6bbcf91ef6a23462b16) +--- + src/libcamera/software_isp/debayer_egl.cpp | 58 ++++++++++++++++------ + src/libcamera/software_isp/debayer_egl.h | 2 +- + 2 files changed, 43 insertions(+), 17 deletions(-) + +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index 067333c03..e0f6dc6da 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -10,6 +10,7 @@ + #include "debayer_egl.h" + + #include ++#include + #include + #include + +@@ -495,16 +496,34 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) + return; + } + +-int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams ¶ms) ++int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *inMapped, std::optional *inDmaSyncer) + { ++ bool dmabuf_import_succeeded = false; ++ + /* 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 (!eglImageBayerIn_->dmabuf_import_failed_) { ++ if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) == 0) ++ dmabuf_import_succeeded = true; ++ else ++ LOG(Debayer, Info) << "Importing input buffer with DMABuf import failed, falling back to upload"; ++ } ++ ++ /* Otherwise create texture for input buffer via upload from CPU */ ++ if (!dmabuf_import_succeeded) { ++ inDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); ++ inMapped->emplace(input, MappedFrameBuffer::MapFlag::Read); ++ if (!inMapped->value().isValid()) { ++ LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; ++ return -ENODEV; ++ } ++ egl_.createTexture2D(*eglImageBayerIn_, inMapped->value().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_); +@@ -526,23 +545,16 @@ 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 inMapped; ++ std::optional inDmaSyncer; + +- if (debayerGPU(in, output->planes()[0].fd.get(), params)) { ++ if (debayerGPU(input, output, params, &inMapped, &inDmaSyncer)) { + LOG(Debayer, Error) << "debayerGPU failed"; + goto error; + } +@@ -550,8 +562,22 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output + metadata.planes()[0].bytesused = output->planes()[0].length; + + /* Calculate stats for the whole frame */ +- stats_->processFrame(frame, 0, in); +- dmaSyncers.clear(); ++ if (frame % SwStatsCpu::kStatPerNumFrames) { ++ stats_->finishFrame(frame, 0); ++ } else { ++ if (!inMapped) { ++ /* ++ * The buffer was directly imported into EGL and thus ++ * not mapped for texture upload. Do it now for the ++ * CPU-based stats calculation. ++ */ ++ assert(!inDmaSyncer); ++ inDmaSyncer.emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); ++ inMapped.emplace(input, MappedFrameBuffer::MapFlag::Read); ++ } ++ stats_->processFrame(frame, 0, inMapped.value()); ++ } ++ inDmaSyncer.reset(); + + egl_.syncOutput(); + bench_.finishFrame(); +diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h +index fcd281f4c..f2a127b0d 100644 +--- a/src/libcamera/software_isp/debayer_egl.h ++++ b/src/libcamera/software_isp/debayer_egl.h +@@ -66,7 +66,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, FrameBuffer *output, const DebayerParams ¶ms, std::optional *mappedInputBuffer, std::optional *inputBufferDmaSyncer); + + /* Shader program identifiers */ + GLuint vertexShaderId_ = 0; +-- +2.54.0 + diff --git a/temp/libcamera/0008-libcamera-software_isp-debayer_egl-Demote-unsupporte.patch b/temp/libcamera/0008-libcamera-software_isp-debayer_egl-Demote-unsupporte.patch new file mode 100644 index 000000000..8d8e6123d --- /dev/null +++ b/temp/libcamera/0008-libcamera-software_isp-debayer_egl-Demote-unsupporte.patch @@ -0,0 +1,54 @@ +From 4afcb102d3742f3223e35668e86d0845dedddca2 Mon Sep 17 00:00:00 2001 +From: Qi Hou +Date: Tue, 2 Jun 2026 10:26:01 +0900 +Subject: [PATCH 08/13] libcamera: software_isp: debayer_egl: Demote + unsupported format log to Info + +DebayerEGL::getInputConfig() logs at Error level when it encounters an +unsupported input format. This function is called during format +enumeration from the simple pipeline handler's tryPipeline(), which +iterates over all pixel formats reported by the video capture device, +including non-Bayer formats such as UYVY and YUYV. The caller already +handles the failure gracefully by checking the return value. Similarly, +DebayerEGL::getOutputConfig() logs at Error level for unsupported +output formats, but is called from strideAndFrameSize() which also +handles failures via the return value. + +Demote both log messages from Error to Info for consistency with +DebayerCpu, which uses Info level in getInputConfig() and +getOutputConfig() for the same situation. + +Signed-off-by: Qi Hou +Reviewed-by: Bryan O'Donoghue +Reviewed-by: Kieran Bingham +Signed-off-by: Kieran Bingham +(cherry picked from commit 2985ca6ac024ff89a077f088de49f7a69ab40d37) +--- + src/libcamera/software_isp/debayer_egl.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index e0f6dc6da..af21ede45 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -74,7 +74,7 @@ int DebayerEGL::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf + return 0; + } + +- LOG(Debayer, Error) ++ LOG(Debayer, Info) + << "Unsupported input format " << inputFormat; + + return -EINVAL; +@@ -88,7 +88,7 @@ int DebayerEGL::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c + return 0; + } + +- LOG(Debayer, Error) ++ LOG(Debayer, Info) + << "Unsupported output format " << outputFormat; + + return -EINVAL; +-- +2.54.0 + diff --git a/temp/libcamera/0009-software_isp-debayer_egl-Request-input-buffer-alignm.patch b/temp/libcamera/0009-software_isp-debayer_egl-Request-input-buffer-alignm.patch new file mode 100644 index 000000000..957ce098f --- /dev/null +++ b/temp/libcamera/0009-software_isp-debayer_egl-Request-input-buffer-alignm.patch @@ -0,0 +1,196 @@ +From 6fee511f290fd0e950e8064cba99204dc08ed552 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Wed, 10 Jun 2026 00:53:56 +0200 +Subject: [PATCH 09/13] software_isp: debayer_egl: Request input buffer + alignment of 256 bytes + +The most common reason dmabuf import with createInputDMABufTexture2D() +fails is that V4L2 drivers use stride alignments that are not sufficient +(too small) for GPUs, preventing the later from directly using input +buffers and forcing us to do relatively expensive uploads (i.e. copies) +of the buffer contents. + +Thus let's request a compatible stride alignment from the V4L2 driver, +which may or may not respect the value. From the v4l2_pix_format -> +bytesperline docs: +> Both applications and drivers can set this field to request padding +> bytes at the end of each line. Drivers however may ignore the value +> requested by the application, returning width times bytes per pixel +> or a larger value required by the hardware. That implies applications +> can just set this field to zero to get a reasonable default. + +The approach works as follows: +1. Before setting the input format, query into the debayer class for a + preferred stride based on the bayer format and width. For DebayerCpu + this returns 0, i.e. let the V4L2 driver decide, while for DebayerEGL + the "magic" stride alignment of 256 bytes is used, which is known + to work with all known/common GPUs and already used for output + buffers. Right now there doesn't exist any API to query the correct + value - in many cases it is 64 or 128 - however if e.g. a new EGL + extension will provide it in the future, we can easily implement it + in the new function. Alternatively a config value or env var could be + added there if the need arises. +2. Pass the calculated stride to V4L2VideoDevice::setFormat(), which + again sets it as the bytesperline value. +3. The V4L2 driver will update bytesperline with the value it actually + chose to use. Compare the requested and actual strides and log an info + message if the driver did not honor the request, hinting users at what + could be improved about the kernel driver. + +Signed-off-by: Robert Mader +Tested-by: Milan Zamazal # rpi4+imx219 +Reviewed-by: Kieran Bingham +Signed-off-by: Kieran Bingham +(cherry picked from commit ff5cb4f17b0b9989dd853b4d4320ddb2c59a9c0e) +--- + .../libcamera/internal/software_isp/software_isp.h | 1 + + src/libcamera/pipeline/simple/simple.cpp | 12 ++++++++++++ + src/libcamera/software_isp/debayer.cpp | 8 ++++++++ + src/libcamera/software_isp/debayer.h | 1 + + src/libcamera/software_isp/debayer_egl.cpp | 8 ++++++++ + src/libcamera/software_isp/debayer_egl.h | 1 + + src/libcamera/software_isp/software_isp.cpp | 13 +++++++++++++ + 7 files changed, 44 insertions(+) + +diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h +index 585e0d6d9..2a6fbe413 100644 +--- a/include/libcamera/internal/software_isp/software_isp.h ++++ b/include/libcamera/internal/software_isp/software_isp.h +@@ -62,6 +62,7 @@ public: + + std::tuple + strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); ++ uint32_t preferredInputStride(const PixelFormat &inputFormat, const Size &size); + + int configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, +diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp +index c6fe12d65..e26f438d9 100644 +--- a/src/libcamera/pipeline/simple/simple.cpp ++++ b/src/libcamera/pipeline/simple/simple.cpp +@@ -1542,6 +1542,11 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) + captureFormat.fourcc = videoFormat; + captureFormat.size = pipeConfig->captureSize; + ++ uint32_t requested_bpl = 0; ++ if (data->swIsp_) ++ requested_bpl = data->swIsp_->preferredInputStride(videoFormat.toPixelFormat(), pipeConfig->captureSize); ++ captureFormat.planes[0].bpl = requested_bpl; ++ + ret = video->setFormat(&captureFormat); + if (ret) + return ret; +@@ -1561,6 +1566,13 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) + return -EINVAL; + } + ++ if (requested_bpl && captureFormat.planes[0].bpl != requested_bpl) { ++ LOG(SimplePipeline, Info) ++ << "Input buffer stride ignored by the driver. " ++ << "Requested " << requested_bpl ++ << ", got " << captureFormat.planes[0].bpl; ++ } ++ + /* Configure the converter if needed. */ + std::vector> outputCfgs; + data->useConversion_ = config->needConversion(); +diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp +index 2d7abfb83..56446f55d 100644 +--- a/src/libcamera/software_isp/debayer.cpp ++++ b/src/libcamera/software_isp/debayer.cpp +@@ -103,6 +103,14 @@ Debayer::~Debayer() + * there is no valid output config + */ + ++/** ++ * \fn uint32_t Debayer::preferredInputStride(const PixelFormat &inputFormat, const Size &size) ++ * Get the preferred input stride in bytes for the given input format and size ++ * \param[in] inputFormat The input format ++ * \param[in] size The input size (width and height in pixels) ++ * \return The preferred input stride in bytes or 0 if there is no preference ++ */ ++ + /** + * \fn void Debayer::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params) + * \brief Process the bayer data into the requested format +diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h +index a2a17ec18..28f1b857b 100644 +--- a/src/libcamera/software_isp/debayer.h ++++ b/src/libcamera/software_isp/debayer.h +@@ -46,6 +46,7 @@ public: + + virtual std::tuple + strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0; ++ virtual uint32_t preferredInputStride([[maybe_unused]] const PixelFormat &inputFormat, [[maybe_unused]] const Size &size) { return 0; } + + virtual void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) = 0; + virtual int start() { return 0; } +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index af21ede45..264a9315d 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -17,6 +17,7 @@ + #include + + #include ++#include "libcamera/internal/formats.h" + + #include "../glsl_shaders.h" + +@@ -373,6 +374,12 @@ DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size + return std::make_tuple(stride, stride * size.height); + } + ++uint32_t DebayerEGL::preferredInputStride(const PixelFormat &inputFormat, const Size &size) ++{ ++ const PixelFormatInfo &info = PixelFormatInfo::info(inputFormat); ++ return info.stride(size.width, 0, 256); ++} ++ + void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) + { + /* +@@ -655,3 +662,4 @@ SizeRange DebayerEGL::sizes(PixelFormat inputFormat, const Size &inputSize) + } + + } /* namespace libcamera */ ++ +diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h +index f2a127b0d..c7cb009b6 100644 +--- a/src/libcamera/software_isp/debayer_egl.h ++++ b/src/libcamera/software_isp/debayer_egl.h +@@ -51,6 +51,7 @@ public: + + std::vector formats(PixelFormat input) override; + std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) override; ++ uint32_t preferredInputStride(const PixelFormat &inputFormat, const Size &size) override; + + void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) override; + int start() override; +diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp +index d227bd8e3..9c4a59f08 100644 +--- a/src/libcamera/software_isp/software_isp.cpp ++++ b/src/libcamera/software_isp/software_isp.cpp +@@ -253,6 +253,19 @@ SoftwareIsp::strideAndFrameSize(const PixelFormat &outputFormat, const Size &siz + return debayer_->strideAndFrameSize(outputFormat, size); + } + ++/** ++ * Get the preferred input stride in bytes for the given input format and size ++ * \param[in] inputFormat The input format ++ * \param[in] size The input size (width and height in pixels) ++ * \return The preferred input stride in bytes or 0 if there is no preference ++ */ ++uint32_t SoftwareIsp::preferredInputStride(const PixelFormat &inputFormat, const Size &size) ++{ ++ ASSERT(debayer_); ++ ++ return debayer_->preferredInputStride(inputFormat, size); ++} ++ + /** + * \brief Configure the SoftwareIsp object according to the passed in parameters + * \param[in] inputCfg The input configuration +-- +2.54.0 + diff --git a/temp/libcamera/0010-egl-Log-the-GL-driver.patch b/temp/libcamera/0010-egl-Log-the-GL-driver.patch new file mode 100644 index 000000000..51a3004b4 --- /dev/null +++ b/temp/libcamera/0010-egl-Log-the-GL-driver.patch @@ -0,0 +1,37 @@ +From 7faa71ddfaca43b76b25a0a34b255999b44bfe40 Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Tue, 16 Jun 2026 13:20:21 +0200 +Subject: [PATCH 10/13] egl: Log the GL-driver + +To make it easier to differentiate various drivers. Some examples from running on +a FairPhone5: + +INFO eGL egl.cpp:362 EGL: GL_RENDERER: FD643 +INFO eGL egl.cpp:362 EGL: GL_RENDERER: llvmpipe (LLVM 22.1.3, 128 bits) +INFO eGL egl.cpp:362 EGL: GL_RENDERER: zink Vulkan 1.3(Turnip Adreno (TM) 643 (MESA_TURNIP)) + +Signed-off-by: Robert Mader +Reviewed-by: Kieran Bingham +Tested-by: Jai Luthra +Reviewed-by: Jai Luthra +Signed-off-by: Kieran Bingham +(cherry picked from commit 51dbd82e5e008d65bce96821d88ed2f6ea6c8e67) +--- + src/libcamera/egl.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp +index 7689d7983..9318a1b43 100644 +--- a/src/libcamera/egl.cpp ++++ b/src/libcamera/egl.cpp +@@ -360,6 +360,7 @@ int eGL::initEGLContext() + + makeCurrent(); + ++ LOG(eGL, Info) << "EGL: GL_RENDERER: " << glGetString(GL_RENDERER); + LOG(eGL, Info) << "EGL: GL_VERSION: " << glGetString(GL_VERSION); + + return 0; +-- +2.54.0 + diff --git a/temp/libcamera/0011-software_isp-debayer_egl-Consider-border-for-scaling.patch b/temp/libcamera/0011-software_isp-debayer_egl-Consider-border-for-scaling.patch new file mode 100644 index 000000000..0cbb66e8c --- /dev/null +++ b/temp/libcamera/0011-software_isp-debayer_egl-Consider-border-for-scaling.patch @@ -0,0 +1,72 @@ +From dd5347b8d391e93a8a3ae3ded7168d5705619f4a Mon Sep 17 00:00:00 2001 +From: Robert Mader +Date: Mon, 15 Jun 2026 20:11:27 +0200 +Subject: [PATCH 11/13] software_isp: debayer_egl: Consider border for scaling + +The debayer algorithm produces a sligtly smaller output resolution +compared to the input one, using a border at the edges depending on the +pattern. This wasn't considered when scaling to the final output buffer +size, resulting in garbage pixels at the right - or in case or 90 degree +rotated sensors - the bottom of the image. + +Use the native (i.e. unscaled) output size instead - the maximum output +buffer size. + +While on it use outputSize_ for better readability and adopt the scaling +comment slightly. + +Fixes: f520b29fe9e6 ("libcamera: software_isp: debayer_egl: Add an eGL Debayer class") +Signed-off-by: Robert Mader +Reviewed-by: Milan Zamazal +Reviewed-by: Kieran Bingham +Signed-off-by: Kieran Bingham +(cherry picked from commit 425dd3955db8d77cb8a4c7a75e2d46a50c896879) +--- + src/libcamera/software_isp/debayer_egl.cpp | 10 ++++++---- + src/libcamera/software_isp/debayer_egl.h | 1 + + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp +index 264a9315d..5fd014d1d 100644 +--- a/src/libcamera/software_isp/debayer_egl.cpp ++++ b/src/libcamera/software_isp/debayer_egl.cpp +@@ -323,6 +323,7 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, + + outputPixelFormat_ = outputCfg.pixelFormat; + outputSize_ = outputCfg.size; ++ nativeOutputSize_ = outSizeRange.max; + + window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & + ~(inputConfig_.patternSize.width - 1); +@@ -394,11 +395,12 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) + 1.0f / (height_ - 1) }; + GLfloat Stride = (GLfloat)width_ / (shaderStridePixels_ / bytesPerPixel_); + /* +- * Scale input to output size, keeping the aspect ratio and preferring +- * cropping over black bars. ++ * Scale the output size from the native size the algorithm produces for ++ * the input size. Keep the aspect ratio and prefer cropping over black ++ * bars. + */ +- GLfloat scale = std::max((GLfloat)window_.width / width_, +- (GLfloat)window_.height / height_); ++ GLfloat scale = std::max((GLfloat)outputSize_.width / nativeOutputSize_.width, ++ (GLfloat)outputSize_.height / nativeOutputSize_.height); + GLfloat trans = -(1.0f - scale); + GLfloat projMatrix[] = { + scale, 0, 0, 0, +diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h +index c7cb009b6..ef8c49814 100644 +--- a/src/libcamera/software_isp/debayer_egl.h ++++ b/src/libcamera/software_isp/debayer_egl.h +@@ -103,6 +103,7 @@ private: + /* Contrast */ + GLint contrastExpUniformDataIn_; + ++ Size nativeOutputSize_; + Rectangle window_; + std::unique_ptr stats_; + eGL egl_; +-- +2.54.0 + diff --git a/temp/libcamera/0001-libcamera-simple-Enable-softISP-for-the-Pinephone.patch b/temp/libcamera/0012-libcamera-simple-Enable-softISP-for-the-Pinephone.patch similarity index 86% rename from temp/libcamera/0001-libcamera-simple-Enable-softISP-for-the-Pinephone.patch rename to temp/libcamera/0012-libcamera-simple-Enable-softISP-for-the-Pinephone.patch index cbf47428f..8074f77b0 100644 --- a/temp/libcamera/0001-libcamera-simple-Enable-softISP-for-the-Pinephone.patch +++ b/temp/libcamera/0012-libcamera-simple-Enable-softISP-for-the-Pinephone.patch @@ -1,7 +1,7 @@ -From ccbfcbaf782fc66fe4600902fb51f043f44bf105 Mon Sep 17 00:00:00 2001 +From afbbb6c818ed330a2239c0ebb78d63ffa775c341 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Wed, 1 May 2024 18:12:02 +0200 -Subject: [PATCH 1/3] libcamera: simple: Enable softISP for the Pinephone +Subject: [PATCH 12/13] libcamera: simple: Enable softISP for the Pinephone In theory the PP should be able to use the actual HW ISP, however in practice this does not work well yet - especially as the driver for the @@ -17,7 +17,7 @@ Signed-off-by: Robert Mader 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp -index c6fe12d65..89b86f59c 100644 +index e26f438d9..24538649c 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -264,7 +264,7 @@ static const SimplePipelineInfo supportedDevices[] = { diff --git a/temp/libcamera/0002-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch b/temp/libcamera/0013-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch similarity index 87% rename from temp/libcamera/0002-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch rename to temp/libcamera/0013-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch index ca8f2b1a3..fa5b0e82b 100644 --- a/temp/libcamera/0002-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch +++ b/temp/libcamera/0013-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch @@ -1,7 +1,8 @@ -From 00e2f3ed19756080d709bd86d46c3c27ec8cea80 Mon Sep 17 00:00:00 2001 +From c7efef9c313386d530ab6422c0677953f36a2478 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Mon, 6 May 2024 21:21:57 +0200 -Subject: [PATCH 2/3] libcamera: simple: Skip hwISP formats if swISP is active +Subject: [PATCH 13/13] libcamera: simple: Skip hwISP formats if swISP is + active On devices like the Pinephone libcamera will advertise support for formats provided by the HW ISP and the SW ISP at the same time. The @@ -15,7 +16,7 @@ Signed-off-by: Robert Mader 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp -index 89b86f59c..1daee387e 100644 +index 24538649c..b96b8b529 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -745,9 +745,7 @@ void SimpleCameraData::tryPipeline(unsigned int code, const Size &size) diff --git a/temp/libcamera/APKBUILD b/temp/libcamera/APKBUILD index 0bee68d07..3f2f59343 100644 --- a/temp/libcamera/APKBUILD +++ b/temp/libcamera/APKBUILD @@ -3,7 +3,7 @@ maintainer="Robert Mader " pkgname=libcamera _pkgver=0.7.1 pkgver=9999$_pkgver -pkgrel=0 +pkgrel=1 pkgdesc="Linux camera framework" url="https://libcamera.org/" arch="all" @@ -42,6 +42,7 @@ subpackages=" $pkgname-gstreamer $pkgname-v4l2 $pkgname-tools + py3-$pkgname-pyc:pyc py3-$pkgname:py3 " _tuning_files=" @@ -55,9 +56,19 @@ _tuning_files=" s5kjn1.yaml " source="https://gitlab.freedesktop.org/camera/libcamera/-/archive/v$_pkgver/libcamera-v$_pkgver.tar.gz - 0001-libcamera-simple-Enable-softISP-for-the-Pinephone.patch - 0002-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch - 0003-RFC-egl-Implement-DMABuf-import-for-input-buffers.patch + 0001-debayer_egl-Include-stats-computation-into-benchmark.patch + 0002-debayer_egl-Sync-output-buffers-after-processing-sta.patch + 0003-egl-Add-GL-format-parameter-to-eGLImage-constructor.patch + 0004-egl-Remove-some-parameters-from-createTexture2D.patch + 0005-egl-eGLImage-Add-flag-to-remember-dmabuf-import-fail.patch + 0006-libcamera-swstats_cpu-Take-MappedFrameBuffer-in-proc.patch + 0007-debayer_egl-Implement-dmabuf-import-for-input-buffer.patch + 0008-libcamera-software_isp-debayer_egl-Demote-unsupporte.patch + 0009-software_isp-debayer_egl-Request-input-buffer-alignm.patch + 0010-egl-Log-the-GL-driver.patch + 0011-software_isp-debayer_egl-Consider-border-for-scaling.patch + 0012-libcamera-simple-Enable-softISP-for-the-Pinephone.patch + 0013-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch qcam.desktop $_tuning_files " @@ -171,9 +182,19 @@ py3() { sha512sums=" 0e886021a3bbd668184b581248b9d89a8e909360a7f138237a2c03b41b477cb255bd6daf4932fdebf86c3410b4deccc4c5db93264ed0c6c9969076cdbae8a77b libcamera-v0.7.1.tar.gz -aa24b1caab3d0e6bca413ff149aafa5233ba8141c2585b1b55c655759dd663612091222135ec5add402e60bf53d58c307f3f3127385efaa11b6cef866e03906e 0001-libcamera-simple-Enable-softISP-for-the-Pinephone.patch -cd1559a70dabe8711bb2cc1a8c6dca114e9f5b83088000935845ad90e5d109e2b215f0810f709f5bf00dd76be76e937bad4db49a1c6662135ec1704809a9a62b 0002-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch -6bca235e430e7392f68c94742d1bc1cd19cffe12ac03c8890ffa27b756972df67f5a408f4c806149a6b4f52827881a73d14d7f6a00bab9d4692f5eb9b06478a5 0003-RFC-egl-Implement-DMABuf-import-for-input-buffers.patch +5e936a5041f30c35f120a437a1cec65ab1d2b3ac335500566c291c7891b9ba585e6b7e4d22c54870257d161d23ef8bc5d3a99a512193f47adf41d4ae1683247a 0001-debayer_egl-Include-stats-computation-into-benchmark.patch +a2b110357ca6b26b469e399fc49fb890efcd97ccc18c16bf715be2a2c9159c293e5f9a23d9bab97dc4a19777232340c008e5ef156699f4383fed67c6157e0e1d 0002-debayer_egl-Sync-output-buffers-after-processing-sta.patch +00792bac0ee7aba1c2abdb1152efa86a08a06a1729c2f7aec19e647b4799ad8cac3a61fb0fc92e87f2af7c776811265e4f391ac8466b8b8a327b10dd9fe8a4f1 0003-egl-Add-GL-format-parameter-to-eGLImage-constructor.patch +75c8adb06c23e791464cbdd8ad36607a5bc6d46fa25af7b395f628b933c2a5fbbe1c1896eb6f4cac521aef38a13b67b71659503d344fe728763d7012f78de4d4 0004-egl-Remove-some-parameters-from-createTexture2D.patch +2afb8080916e25be93b6313f7419364ef8d02616b2e3065733ef180ebadf8ae05412c3b9b03017db711ca4460cf1bbe8c240e6502ff3b8797d7c864b0852b7c2 0005-egl-eGLImage-Add-flag-to-remember-dmabuf-import-fail.patch +5eca6b23c73300948e743e56cb4632db774c860a580f242ba20f387353d00879f70067179eeedb1c1c2f240303af51dc63e40573fa2ef03ebca26bfce1e94c69 0006-libcamera-swstats_cpu-Take-MappedFrameBuffer-in-proc.patch +9fc710bc0e177dcd664b1c7773e8c96dcf8bdf64ababf3f357b95d6dda2e8127ff0ee76f3d11ad01942f5a70f85ed94b78c17ef30c5639bd1c1b2b17fcdf17a4 0007-debayer_egl-Implement-dmabuf-import-for-input-buffer.patch +df8bbbb4438821e8c61a812886f0266f54f10b4b4d490efb6564e30010b8b624671f4b257dbda34056e03b369041c1e39c75aac351ddad2c9a4b98113f3feb9b 0008-libcamera-software_isp-debayer_egl-Demote-unsupporte.patch +8b2b8323b44d9ad45fa73862b0d7287ad9eb5f36583fb1bcbbf01ca85e2117883fde034e3314cbcbc3a73504f08c6abbb00a7e54d97f5991b3570e4e3a20925c 0009-software_isp-debayer_egl-Request-input-buffer-alignm.patch +0cc8cb2da2a25f3c5daa4d644e05f3ba6d45717eaea9e3e19cf65ace4d0eba30df9f5c16b351a693c5db4d4c298f5c04e69aa70db1e4e11318b0bb914e90af06 0010-egl-Log-the-GL-driver.patch +ca6dacedbd76a629539d033c028018ab5b858fcc3194787ceeda6b560d4d20dbb9b684f859ac2e40d144a77bcb2cc211c47d639ac6053cfc80cffeff3c5392b8 0011-software_isp-debayer_egl-Consider-border-for-scaling.patch +709a610297f7d3191da404816841183094bf8deeca4f0abec63a59f0ae7b95d02b546bb6315932264f7a0a731f7e3b949eeb5d5078f7399f39b580d4ff11da66 0012-libcamera-simple-Enable-softISP-for-the-Pinephone.patch +4482204e7a5fea2b853b8030e45fac8716b9e3fc84a16f248b778b3f10a85d956698147f04a173956f3bbf4cfdc6c12879fd8f621bd0147ecb9b3b0d2ddc3d6b 0013-libcamera-simple-Skip-hwISP-formats-if-swISP-is-acti.patch 22167a4eceb6d1b40b0b7c45fdf116c71684f5340de7f767535cb8e160ad9d2ae0f00cb3d461f73a344520a48a4641cf46226841d78bee06bfbfd2a91337f754 qcam.desktop 2ee566653b17d565d2c0de67cbe6ebad25df5aac6051cad78e6bae52016fa2ca0247e964d735ac776b3e0bd447ead9c4fcb26cd7629228cdba3ceb91b46f378f hi846.yaml 2ee566653b17d565d2c0de67cbe6ebad25df5aac6051cad78e6bae52016fa2ca0247e964d735ac776b3e0bd447ead9c4fcb26cd7629228cdba3ceb91b46f378f imx355.yaml