[{"id":39465,"web_url":"https://patchwork.libcamera.org/comment/39465/","msgid":"<0d3d61f3-d999-444c-8dcd-cc92193b5886@collabora.com>","date":"2026-06-26T12:29:38","subject":"Re: [PATCH v3 8/8] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":140,"url":"https://patchwork.libcamera.org/api/people/140/","name":"Robert Mader","email":"robert.mader@collabora.com"},"content":"On 26.06.26 13:33, Bryan O'Donoghue wrote:\n> Implement a texture caching mechanism for both input and output frames and\n> for both types of input frame.\n>\n> The before/after on a Qualcomm x1e is:\n>\n> 9.737ms per frame\n> 5.691ms per frame\n>\n> The before/after on a Qualcomm sm8250 is:\n>\n> 21.710ms per frame\n> 17.336ms per frame\n>\n> for i in {1..20} do\n> cam -c /base/soc@0/cci@ac16000/i2c-bus@1/camera@10 -s width=1920,height=1080 --capture=60\n>\n> Interestingly there appears to be an absolute ~ 4.x ms per frame uplift as\n> opposed to what intuition might suggest a proportional.\n>\n> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>\n> ---\n>   src/libcamera/software_isp/debayer_egl.cpp | 87 +++++++++++++++++-----\n>   src/libcamera/software_isp/debayer_egl.h   | 10 ++-\n>   2 files changed, 75 insertions(+), 22 deletions(-)\n>\n> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n> index 53bb67c17..fc37f0b75 100644\n> --- a/src/libcamera/software_isp/debayer_egl.cpp\n> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n> @@ -355,6 +355,9 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,\n>   \t */\n>   \tstats_->setWindow(Rectangle(window_.size()));\n>   \n> +\tinputBufferCount_ = inputCfg.bufferCount;\n> +\toutputBufferCount_ = outputCfg.bufferCount;\n> +\n>   \treturn 0;\n>   }\n>   \n> @@ -514,34 +517,84 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara\n>   \treturn;\n>   }\n>   \n> -int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +eGLImage *DebayerEGL::getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n>   {\n> -\t/* eGL context switch */\n> -\tegl_.makeCurrent();\n> +\tauto [input_cache, cache_miss] = eglImageBayerIn_.try_emplace(input->planes()[0].fd.get());\n> +\tif (cache_miss) {\n> +\t\tif (eglImageBayerIn_.size() > inputBufferCount_) {\n> +\t\t\tLOG(Debayer, Error) << \"Input count \" << inputBufferCount_ << \" exhausted\";\n> +\t\t\treturn nullptr;\n> +\t\t}\n> +\t\tinput_cache->second = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_,\n> +\t\t\t\t\t\t\t\t height_, inputConfig_.stride, GL_TEXTURE0, 0);\n> +\t}\n> +\teGLImage *eglImageIn = input_cache->second.get();\n>   \n>   \t/* Try to create texture for input buffer via dmabuf import */\n> -\tif (use_dmabuf_) {\n> -\t\tif (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) {\n> +\tif (use_dmabuf_ && cache_miss) {\n> +\t\tif (egl_.createInputDMABufTexture2D(*eglImageIn, input->planes()[0].fd.get()) != 0) {\n>   \t\t\tuse_dmabuf_ = false;\n>   \t\t\tLOG(Debayer, Info) << \"Importing input buffer with DMABuf import failed, falling back to upload\";\n>   \t\t}\n>   \t}\n>   \n> -\t/* Otherwise create texture for input buffer via upload from CPU */\n> -\tif (!use_dmabuf_) {\n> +\tif (use_dmabuf_) {\n> +\t\t/* Cache hit using dmabuf activate and bind */\n> +\t\tif (!cache_miss)\n> +\t\t\tegl_.activateBindTexture(*eglImageIn);\n> +\t} else {\n> +\t\t/* Otherwise create texture for input buffer via upload from CPU */\n>   \t\tinDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read);\n>   \t\tinMapped->emplace(input, MappedFrameBuffer::MapFlag::Read);\n>   \t\tif (!inMapped->value().isValid()) {\n>   \t\t\tLOG(Debayer, Error) << \"mmap-ing buffer(s) failed\";\n> -\t\t\treturn -ENODEV;\n> +\t\t\treturn nullptr;\n>   \t\t}\n> -\t\tegl_.createTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data());\n> +\t\tif (cache_miss)\n> +\t\t\tegl_.createTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n> +\t\telse\n> +\t\t\tegl_.updateTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n>   \t}\n>   \n> -\t/* Generate the output render framebuffer as render to texture */\n> -\tegl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get());\n> +\treturn eglImageIn;\n> +}\n> +\n> +eGLImage *DebayerEGL::getCachedOutputFrameBuffer(FrameBuffer *output)\n> +{\n> +\tauto [output_cache, cache_miss] = eglImageBayerOut_.try_emplace(output->planes()[0].fd.get());\n> +\tif (cache_miss) {\n> +\t\tif (eglImageBayerOut_.size() > outputBufferCount_) {\n> +\t\t\tLOG(Debayer, Error) << \"Output buffer count \" << outputBufferCount_ << \" exhaustion\";\n> +\t\t\treturn nullptr;\n> +\t\t}\n> +\t\toutput_cache->second = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width,\n> +\t\t\t\t\t\t\t\t  outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);\n> +\t\tegl_.createOutputDMABufTexture2D(*output_cache->second, output->planes()[0].fd.get());\n> +\t}\nAnswering to my own question in the previous review: IIUC we indeed \ndon't need to call \"egl_.activateBindTexture(*eglImageBayerOut_);\" in \nthe \"else\" case here, it's apparently only required when setting up the \ntexture. Hope that's correct.\n> +\teGLImage *eglImageOut = output_cache->second.get();\n> +\n> +\treturn eglImageOut;\n> +}\n> +\n> +int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +{\n> +\teGLImage *eglImageIn;\n> +\teGLImage *eglImageOut;\n> +\n> +\t/* eGL context switch */\n> +\tegl_.makeCurrent();\n> +\n> +\teglImageIn = getCachedInputFrameBuffer(input, inMapped, inDmaSyncer);\n> +\tif (!eglImageIn)\n> +\t\treturn -ENOMEM;\n> +\n> +\teglImageOut = getCachedOutputFrameBuffer(output);\n> +\tif (!eglImageOut)\n> +\t\treturn -ENOMEM;\n> +\n> +\tegl_.attachTextureToFBO(*eglImageOut);\n> +\tsetShaderVariableValues(*eglImageIn, params);\n>   \n> -\tsetShaderVariableValues(*eglImageBayerIn_, params);\n>   \tglViewport(0, 0, width_, height_);\n>   \tglClear(GL_COLOR_BUFFER_BIT);\n>   \tglDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS);\n> @@ -623,19 +676,13 @@ int DebayerEGL::start()\n>   \tif (initBayerShaders(inputPixelFormat_, outputPixelFormat_))\n>   \t\treturn -EINVAL;\n>   \n> -\t/* Raw bayer input as texture */\n> -\teglImageBayerIn_ = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0);\n> -\n> -\t/* Texture we will render to */\n> -\teglImageBayerOut_ = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);\n> -\n>   \treturn 0;\n>   }\n>   \n>   void DebayerEGL::stop()\n>   {\n> -\teglImageBayerOut_.reset();\n> -\teglImageBayerIn_.reset();\n> +\teglImageBayerOut_.clear();\n> +\teglImageBayerIn_.clear();\nShould we also reset inputBufferCount_ and outputBufferCount_ here, just \nto ensure the state is clean and can't accidentally be used in the future?\n>   \n>   \tif (programId_)\n>   \t\tglDeleteProgram(programId_);\n> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n> index d8509e9f2..ddb3ef378 100644\n> --- a/src/libcamera/software_isp/debayer_egl.h\n> +++ b/src/libcamera/software_isp/debayer_egl.h\n> @@ -22,6 +22,7 @@\n>   #include \"libcamera/internal/mapped_framebuffer.h\"\n>   #include \"libcamera/internal/software_isp/benchmark.h\"\n>   #include \"libcamera/internal/software_isp/swstats_cpu.h\"\n> +#include \"libcamera/internal/v4l2_videodevice.h\"\nShould be removed again I think?\n>   \n>   #include <EGL/egl.h>\n>   #include <EGL/eglext.h>\n> @@ -70,14 +71,19 @@ private:\n>   \n>   \tbool use_dmabuf_;\n>   \n> +\teGLImage *getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer);\n> +\teGLImage *getCachedOutputFrameBuffer(FrameBuffer *output);\n> +\n>   \t/* Shader program identifiers */\n>   \tGLuint vertexShaderId_ = 0;\n>   \tGLuint fragmentShaderId_ = 0;\n>   \tGLuint programId_ = 0;\n>   \n>   \t/* Pointer to object representing input texture */\n> -\tstd::unique_ptr<eGLImage> eglImageBayerIn_;\n> -\tstd::unique_ptr<eGLImage> eglImageBayerOut_;\n> +\tstd::unordered_map<int, std::unique_ptr<eGLImage>> eglImageBayerIn_;\n> +\tstd::unordered_map<int, std::unique_ptr<eGLImage>> eglImageBayerOut_;\n> +\tunsigned int inputBufferCount_;\n> +\tunsigned int outputBufferCount_;\n>   \n>   \t/* Shader parameters */\n>   \tfloat firstRed_x_;\n\nThis approach LGTM - with the two minor commits addressed:\n\nReviewed-by: Robert Mader <robert.mader@collabora.com>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E8F3FBF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 26 Jun 2026 12:29:49 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 83D7865ED9;\n\tFri, 26 Jun 2026 14:29:49 +0200 (CEST)","from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com\n\t[136.143.188.12])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CE30A658FA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 26 Jun 2026 14:29:47 +0200 (CEST)","by mx.zohomail.com with SMTPS id 1782476981427927.1827261966066;\n\tFri, 26 Jun 2026 05:29:41 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=collabora.com\n\theader.i=robert.mader@collabora.com header.b=\"MyTTjC1r\"; \n\tdkim-atps=neutral","ARC-Seal":"i=1; a=rsa-sha256; t=1782476984; cv=none; \n\td=zohomail.com; s=zohoarc; \n\tb=iW0s44KI2d3rNMDOyrEQvSvL4dfDzN0/3ounWfNqwyCathoTnqyRUgWsuRX01zueHfR2ladfS25mraQukuEIGc9bcW1ZVNTZa6W09e5fNiZii/vZJfIxXNXl5xS5Mg870HyAFrmkc3DNUCWOgLSXXCfQa/oQfYvtTPSOJu57PXQ=","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; \n\ts=zohoarc; t=1782476984;\n\th=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To:Cc;\n\tbh=r7+NOgYRUEBj+DYL45Au35qN5AezOefW41NF5jFfpQs=; \n\tb=KgMxebDNX9KoUVwR9qe5RiN5A62UN8OyhG4WNXXuMZ9IpmZCk6DoUMISmZl1mD60QVMsroNG9Do+leLNGnrS5tSGRvecIkXyv8fKHtqT7sRCdIrqcCp5puixPv14ZK7ggo8NkUNnsHxC6rN46AIu8X/j5iNqmG5b8K1ayo1AMhw=","ARC-Authentication-Results":"i=1; mx.zohomail.com;\n\tdkim=pass  header.i=collabora.com;\n\tspf=pass  smtp.mailfrom=robert.mader@collabora.com;\n\tdmarc=pass header.from=<robert.mader@collabora.com>","DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782476984;\n\ts=zohomail; d=collabora.com; i=robert.mader@collabora.com;\n\th=Message-ID:Date:Date:MIME-Version:Subject:Subject:To:To:References:From:From:In-Reply-To:Content-Type:Content-Transfer-Encoding:Message-Id:Reply-To:Cc;\n\tbh=r7+NOgYRUEBj+DYL45Au35qN5AezOefW41NF5jFfpQs=;\n\tb=MyTTjC1riXxNdiMcn+afTL8LnvyJRaAsi+VAWpGAJnoBGlFMXF0aPEcOIEShfedx\n\tF0xphOY4XXEOXw9byXk0YSLO6OlC6LgUWyNObnq6VRH7Oq1CObNiych6CRC2WW/4hoN\n\tOx0sEjP3wkZRNBywOWYTllV2idoyR7Q5dk6h2a9Q=","Message-ID":"<0d3d61f3-d999-444c-8dcd-cc92193b5886@collabora.com>","Date":"Fri, 26 Jun 2026 14:29:38 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3 8/8] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","To":"libcamera-devel@lists.libcamera.org","References":"<20260626113325.3218045-1-bryan.odonoghue@linaro.org>\n\t<20260626113325.3218045-9-bryan.odonoghue@linaro.org>","Content-Language":"en-US, de-DE, en-GB","From":"Robert Mader <robert.mader@collabora.com>","In-Reply-To":"<20260626113325.3218045-9-bryan.odonoghue@linaro.org>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":39469,"web_url":"https://patchwork.libcamera.org/comment/39469/","msgid":"<26817e1b-6a2b-43b7-b577-d2d7d976f2b5@ideasonboard.com>","date":"2026-06-26T13:19:43","subject":"Re: [PATCH v3 8/8] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 06. 26. 13:33 keltezéssel, Bryan O'Donoghue írta:\n> Implement a texture caching mechanism for both input and output frames and\n> for both types of input frame.\n> \n> The before/after on a Qualcomm x1e is:\n> \n> 9.737ms per frame\n> 5.691ms per frame\n> \n> The before/after on a Qualcomm sm8250 is:\n> \n> 21.710ms per frame\n> 17.336ms per frame\n> \n> for i in {1..20} do\n> cam -c /base/soc@0/cci@ac16000/i2c-bus@1/camera@10 -s width=1920,height=1080 --capture=60\n> \n> Interestingly there appears to be an absolute ~ 4.x ms per frame uplift as\n> opposed to what intuition might suggest a proportional.\n> \n> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>\n> ---\n>   src/libcamera/software_isp/debayer_egl.cpp | 87 +++++++++++++++++-----\n>   src/libcamera/software_isp/debayer_egl.h   | 10 ++-\n>   2 files changed, 75 insertions(+), 22 deletions(-)\n> \n> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n> index 53bb67c17..fc37f0b75 100644\n> --- a/src/libcamera/software_isp/debayer_egl.cpp\n> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n> @@ -355,6 +355,9 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,\n>   \t */\n>   \tstats_->setWindow(Rectangle(window_.size()));\n> \n> +\tinputBufferCount_ = inputCfg.bufferCount;\n> +\toutputBufferCount_ = outputCfg.bufferCount;\n> +\n>   \treturn 0;\n>   }\n> \n> @@ -514,34 +517,84 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara\n>   \treturn;\n>   }\n> \n> -int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +eGLImage *DebayerEGL::getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n>   {\n> -\t/* eGL context switch */\n> -\tegl_.makeCurrent();\n> +\tauto [input_cache, cache_miss] = eglImageBayerIn_.try_emplace(input->planes()[0].fd.get());\n> +\tif (cache_miss) {\n> +\t\tif (eglImageBayerIn_.size() > inputBufferCount_) {\n> +\t\t\tLOG(Debayer, Error) << \"Input count \" << inputBufferCount_ << \" exhausted\";\n\n   eglImageBayerIn_.erase(input_cache);\n\notherwise the stale entry (nullptr) might cause issues later.\n\n\n> +\t\t\treturn nullptr;\n> +\t\t}\n> +\t\tinput_cache->second = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_,\n> +\t\t\t\t\t\t\t\t height_, inputConfig_.stride, GL_TEXTURE0, 0);\n> +\t}\n> +\teGLImage *eglImageIn = input_cache->second.get();\n> \n>   \t/* Try to create texture for input buffer via dmabuf import */\n> -\tif (use_dmabuf_) {\n> -\t\tif (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) {\n> +\tif (use_dmabuf_ && cache_miss) {\n> +\t\tif (egl_.createInputDMABufTexture2D(*eglImageIn, input->planes()[0].fd.get()) != 0) {\n>   \t\t\tuse_dmabuf_ = false;\n>   \t\t\tLOG(Debayer, Info) << \"Importing input buffer with DMABuf import failed, falling back to upload\";\n>   \t\t}\n>   \t}\n> \n> -\t/* Otherwise create texture for input buffer via upload from CPU */\n> -\tif (!use_dmabuf_) {\n> +\tif (use_dmabuf_) {\n> +\t\t/* Cache hit using dmabuf activate and bind */\n> +\t\tif (!cache_miss)\n> +\t\t\tegl_.activateBindTexture(*eglImageIn);\n> +\t} else {\n> +\t\t/* Otherwise create texture for input buffer via upload from CPU */\n>   \t\tinDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read);\n>   \t\tinMapped->emplace(input, MappedFrameBuffer::MapFlag::Read);\n>   \t\tif (!inMapped->value().isValid()) {\n>   \t\t\tLOG(Debayer, Error) << \"mmap-ing buffer(s) failed\";\n> -\t\t\treturn -ENODEV;\n> +\t\t\treturn nullptr;\n>   \t\t}\n> -\t\tegl_.createTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data());\n> +\t\tif (cache_miss)\n> +\t\t\tegl_.createTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n> +\t\telse\n> +\t\t\tegl_.updateTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n>   \t}\n> \n> -\t/* Generate the output render framebuffer as render to texture */\n> -\tegl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get());\n> +\treturn eglImageIn;\n> +}\n> +\n> +eGLImage *DebayerEGL::getCachedOutputFrameBuffer(FrameBuffer *output)\n> +{\n> +\tauto [output_cache, cache_miss] = eglImageBayerOut_.try_emplace(output->planes()[0].fd.get());\n> +\tif (cache_miss) {\n> +\t\tif (eglImageBayerOut_.size() > outputBufferCount_) {\n> +\t\t\tLOG(Debayer, Error) << \"Output buffer count \" << outputBufferCount_ << \" exhaustion\";\n\n   eglImageBayerOut_.erase(output_cache);\n\nfor the same reason as above.\n\n\n> +\t\t\treturn nullptr;\n> +\t\t}\n> +\t\toutput_cache->second = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width,\n> +\t\t\t\t\t\t\t\t  outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);\n> +\t\tegl_.createOutputDMABufTexture2D(*output_cache->second, output->planes()[0].fd.get());\n> +\t}\n> +\teGLImage *eglImageOut = output_cache->second.get();\n> +\n> +\treturn eglImageOut;\n\n   return output_cache->second.get();\n\n?\n\n\n> +}\n> +\n> +int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +{\n> +\teGLImage *eglImageIn;\n> +\teGLImage *eglImageOut;\n> +\n> +\t/* eGL context switch */\n> +\tegl_.makeCurrent();\n> +\n> +\teglImageIn = getCachedInputFrameBuffer(input, inMapped, inDmaSyncer);\n> +\tif (!eglImageIn)\n> +\t\treturn -ENOMEM;\n> +\n> +\teglImageOut = getCachedOutputFrameBuffer(output);\n> +\tif (!eglImageOut)\n> +\t\treturn -ENOMEM;\n> +\n> +\tegl_.attachTextureToFBO(*eglImageOut);\n> +\tsetShaderVariableValues(*eglImageIn, params);\n> \n> -\tsetShaderVariableValues(*eglImageBayerIn_, params);\n>   \tglViewport(0, 0, width_, height_);\n>   \tglClear(GL_COLOR_BUFFER_BIT);\n>   \tglDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS);\n> @@ -623,19 +676,13 @@ int DebayerEGL::start()\n>   \tif (initBayerShaders(inputPixelFormat_, outputPixelFormat_))\n>   \t\treturn -EINVAL;\n> \n> -\t/* Raw bayer input as texture */\n> -\teglImageBayerIn_ = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0);\n> -\n> -\t/* Texture we will render to */\n> -\teglImageBayerOut_ = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);\n> -\n>   \treturn 0;\n>   }\n> \n>   void DebayerEGL::stop()\n>   {\n> -\teglImageBayerOut_.reset();\n> -\teglImageBayerIn_.reset();\n> +\teglImageBayerOut_.clear();\n> +\teglImageBayerIn_.clear();\n> \n>   \tif (programId_)\n>   \t\tglDeleteProgram(programId_);\n> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n> index d8509e9f2..ddb3ef378 100644\n> --- a/src/libcamera/software_isp/debayer_egl.h\n> +++ b/src/libcamera/software_isp/debayer_egl.h\n> @@ -22,6 +22,7 @@\n>   #include \"libcamera/internal/mapped_framebuffer.h\"\n>   #include \"libcamera/internal/software_isp/benchmark.h\"\n>   #include \"libcamera/internal/software_isp/swstats_cpu.h\"\n> +#include \"libcamera/internal/v4l2_videodevice.h\"\n> \n>   #include <EGL/egl.h>\n>   #include <EGL/eglext.h>\n> @@ -70,14 +71,19 @@ private:\n> \n>   \tbool use_dmabuf_;\n> \n> +\teGLImage *getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer);\n> +\teGLImage *getCachedOutputFrameBuffer(FrameBuffer *output);\n> +\n>   \t/* Shader program identifiers */\n>   \tGLuint vertexShaderId_ = 0;\n>   \tGLuint fragmentShaderId_ = 0;\n>   \tGLuint programId_ = 0;\n> \n>   \t/* Pointer to object representing input texture */\n> -\tstd::unique_ptr<eGLImage> eglImageBayerIn_;\n> -\tstd::unique_ptr<eGLImage> eglImageBayerOut_;\n> +\tstd::unordered_map<int, std::unique_ptr<eGLImage>> eglImageBayerIn_;\n> +\tstd::unordered_map<int, std::unique_ptr<eGLImage>> eglImageBayerOut_;\n\nI think we should use `SharedFD` here to avoid any fd reuse issues. I have just\nrealized that `V4l2BufferCache` does not use `SharedFD` either. And I think\nthat is kind of an issue. Well, nowadays every user just uses `FrameBufferAllocator`\nwith long lived `FrameBuffer`s, but the libcamera api does not require anything\nlike that.\n\nMaybe this should be discussed more, what the exact schemantics should be, etc.\n\nIn any case, this should be an easy change, just needs this as well:\n\ndiff --git a/include/libcamera/base/shared_fd.h b/include/libcamera/base/shared_fd.h\nindex 61fe11c1d6..cec1f6036c 100644\n--- a/include/libcamera/base/shared_fd.h\n+++ b/include/libcamera/base/shared_fd.h\n@@ -7,6 +7,7 @@\n  \n  #pragma once\n  \n+#include <functional>\n  #include <memory>\n  \n  namespace libcamera {\n@@ -57,3 +58,11 @@ static inline bool operator!=(const SharedFD &lhs, const SharedFD &rhs)\n  }\n  \n  } /* namespace libcamera */\n+\n+template<>\n+struct std::hash<libcamera::SharedFD> : private std::hash<int> {\n+       auto operator()(const libcamera::SharedFD &x) const noexcept\n+       {\n+               return std::hash<int>::operator()(x.get());\n+       }\n+};\n\n\n> +\tunsigned int inputBufferCount_;\n> +\tunsigned int outputBufferCount_;\n\nSomething like `xyzBufferCacheMaxSize_` / `maxXyzBufferCacheSize_` is more to the point in my opinion.\n\n> \n>   \t/* Shader parameters */\n>   \tfloat firstRed_x_;\n> --\n> 2.54.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id A528ABF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 26 Jun 2026 13:19:49 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6B49A65EEB;\n\tFri, 26 Jun 2026 15:19:48 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 42D6165BB8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 26 Jun 2026 15:19:47 +0200 (CEST)","from [192.168.33.48] (185.221.143.75.nat.pool.zt.hu\n\t[185.221.143.75])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 0BD0F1E7;\n\tFri, 26 Jun 2026 15:19:05 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"W9U2sPqA\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1782479946;\n\tbh=dcwcAZOOhGCxqcWfCzYVATtl2Zxs95jgESoF5K1tUtM=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=W9U2sPqAiGXp6vc27ucbZp8tIZMuVF/dZkULN6J4+69vS/0EFNRfPmGGnBmszz76r\n\tfIWWtdZZZgtslAD+gA4i6rbDspDQndwo9DPUb4QH5ws5KA5QEslGRIJAMJc42kG+If\n\t/X/j9VgAXjCzA7FFB7oElEmBPDdExaGhrZN/fx3M=","Message-ID":"<26817e1b-6a2b-43b7-b577-d2d7d976f2b5@ideasonboard.com>","Date":"Fri, 26 Jun 2026 15:19:43 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3 8/8] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","To":"Bryan O'Donoghue <bryan.odonoghue@linaro.org>,\n\tlibcamera-devel@lists.libcamera.org","Cc":"pavel@ucw.cz","References":"<20260626113325.3218045-1-bryan.odonoghue@linaro.org>\n\t<C1il0DL1DM0f78HuOSrU9RDJeh9sTlidvAwtijMRGkRXlfxHlpKrKjeWVkNueFNM7YfWfA8wC5W51dJuUeiBDw==@protonmail.internalid>\n\t<20260626113325.3218045-9-bryan.odonoghue@linaro.org>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260626113325.3218045-9-bryan.odonoghue@linaro.org>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":39470,"web_url":"https://patchwork.libcamera.org/comment/39470/","msgid":"<994d46e4-eac1-4fa3-b9bc-042dbee618da@ideasonboard.com>","date":"2026-06-26T13:22:13","subject":"Re: [PATCH v3 8/8] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 06. 26. 15:19 keltezéssel, Barnabás Pőcze írta:\n> 2026. 06. 26. 13:33 keltezéssel, Bryan O'Donoghue írta:\n>> Implement a texture caching mechanism for both input and output frames and\n>> for both types of input frame.\n>>\n>> The before/after on a Qualcomm x1e is:\n>>\n>> 9.737ms per frame\n>> 5.691ms per frame\n>>\n>> The before/after on a Qualcomm sm8250 is:\n>>\n>> 21.710ms per frame\n>> 17.336ms per frame\n>>\n>> for i in {1..20} do\n>> cam -c /base/soc@0/cci@ac16000/i2c-bus@1/camera@10 -s width=1920,height=1080 --capture=60\n>>\n>> Interestingly there appears to be an absolute ~ 4.x ms per frame uplift as\n>> opposed to what intuition might suggest a proportional.\n>>\n>> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>\n>> ---\n>>    src/libcamera/software_isp/debayer_egl.cpp | 87 +++++++++++++++++-----\n>>    src/libcamera/software_isp/debayer_egl.h   | 10 ++-\n>>    2 files changed, 75 insertions(+), 22 deletions(-)\n>>\n>> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n>> index 53bb67c17..fc37f0b75 100644\n>> --- a/src/libcamera/software_isp/debayer_egl.cpp\n>> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n>> @@ -355,6 +355,9 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,\n> [...]\n>> +eGLImage *DebayerEGL::getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n>>    {\n>> -\t/* eGL context switch */\n>> -\tegl_.makeCurrent();\n>> +\tauto [input_cache, cache_miss] = eglImageBayerIn_.try_emplace(input->planes()[0].fd.get());\n>> +\tif (cache_miss) {\n>> +\t\tif (eglImageBayerIn_.size() > inputBufferCount_) {\n>> +\t\t\tLOG(Debayer, Error) << \"Input count \" << inputBufferCount_ << \" exhausted\";\n\nAnd I am not sure this should be an error, maybe \"debug\" at most.\n\n\n> \n>     eglImageBayerIn_.erase(input_cache);\n> \n> otherwise the stale entry (nullptr) might cause issues later.\n> \n> \n>> +\t\t\treturn nullptr;\n>> +\t\t}\n>> +\t\tinput_cache->second = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_,\n>> +\t\t\t\t\t\t\t\t height_, inputConfig_.stride, GL_TEXTURE0, 0);\n>> +\t}\n>> +\teGLImage *eglImageIn = input_cache->second.get();\n>>\n>>    \t/* Try to create texture for input buffer via dmabuf import */\n>> -\tif (use_dmabuf_) {\n>> -\t\tif (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) {\n>> +\tif (use_dmabuf_ && cache_miss) {\n>> +\t\tif (egl_.createInputDMABufTexture2D(*eglImageIn, input->planes()[0].fd.get()) != 0) {\n>>    \t\t\tuse_dmabuf_ = false;\n>>    \t\t\tLOG(Debayer, Info) << \"Importing input buffer with DMABuf import failed, falling back to upload\";\n>>    \t\t}\n>>    \t}\n>>\n>> -\t/* Otherwise create texture for input buffer via upload from CPU */\n>> -\tif (!use_dmabuf_) {\n>> +\tif (use_dmabuf_) {\n>> +\t\t/* Cache hit using dmabuf activate and bind */\n>> +\t\tif (!cache_miss)\n>> +\t\t\tegl_.activateBindTexture(*eglImageIn);\n>> +\t} else {\n>> +\t\t/* Otherwise create texture for input buffer via upload from CPU */\n>>    \t\tinDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read);\n>>    \t\tinMapped->emplace(input, MappedFrameBuffer::MapFlag::Read);\n>>    \t\tif (!inMapped->value().isValid()) {\n>>    \t\t\tLOG(Debayer, Error) << \"mmap-ing buffer(s) failed\";\n>> -\t\t\treturn -ENODEV;\n>> +\t\t\treturn nullptr;\n>>    \t\t}\n>> -\t\tegl_.createTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data());\n>> +\t\tif (cache_miss)\n>> +\t\t\tegl_.createTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n>> +\t\telse\n>> +\t\t\tegl_.updateTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n>>    \t}\n>>\n>> -\t/* Generate the output render framebuffer as render to texture */\n>> -\tegl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get());\n>> +\treturn eglImageIn;\n>> +}\n>> [...]","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 777F3BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 26 Jun 2026 13:22:21 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7916E65EF3;\n\tFri, 26 Jun 2026 15:22:20 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 150F865BB8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 26 Jun 2026 15:22:19 +0200 (CEST)","from [192.168.33.48] (185.221.143.75.nat.pool.zt.hu\n\t[185.221.143.75])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 816851E7;\n\tFri, 26 Jun 2026 15:21:37 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"TV11e7Dg\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1782480098;\n\tbh=f8MhNGGSB8azoHv1Ag3wIc0t6x+9IKahAeDc4vQB37c=;\n\th=Date:Subject:From:To:Cc:Reply-To:References:In-Reply-To:From;\n\tb=TV11e7DgS6Kc5vESNxh49yNG/dsQPL3t6q9Fbnun2CfTycQm26bU1AH6EeWh9Lk4O\n\tvGpWj6oRRT87S0ewLB35Mm1UQiNCE5A5LIrnVicqAdUQztv1OIFnCOoB2VCLQf9ePg\n\t2Zjyk9gnx4UKiSonKY4Yuo+f1QzJx7avBJvWzMNw=","Message-ID":"<994d46e4-eac1-4fa3-b9bc-042dbee618da@ideasonboard.com>","Date":"Fri, 26 Jun 2026 15:22:13 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3 8/8] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","To":"Bryan O'Donoghue <bryan.odonoghue@linaro.org>,\n\tlibcamera-devel@lists.libcamera.org","Cc":"pavel@ucw.cz","References":"<20260626113325.3218045-1-bryan.odonoghue@linaro.org>\n\t<C1il0DL1DM0f78HuOSrU9RDJeh9sTlidvAwtijMRGkRXlfxHlpKrKjeWVkNueFNM7YfWfA8wC5W51dJuUeiBDw==@protonmail.internalid>\n\t<20260626113325.3218045-9-bryan.odonoghue@linaro.org>\n\t<22gpS-p0fBZV2yM2XGmmihAZxdgeJL_W75DbidOef58niPoul3OF3Mu4Pw2BaKWIxwLoqul05gnv9ZwtlqOb5A==@protonmail.internalid>\n\t<26817e1b-6a2b-43b7-b577-d2d7d976f2b5@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<26817e1b-6a2b-43b7-b577-d2d7d976f2b5@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Reply-To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?=\n\t<barnabas.pocze@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":39473,"web_url":"https://patchwork.libcamera.org/comment/39473/","msgid":"<3e6adc06-f18f-4f68-9e66-af751e493247@linaro.org>","date":"2026-06-26T14:10:46","subject":"Re: [PATCH v3 8/8] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":175,"url":"https://patchwork.libcamera.org/api/people/175/","name":"Bryan O'Donoghue","email":"bryan.odonoghue@linaro.org"},"content":"On 26/06/2026 14:19, Barnabás Pőcze wrote:\n> diff --git a/include/libcamera/base/shared_fd.h b/include/libcamera/ \n> base/shared_fd.h\n> index 61fe11c1d6..cec1f6036c 100644\n> --- a/include/libcamera/base/shared_fd.h\n> +++ b/include/libcamera/base/shared_fd.h\n> @@ -7,6 +7,7 @@\n> \n>   #pragma once\n> \n> +#include <functional>\n>   #include <memory>\n> \n>   namespace libcamera {\n> @@ -57,3 +58,11 @@ static inline bool operator!=(const SharedFD &lhs, \n> const SharedFD &rhs)\n>   }\n> \n>   } /* namespace libcamera */\n> +\n> +template<>\n> +struct std::hash<libcamera::SharedFD> : private std::hash<int> {\n> +       auto operator()(const libcamera::SharedFD &x) const noexcept\n> +       {\n> +               return std::hash<int>::operator()(x.get());\n> +       }\n> +};\n\nDo you want to make that into a patch yourself or for me to pick it up \nfor you ?\n\n---\nbod","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 46C79C3264\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 26 Jun 2026 14:10:51 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2D67265EEF;\n\tFri, 26 Jun 2026 16:10:50 +0200 (CEST)","from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com\n\t[IPv6:2a00:1450:4864:20::62b])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1A3CA65BB8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 26 Jun 2026 16:10:49 +0200 (CEST)","by mail-ej1-x62b.google.com with SMTP id\n\ta640c23a62f3a-c122d85eae1so103836366b.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 26 Jun 2026 07:10:49 -0700 (PDT)","from [192.168.0.101] ([109.76.78.98])\n\tby smtp.gmail.com with ESMTPSA id\n\ta640c23a62f3a-c11fbe6a0f6sm330361666b.53.2026.06.26.07.10.47\n\t(version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n\tFri, 26 Jun 2026 07:10:47 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=linaro.org header.i=@linaro.org\n\theader.b=\"TKhM/Zb/\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=linaro.org; s=google; t=1782483048; x=1783087848;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:in-reply-to:content-language:from\n\t:references:cc:to:subject:user-agent:mime-version:date:message-id\n\t:from:to:cc:subject:date:message-id:reply-to;\n\tbh=HGm00QBGNAL26G1/ht4C/xe4MuE7bue2MBaXRvY1DWQ=;\n\tb=TKhM/Zb/Qf/l/t1834ePr0BKYSEKq/prAn4IOZYUXlCOtdW+OBtynf5b9RoGdqqWKg\n\t5FAq/F6PtQnWTwYJsWoq2/DJs8QG8bAh/breY2MxCTmiJrIByNHF5FJueH8pXPxcZHTZ\n\tXQS5ep1/ICnsPHkPhd3llmHndS/dYhGDzV/9vxpd+ynH/S6HT9nh8dhdUOkc+ftv1gcd\n\tv4dYz76ip8gYMJdZWD2YmI7iZLo2nwzARvxTQB1BI7mTVK89suYN6v3OsTGeVeYrpO/0\n\tEv3QMO3GnlU0+1JnxDnOE2lQubEGnMel045KBKJaGHKd2dltsXC2m3TkaF3g+ANOZeSd\n\tPKvA==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1782483048; x=1783087848;\n\th=content-transfer-encoding:in-reply-to:content-language:from\n\t:references:cc:to:subject:user-agent:mime-version:date:message-id\n\t:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=HGm00QBGNAL26G1/ht4C/xe4MuE7bue2MBaXRvY1DWQ=;\n\tb=TwERaIyjSwHyZEkxWd+8i1hh5U9JybIbPMAoWB/BDhe9EYP32IBLHnImxF7kEbzbmS\n\tZhvXyde9CoyehsK7UwsAkY7bknqM9OlLHDJI/4dARbIZDg4XC91n06hBWS7pUC9RXRNW\n\tO/dA7uJQK2QNU9smNxAE3wjIrpBVZlE/fEnypzFWKEOyf4dA6PVLMJzX3E1LjxoRNzsh\n\tPiO8+Q9by6xBhymyfR0tLVIzCavI4ECucGK76dmKZOBXnK9bxORaeUkDQlXSzDbfM57j\n\td7cFXNT4LYD2V2QGTpK7BNmm9PxaJqdBDNwVQCBpbSywPS4apybKcSwI46OspykXYxl0\n\t/SWw==","X-Forwarded-Encrypted":"i=1;\n\tAHgh+RpJbZAvsM0tzYo8lED5xP36uv5n4WB++8p2KdUSQiZbuSgIcH230zcZeu1CtHiEPeHnMSvE8vrS2//vdejwTlo=@lists.libcamera.org","X-Gm-Message-State":"AOJu0Yz+/aoPUq0Yk6xwHOv12tiq8GECVWQeOWicRAksXFTr6p2WcB9J\n\thSX7y3MsJ1TTcsuIPU0PiLODBOFyspYSjkH60zffVE7Zx5s1Ujeu2otUs2sQ39nqr4c=","X-Gm-Gg":"AfdE7cltJrY6t1qMdSpRQftoZGGlNC0A46SHUZJLEQlkYUdBbMM5uL5hEOstzow+VV1\n\tKdBs/odeQUvbgTISYz/2KhRCHLybM2WAXNJl5RKRbm1rdNsHYD+ZccP2N0VPyWaqDy2NV5r+ea3\n\tEAmOuQlB+bQakttox4Fza0vAH6mJT3HtE5tlWRULIKE/+RcXVMxFqppdNYKEZzFetemsg5ZQpsk\n\tk25GiT7nXWeOlVcoi63u8ZcOuPfwU1799blRkCIfobySyW/WgPLmm2QgLfRkP6cEkdnGDlSUwqk\n\tnMuzdTQVmCDbQnrgeHsP7jmrROKuOOw5GutL/tJAeYVVbgpEyVRxVc0qp7CeRhPREcJSIjRJhRF\n\tHH2p8aAYXrdv6Mwjr47y9OJvbzqyC0aGY9k/YO6cPaVndlzjRG61+n6YbaxnxWyr8902y3oGyBJ\n\tRy9EDP099v7O9zRPzcgaduNKao0hnhGCQ/6w==","X-Received":"by 2002:a17:906:eec1:b0:c0d:43b2:e8e7 with SMTP id\n\ta640c23a62f3a-c1205ee0e4bmr463118366b.35.1782483048202; \n\tFri, 26 Jun 2026 07:10:48 -0700 (PDT)","Message-ID":"<3e6adc06-f18f-4f68-9e66-af751e493247@linaro.org>","Date":"Fri, 26 Jun 2026 15:10:46 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3 8/8] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Cc":"pavel@ucw.cz","References":"<20260626113325.3218045-1-bryan.odonoghue@linaro.org>\n\t<C1il0DL1DM0f78HuOSrU9RDJeh9sTlidvAwtijMRGkRXlfxHlpKrKjeWVkNueFNM7YfWfA8wC5W51dJuUeiBDw==@protonmail.internalid>\n\t<20260626113325.3218045-9-bryan.odonoghue@linaro.org>\n\t<26817e1b-6a2b-43b7-b577-d2d7d976f2b5@ideasonboard.com>","From":"Bryan O'Donoghue <bryan.odonoghue@linaro.org>","Content-Language":"en-US","In-Reply-To":"<26817e1b-6a2b-43b7-b577-d2d7d976f2b5@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]