[{"id":39817,"web_url":"https://patchwork.libcamera.org/comment/39817/","msgid":"<f0ea0ed1-db25-4021-91c5-b274f744d41b@ideasonboard.com>","date":"2026-07-24T10:05:43","subject":"Re: [PATCH] libcamera: egl: Cache probed EGLDisplay to avoid\n\tredundant init/teardown","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 07. 24. 3:43 keltezéssel, qi.hou@oss.nxp.com írta:\n> From: Qi Hou <qi.hou@nxp.com>\n> \n> isAvailable() previously called probeDisplay() which ran eglBindAPI(),\n> eglGetPlatformDisplay() and eglInitialize(), then immediately terminated\n> the display with eglTerminate(). When SoftwareIsp subsequently called\n> initEGLContext(), probeDisplay() repeated a full initialisation sequence.\n> \n> Avoid this double init/teardown by caching the EGLDisplay handle inside\n> probeDisplay() using static parameters. The first call initialises EGL\n> and stores the result, all later calls return the cached handle\n> without reinitialising.\n> \n> isAvailable() is simplified to return probeDisplay() != EGL_NO_DISPLAY\n> and no longer calls eglTerminate(), because the cached display should\n> be live for reuse by initEGLContext().\n> ---\n>   src/libcamera/egl.cpp | 31 +++++++++++++++++--------------\n>   1 file changed, 17 insertions(+), 14 deletions(-)\n> \n> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp\n> index 7ec7a654d..f5200ee76 100644\n> --- a/src/libcamera/egl.cpp\n> +++ b/src/libcamera/egl.cpp\n> @@ -301,46 +301,49 @@ void eGL::createTexture2D(eGLImage &eglImage, void *data)\n>   \n>   EGLDisplay eGL::probeDisplay()\n>   {\n> -\tEGLDisplay display;\n> +\tstatic EGLDisplay cachedDisplay = EGL_NO_DISPLAY;\n> +\tstatic bool probed = false;\n\nI'm not a fan of adding more mutable global state. As an alternative:\n   * modify `eGL` to take the EGLDisplay in its constructor\n     and adjust `initEGLContext()` to not retrieve the display\n   * adjust `DebayerEGL` accordingly\n   * adjust `SoftwareISP` to call `probeDisplay()` and forward the result\n\nHere is a prototype of the idea:\n\ndiff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h\nindex 1e31d490bd..7ef1ca0d93 100644\n--- a/include/libcamera/internal/egl.h\n+++ b/include/libcamera/internal/egl.h\n@@ -99,11 +99,11 @@ private:\n  class eGL\n  {\n  public:\n-\teGL();\n+\teGL(EGLDisplay display);\n  \t~eGL();\n  \n  \tint initEGLContext();\n-\tstatic bool isAvailable();\n+\tstatic EGLDisplay probeDisplay();\n  \n  \tint createInputDMABufTexture2D(eGLImage &eglImage, int fd);\n  \tint createOutputDMABufTexture2D(eGLImage &eglImage, int fd);\n@@ -137,7 +137,6 @@ private:\n  \tEGLContext context_ = EGL_NO_CONTEXT;\n  \tEGLSurface surface_ = EGL_NO_SURFACE;\n  \n-\tstatic EGLDisplay probeDisplay();\n  \tint compileShader(int shaderType, GLuint &shaderId, Span<const unsigned char> shaderData,\n  \t\t\t  Span<const std::string> shaderEnv);\n  \ndiff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp\nindex 7ec7a654da..3d1a15493a 100644\n--- a/src/libcamera/egl.cpp\n+++ b/src/libcamera/egl.cpp\n@@ -64,12 +64,15 @@ LOG_DEFINE_CATEGORY(eGL)\n  \n  /**\n   * \\brief Construct an EGL helper\n+ * \\param[in] display The EGL display to use\n   *\n   * Creates an eGL instance with uninitialised context. Call initEGLContext()\n- * to set up the EGL display, context, and load extension functions.\n+ * to set up the EGL context, and load extension functions.\n   */\n-eGL::eGL()\n+eGL::eGL(EGLDisplay display)\n+\t: display_(display)\n  {\n+\tASSERT(display_ != EGL_NO_DISPLAY);\n  }\n  \n  /**\n@@ -299,6 +302,13 @@ void eGL::createTexture2D(eGLImage &eglImage, void *data)\n  \tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n  }\n  \n+/**\n+ * \\brief Try to create an EGL display for surfaceless rendering\n+ *\n+ * Tries to create an EGL display for surfaceless rendering.\n+ *\n+ * \\return A EGL display handle if successfull, otherwise \\a EGL_NO_DISPLAY\n+ */\n  EGLDisplay eGL::probeDisplay()\n  {\n  \tEGLDisplay display;\n@@ -325,24 +335,6 @@ EGLDisplay eGL::probeDisplay()\n  \treturn display;\n  }\n  \n-/**\n- * \\brief Probe whether EGL surfaceless rendering is available\n- *\n- * Checks if an EGL surfaceless display can be obtained and initialised.\n- * The display is immediately terminated so that no resources are leaked.\n- *\n- * \\return True if EGL surfaceless rendering is available, false otherwise\n- */\n-bool eGL::isAvailable()\n-{\n-\tEGLDisplay display = probeDisplay();\n-\tif (display == EGL_NO_DISPLAY)\n-\t\treturn false;\n-\n-\teglTerminate(display);\n-\treturn true;\n-}\n-\n  /**\n   * \\brief Update a 2D texture already created\n   * \\param[in,out] eglImage EGL image to associate with the texture\n@@ -403,12 +395,6 @@ int eGL::initEGLContext()\n  \tEGLint numConfigs;\n  \tEGLConfig config;\n  \n-\tdisplay_ = probeDisplay();\n-\tif (display_ == EGL_NO_DISPLAY) {\n-\t\tLOG(eGL, Error) << \"Unable to probe display\";\n-\t\tgoto fail;\n-\t}\n-\n  \tLOG(eGL, Info) << \"EGL: EGL_VERSION: \" << eglQueryString(display_, EGL_VERSION);\n  \tLOG(eGL, Info) << \"EGL: EGL_VENDOR: \" << eglQueryString(display_, EGL_VENDOR);\n  \tLOG(eGL, Info) << \"EGL: EGL_CLIENT_APIS: \" << eglQueryString(display_, EGL_CLIENT_APIS);\ndiff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\nindex dd20412194..20b478b1c3 100644\n--- a/src/libcamera/software_isp/debayer_egl.cpp\n+++ b/src/libcamera/software_isp/debayer_egl.cpp\n@@ -40,9 +40,10 @@ namespace libcamera {\n   * \\brief Construct a DebayerEGL object\n   * \\param[in] stats Statistics processing object\n   * \\param[in] cm The camera manager\n+ * \\param[in] display The EGL display to use\n   */\n-DebayerEGL::DebayerEGL(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm)\n-\t: Debayer(cm), stats_(std::move(stats))\n+DebayerEGL::DebayerEGL(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm, EGLDisplay display)\n+\t: Debayer(cm), stats_(std::move(stats)), egl_(display)\n  {\n  }\n  \ndiff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\nindex e613639f5c..30e51a4773 100644\n--- a/src/libcamera/software_isp/debayer_egl.h\n+++ b/src/libcamera/software_isp/debayer_egl.h\n@@ -40,7 +40,7 @@ class CameraManager;\n  class DebayerEGL : public Debayer\n  {\n  public:\n-\tDebayerEGL(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm);\n+\tDebayerEGL(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm, EGLDisplay display);\n  \t~DebayerEGL();\n  \n  \tint configure(const StreamConfiguration &inputCfg,\ndiff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\nindex c73a16ce0a..c7165771c6 100644\n--- a/src/libcamera/software_isp/software_isp.cpp\n+++ b/src/libcamera/software_isp/software_isp.cpp\n@@ -120,8 +120,9 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,\n  \t}\n  \n  \tif (!softISPMode || softISPMode == \"gpu\") {\n-\t\tif (eGL::isAvailable()) {\n-\t\t\tdebayer_ = std::make_unique<DebayerEGL>(std::move(stats), cm);\n+\t\tauto display = eGL::probeDisplay();\n+\t\tif (display != EGL_NO_DISPLAY) {\n+\t\t\tdebayer_ = std::make_unique<DebayerEGL>(std::move(stats), cm, display);\n  \t\t} else {\n  \t\t\tLOG(SoftwareIsp, Info)\n  \t\t\t\t<< \"EGL not available, falling back to CPU debayer\";\n\n> +\n> +\tif (probed)\n> +\t\treturn cachedDisplay;\n> +\n> +\tprobed = true;\n>   \n>   \tif (!eglBindAPI(EGL_OPENGL_ES_API)) {\n>   \t\tLOG(eGL, Info) << \"API bind fail\";\n>   \t\treturn EGL_NO_DISPLAY;\n>   \t}\n>   \n> -\tdisplay = eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA,\n> -\t\t\t\t\tEGL_DEFAULT_DISPLAY,\n> -\t\t\t\t\tnullptr);\n> +\tcachedDisplay = eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA,\n> +\t\t\t\t\t      EGL_DEFAULT_DISPLAY,\n> +\t\t\t\t\t      nullptr);\n>   \n> -\tif (display == EGL_NO_DISPLAY) {\n> +\tif (cachedDisplay == EGL_NO_DISPLAY) {\n>   \t\tLOG(eGL, Info) << \"Unable to get EGL display\";\n>   \t\treturn EGL_NO_DISPLAY;\n>   \t}\n>   \n> -\tif (eglInitialize(display, nullptr, nullptr) != EGL_TRUE) {\n> +\tif (eglInitialize(cachedDisplay, nullptr, nullptr) != EGL_TRUE) {\n>   \t\tLOG(eGL, Error) << \"eglInitialize fail\";\n> +\t\tcachedDisplay = EGL_NO_DISPLAY;\n>   \t\treturn EGL_NO_DISPLAY;\n>   \t}\n>   \n> -\treturn display;\n> +\treturn cachedDisplay;\n>   }\n>   \n>   /**\n>    * \\brief Probe whether EGL surfaceless rendering is available\n>    *\n>    * Checks if an EGL surfaceless display can be obtained and initialised.\n> - * The display is immediately terminated so that no resources are leaked.\n> + * The result is cached so that a subsequent call to initEGLContext() reuses\n> + * the already-initialised display without a redundant init/teardown cycle.\n>    *\n>    * \\return True if EGL surfaceless rendering is available, false otherwise\n>    */\n>   bool eGL::isAvailable()\n>   {\n> -\tEGLDisplay display = probeDisplay();\n> -\tif (display == EGL_NO_DISPLAY)\n> -\t\treturn false;\n> -\n> -\teglTerminate(display);\n> -\treturn true;\n> +\treturn probeDisplay() != EGL_NO_DISPLAY;\n>   }\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 7FE76BDE4C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 24 Jul 2026 10:05:50 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6930D67EE9;\n\tFri, 24 Jul 2026 12:05:49 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C30A667E89\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Jul 2026 12:05:47 +0200 (CEST)","from [192.168.33.42] (185.182.215.156.nat.pool.zt.hu\n\t[185.182.215.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 2856B524;\n\tFri, 24 Jul 2026 12:04:46 +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=\"MRCp4nmR\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1784887486;\n\tbh=gtBwz++dqEMqVpaKolIwmxoMTMIrMH3+R3ZO9usovrA=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=MRCp4nmR2SU16gtCfcygH5Wt80x0oP8pFMfHy2Q6Z8HBXHDEjr27He0zevT8vqpAt\n\tnEQZ+VaDqmKQ4pBF0U26Wz9ZgJXxpf1HXuMxvUlDZXg8fsT06rSHKL0RCF1FOa7NAO\n\tvEcMLii6f08ILrHJCWh4/GE8NjESSQTLVTGlSdcc=","Message-ID":"<f0ea0ed1-db25-4021-91c5-b274f744d41b@ideasonboard.com>","Date":"Fri, 24 Jul 2026 12:05:43 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] libcamera: egl: Cache probed EGLDisplay to avoid\n\tredundant init/teardown","To":"qi.hou@oss.nxp.com, libcamera-devel@lists.libcamera.org","Cc":"jared.hu@nxp.com, qi.hou@nxp.com, julien.vuillaumier@nxp.com","References":"<20260724014338.1850939-1-qi.hou@oss.nxp.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260724014338.1850939-1-qi.hou@oss.nxp.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>"}},{"id":39860,"web_url":"https://patchwork.libcamera.org/comment/39860/","msgid":"<PAXPR04MB8285C56F45871D359DFC2A7F97CC2@PAXPR04MB8285.eurprd04.prod.outlook.com>","date":"2026-07-27T06:44:51","subject":"RE: [PATCH] libcamera: egl: Cache probed EGLDisplay to avoid\n\tredundant init/teardown","submitter":{"id":455,"url":"https://patchwork.libcamera.org/api/people/455/","name":"Qi Hou (OSS)","email":"qi.hou@oss.nxp.com"},"content":"Hi Barnabás Pőcze,\n\nThanks for your detailed review. I have sent out v2 named as \"[v2] libcamera: egl: Pass EGLDisplay to eGL constructor to avoid double init\".\n\nRegards,\nQi Hou\n\n-----Original Message-----\nFrom: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> \nSent: Friday, July 24, 2026 6:06 PM\nTo: Qi Hou (OSS) <qi.hou@oss.nxp.com>; libcamera-devel@lists.libcamera.org\nCc: Jared Hu <jared.hu@nxp.com>; Qi Hou <qi.hou@nxp.com>; Julien Vuillaumier <julien.vuillaumier@nxp.com>\nSubject: Re: [PATCH] libcamera: egl: Cache probed EGLDisplay to avoid redundant init/teardown\n\n2026. 07. 24. 3:43 keltezéssel, qi.hou@oss.nxp.com írta:\n> From: Qi Hou <qi.hou@nxp.com>\n> \n> isAvailable() previously called probeDisplay() which ran eglBindAPI(),\n> eglGetPlatformDisplay() and eglInitialize(), then immediately \n> terminated the display with eglTerminate(). When SoftwareIsp \n> subsequently called initEGLContext(), probeDisplay() repeated a full initialisation sequence.\n> \n> Avoid this double init/teardown by caching the EGLDisplay handle \n> inside\n> probeDisplay() using static parameters. The first call initialises EGL \n> and stores the result, all later calls return the cached handle \n> without reinitialising.\n> \n> isAvailable() is simplified to return probeDisplay() != EGL_NO_DISPLAY \n> and no longer calls eglTerminate(), because the cached display should \n> be live for reuse by initEGLContext().\n> ---\n>   src/libcamera/egl.cpp | 31 +++++++++++++++++--------------\n>   1 file changed, 17 insertions(+), 14 deletions(-)\n> \n> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index \n> 7ec7a654d..f5200ee76 100644\n> --- a/src/libcamera/egl.cpp\n> +++ b/src/libcamera/egl.cpp\n> @@ -301,46 +301,49 @@ void eGL::createTexture2D(eGLImage &eglImage, \n> void *data)\n>   \n>   EGLDisplay eGL::probeDisplay()\n>   {\n> -\tEGLDisplay display;\n> +\tstatic EGLDisplay cachedDisplay = EGL_NO_DISPLAY;\n> +\tstatic bool probed = false;\n\nI'm not a fan of adding more mutable global state. As an alternative:\n   * modify `eGL` to take the EGLDisplay in its constructor\n     and adjust `initEGLContext()` to not retrieve the display\n   * adjust `DebayerEGL` accordingly\n   * adjust `SoftwareISP` to call `probeDisplay()` and forward the result\n\nHere is a prototype of the idea:\n\ndiff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h\nindex 1e31d490bd..7ef1ca0d93 100644\n--- a/include/libcamera/internal/egl.h\n+++ b/include/libcamera/internal/egl.h\n@@ -99,11 +99,11 @@ private:\n  class eGL\n  {\n  public:\n-\teGL();\n+\teGL(EGLDisplay display);\n  \t~eGL();\n  \n  \tint initEGLContext();\n-\tstatic bool isAvailable();\n+\tstatic EGLDisplay probeDisplay();\n  \n  \tint createInputDMABufTexture2D(eGLImage &eglImage, int fd);\n  \tint createOutputDMABufTexture2D(eGLImage &eglImage, int fd); @@ -137,7 +137,6 @@ private:\n  \tEGLContext context_ = EGL_NO_CONTEXT;\n  \tEGLSurface surface_ = EGL_NO_SURFACE;\n  \n-\tstatic EGLDisplay probeDisplay();\n  \tint compileShader(int shaderType, GLuint &shaderId, Span<const unsigned char> shaderData,\n  \t\t\t  Span<const std::string> shaderEnv);\n  \ndiff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 7ec7a654da..3d1a15493a 100644\n--- a/src/libcamera/egl.cpp\n+++ b/src/libcamera/egl.cpp\n@@ -64,12 +64,15 @@ LOG_DEFINE_CATEGORY(eGL)\n  \n  /**\n   * \\brief Construct an EGL helper\n+ * \\param[in] display The EGL display to use\n   *\n   * Creates an eGL instance with uninitialised context. Call initEGLContext()\n- * to set up the EGL display, context, and load extension functions.\n+ * to set up the EGL context, and load extension functions.\n   */\n-eGL::eGL()\n+eGL::eGL(EGLDisplay display)\n+\t: display_(display)\n  {\n+\tASSERT(display_ != EGL_NO_DISPLAY);\n  }\n  \n  /**\n@@ -299,6 +302,13 @@ void eGL::createTexture2D(eGLImage &eglImage, void *data)\n  \tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n  }\n  \n+/**\n+ * \\brief Try to create an EGL display for surfaceless rendering\n+ *\n+ * Tries to create an EGL display for surfaceless rendering.\n+ *\n+ * \\return A EGL display handle if successfull, otherwise \\a \n+EGL_NO_DISPLAY  */\n  EGLDisplay eGL::probeDisplay()\n  {\n  \tEGLDisplay display;\n@@ -325,24 +335,6 @@ EGLDisplay eGL::probeDisplay()\n  \treturn display;\n  }\n  \n-/**\n- * \\brief Probe whether EGL surfaceless rendering is available\n- *\n- * Checks if an EGL surfaceless display can be obtained and initialised.\n- * The display is immediately terminated so that no resources are leaked.\n- *\n- * \\return True if EGL surfaceless rendering is available, false otherwise\n- */\n-bool eGL::isAvailable()\n-{\n-\tEGLDisplay display = probeDisplay();\n-\tif (display == EGL_NO_DISPLAY)\n-\t\treturn false;\n-\n-\teglTerminate(display);\n-\treturn true;\n-}\n-\n  /**\n   * \\brief Update a 2D texture already created\n   * \\param[in,out] eglImage EGL image to associate with the texture @@ -403,12 +395,6 @@ int eGL::initEGLContext()\n  \tEGLint numConfigs;\n  \tEGLConfig config;\n  \n-\tdisplay_ = probeDisplay();\n-\tif (display_ == EGL_NO_DISPLAY) {\n-\t\tLOG(eGL, Error) << \"Unable to probe display\";\n-\t\tgoto fail;\n-\t}\n-\n  \tLOG(eGL, Info) << \"EGL: EGL_VERSION: \" << eglQueryString(display_, EGL_VERSION);\n  \tLOG(eGL, Info) << \"EGL: EGL_VENDOR: \" << eglQueryString(display_, EGL_VENDOR);\n  \tLOG(eGL, Info) << \"EGL: EGL_CLIENT_APIS: \" << eglQueryString(display_, EGL_CLIENT_APIS); diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\nindex dd20412194..20b478b1c3 100644\n--- a/src/libcamera/software_isp/debayer_egl.cpp\n+++ b/src/libcamera/software_isp/debayer_egl.cpp\n@@ -40,9 +40,10 @@ namespace libcamera {\n   * \\brief Construct a DebayerEGL object\n   * \\param[in] stats Statistics processing object\n   * \\param[in] cm The camera manager\n+ * \\param[in] display The EGL display to use\n   */\n-DebayerEGL::DebayerEGL(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm)\n-\t: Debayer(cm), stats_(std::move(stats))\n+DebayerEGL::DebayerEGL(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm, EGLDisplay display)\n+\t: Debayer(cm), stats_(std::move(stats)), egl_(display)\n  {\n  }\n  \ndiff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\nindex e613639f5c..30e51a4773 100644\n--- a/src/libcamera/software_isp/debayer_egl.h\n+++ b/src/libcamera/software_isp/debayer_egl.h\n@@ -40,7 +40,7 @@ class CameraManager;\n  class DebayerEGL : public Debayer\n  {\n  public:\n-\tDebayerEGL(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm);\n+\tDebayerEGL(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm, \n+EGLDisplay display);\n  \t~DebayerEGL();\n  \n  \tint configure(const StreamConfiguration &inputCfg, diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\nindex c73a16ce0a..c7165771c6 100644\n--- a/src/libcamera/software_isp/software_isp.cpp\n+++ b/src/libcamera/software_isp/software_isp.cpp\n@@ -120,8 +120,9 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,\n  \t}\n  \n  \tif (!softISPMode || softISPMode == \"gpu\") {\n-\t\tif (eGL::isAvailable()) {\n-\t\t\tdebayer_ = std::make_unique<DebayerEGL>(std::move(stats), cm);\n+\t\tauto display = eGL::probeDisplay();\n+\t\tif (display != EGL_NO_DISPLAY) {\n+\t\t\tdebayer_ = std::make_unique<DebayerEGL>(std::move(stats), cm, \n+display);\n  \t\t} else {\n  \t\t\tLOG(SoftwareIsp, Info)\n  \t\t\t\t<< \"EGL not available, falling back to CPU debayer\";\n\n> +\n> +\tif (probed)\n> +\t\treturn cachedDisplay;\n> +\n> +\tprobed = true;\n>   \n>   \tif (!eglBindAPI(EGL_OPENGL_ES_API)) {\n>   \t\tLOG(eGL, Info) << \"API bind fail\";\n>   \t\treturn EGL_NO_DISPLAY;\n>   \t}\n>   \n> -\tdisplay = eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA,\n> -\t\t\t\t\tEGL_DEFAULT_DISPLAY,\n> -\t\t\t\t\tnullptr);\n> +\tcachedDisplay = eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA,\n> +\t\t\t\t\t      EGL_DEFAULT_DISPLAY,\n> +\t\t\t\t\t      nullptr);\n>   \n> -\tif (display == EGL_NO_DISPLAY) {\n> +\tif (cachedDisplay == EGL_NO_DISPLAY) {\n>   \t\tLOG(eGL, Info) << \"Unable to get EGL display\";\n>   \t\treturn EGL_NO_DISPLAY;\n>   \t}\n>   \n> -\tif (eglInitialize(display, nullptr, nullptr) != EGL_TRUE) {\n> +\tif (eglInitialize(cachedDisplay, nullptr, nullptr) != EGL_TRUE) {\n>   \t\tLOG(eGL, Error) << \"eglInitialize fail\";\n> +\t\tcachedDisplay = EGL_NO_DISPLAY;\n>   \t\treturn EGL_NO_DISPLAY;\n>   \t}\n>   \n> -\treturn display;\n> +\treturn cachedDisplay;\n>   }\n>   \n>   /**\n>    * \\brief Probe whether EGL surfaceless rendering is available\n>    *\n>    * Checks if an EGL surfaceless display can be obtained and initialised.\n> - * The display is immediately terminated so that no resources are leaked.\n> + * The result is cached so that a subsequent call to initEGLContext() \n> + reuses\n> + * the already-initialised display without a redundant init/teardown cycle.\n>    *\n>    * \\return True if EGL surfaceless rendering is available, false otherwise\n>    */\n>   bool eGL::isAvailable()\n>   {\n> -\tEGLDisplay display = probeDisplay();\n> -\tif (display == EGL_NO_DISPLAY)\n> -\t\treturn false;\n> -\n> -\teglTerminate(display);\n> -\treturn true;\n> +\treturn probeDisplay() != EGL_NO_DISPLAY;\n>   }\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 F1D32C328C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 27 Jul 2026 06:45:00 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1D36D67F56;\n\tMon, 27 Jul 2026 08:45:00 +0200 (CEST)","from AM0PR83CU005.outbound.protection.outlook.com\n\t(mail-westeuropeazlp170100001.outbound.protection.outlook.com\n\t[IPv6:2a01:111:f403:c201::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 238DB67F4C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 27 Jul 2026 08:44:58 +0200 (CEST)","from PAXPR04MB8285.eurprd04.prod.outlook.com\n\t(2603:10a6:102:1ca::15)\n\tby PAXPR04MB8406.eurprd04.prod.outlook.com (2603:10a6:102:1c4::10)\n\twith Microsoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.245.13;\n\tMon, 27 Jul 2026 06:44:51 +0000","from PAXPR04MB8285.eurprd04.prod.outlook.com\n\t([fe80::81d0:4221:c6e5:9b82]) by\n\tPAXPR04MB8285.eurprd04.prod.outlook.com\n\t([fe80::81d0:4221:c6e5:9b82%4]) with mapi id 15.21.0245.012;\n\tMon, 27 Jul 2026 06:44:51 +0000"],"Authentication-Results":["lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=NXP1.onmicrosoft.com\n\theader.i=@NXP1.onmicrosoft.com header.b=\"iJQwNJLa\"; \n\tdkim-atps=neutral","dkim=none (message not signed)\n\theader.d=none;dmarc=none action=none header.from=oss.nxp.com;"],"ARC-Seal":"i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n\tb=Yg/xdAfmf6C16p13v8+fhRn9odWcFfGlYMfHDk6sqmT4c4iFHQuc6+hsiTSE17v1//MHLchCSLcycifbr/Nu0XFiBVFcfemRUpWKBSuBfCEWtv9w2dZHEyqGEuV28xqNWoKRrIDyxFOS7bcS/O5Z6NCNNpbbbc6Kwe4erhKPeeyXl8H1k7TDGtkifL6ojJvtDqPGM4y8KTd5JdMFbWI1wdd0PiYv5auJ9KoJUhMNNSdOGGL1HOmwu26MqD3QFYwMBXN9NDLQLObdlapSpEkY/LRIK+ZJ0A1ln/Xc32cq3mAl7Lue8LPd9UBfVXq1AqxGZx5E1kVa66c1yXxDS8DGsA==","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n\ts=arcselector10001;\n\th=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n\tbh=gHnzQQyQ5FbA9b5J6msOVkrhCh92K/DCzdyRGNn+Hxs=;\n\tb=d/jHf4jEEFy1Afqy6RxotdqarI7vGTuTGsQEfJ/PTkQRE37UXR6IFc7xmKP7O5fxRL/C/bIdKivyiSojq1/X//4K7U6/tf1mEWMZzmb55bJKRVq9A/xYETo/okTWHA0CCUNcR2qfFyiRVQLGLiCOjbAG3PpkpHQjoyixRZnSlNqYd2nJuLMti+8r8fy8RjLxbe6p9eHOW8KrmPB4fn+l2jZqgJoL/ZziUt8JZ0y0XAbkXUHRWod8w8Y+zxB12UilBsOolzoMd20g0TGZ1cyVS5/LxsjO9Thz9YMOFua5as1cDqbm9VhvsClSg9F/DZm9jMd0950nNeS51nxRVGEcIA==","ARC-Authentication-Results":"i=1; mx.microsoft.com 1; spf=pass\n\tsmtp.mailfrom=oss.nxp.com;\n\tdmarc=pass action=none header.from=oss.nxp.com; \n\tdkim=pass header.d=oss.nxp.com; arc=none","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com;\n\ts=selector1-NXP1-onmicrosoft-com;\n\th=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n\tbh=gHnzQQyQ5FbA9b5J6msOVkrhCh92K/DCzdyRGNn+Hxs=;\n\tb=iJQwNJLaSWJdXxhLHJhqaq6xCmpDITMp8BPaCqXgxgi4U7TJsOi32mQi1AD2QEVTafXCnRzY5ACkBU3UnPq5N1i+Tx66JixpQCE/AC2CGJ+jhdB370TxIdw7dIfhyxeypl+S4fUeuC6mVEWEAfGO7KbDcQYeahFEnWqklOw2LDu626e3E5331wUMb1yb2j6kqpf631vtXeBoo/sP6WsNv3XndfODTeyManddvfI9m/8mReT3vtk74nJpCClU9bJbPoGsSuKYs3J7vqztdgI5Y056uflbr85x3br6qVbuFu5n3OaXJT5aWOKFHSh36KqiQapFH2qSeubfMv3fQ6OCFg==","From":"\"Qi Hou (OSS)\" <qi.hou@oss.nxp.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>,\n\t\"Qi Hou (OSS)\" <qi.hou@oss.nxp.com>,\n\t\"libcamera-devel@lists.libcamera.org\"\n\t<libcamera-devel@lists.libcamera.org>","CC":"Jared Hu <jared.hu@nxp.com>, Qi Hou <qi.hou@nxp.com>, Julien Vuillaumier\n\t<julien.vuillaumier@nxp.com>","Subject":"RE: [PATCH] libcamera: egl: Cache probed EGLDisplay to avoid\n\tredundant init/teardown","Thread-Topic":"[PATCH] libcamera: egl: Cache probed EGLDisplay to avoid\n\tredundant init/teardown","Thread-Index":"AQHdHZNskWBqRjn8vkazjsx5Hp760A==","Date":"Mon, 27 Jul 2026 06:44:51 +0000","Message-ID":"<PAXPR04MB8285C56F45871D359DFC2A7F97CC2@PAXPR04MB8285.eurprd04.prod.outlook.com>","References":"<20260724014338.1850939-1-qi.hou@oss.nxp.com>\n\t<f0ea0ed1-db25-4021-91c5-b274f744d41b@ideasonboard.com>","In-Reply-To":"<f0ea0ed1-db25-4021-91c5-b274f744d41b@ideasonboard.com>","Accept-Language":"zh-CN, en-US","Content-Language":"en-US","X-MS-Has-Attach":"","X-MS-TNEF-Correlator":"","authentication-results":["lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=NXP1.onmicrosoft.com\n\theader.i=@NXP1.onmicrosoft.com header.b=\"iJQwNJLa\"; \n\tdkim-atps=neutral","dkim=none (message not signed)\n\theader.d=none;dmarc=none action=none header.from=oss.nxp.com;"],"x-ms-exchange-messagesentrepresentingtype":"1","x-ms-publictraffictype":"Email","x-ms-traffictypediagnostic":"PAXPR04MB8285:EE_|PAXPR04MB8406:EE_","x-ms-office365-filtering-correlation-id":"1c55fedc-8ea4-40ce-b539-08deebaa8f56","x-ms-exchange-sharedmailbox-routingagent-processed":"True","x-ms-exchange-senderadcheck":"1","x-ms-exchange-antispam-relay":"0","x-microsoft-antispam":"BCL:0;\n\tARA:13230040|376014|366016|23010399003|19092799006|1800799024|6133799003|18002099003|22082099003|38070700021|3023799007|56012099006|4143699003|11063799006|10067099003;","x-microsoft-antispam-message-info":"WKlWloUUGrf1PyEaTSOIDDrp3dKGaLxogUWY5JDFxOYSLkqtiVDXgnNWr89o9Dakn6fxjpURLLxxczBPuOmO0JGOol7OdNUNBJ5cUajpMpKp1k8osbbEgz+cenPOI7CSAOb9/AuFGiSVJEVQhudTgZQyg9YsVPSne4vF6tXqqW+9QWtOZaPI0YM4mq9PRZPyq6hfVgK1MKUCP1zY4d1a3E3FbmcH22Bi9R0EVtIgu1Grv02UwztyaKvrxUiMkT5WrKWuQuTcg7b/wAYPcs97pjd+ID5MHrjUaLlkSDoX0Ya2CGD3+F1oSs8b+IwfGST4Pe7Nvh8+MlOB8lTJ5/cxNkX7v20p3SYXHl1Ephq+FcxzXEMYAUTDALPmrxuUZS+Mlx5S8j/0vXcdCpmKytCz/Anq2G6rJ5NuWn1wdUGcDbYS4LjoHaZWueb9jBK5C+Os2xSuExBwe4Aj1FafodBts/cqxKsCASySheqEvpIgUz1xfWTaTfL3Z/WQR99YW4jTQWYFMfbRMjjuKAKQZiyhOKuv/iZl6fGnDhuUH96J+Zeq8R7KTZ48xN8ZR28lOplxNvKAb/brZyvDkRWq89i8mb84ZB9s8CQSyqxHmZJR+CvACx964uO4izXd9qP8gCFSI0YwsCDLIrvYQRSK1vyfdgvspiduK4Ghn1aWblTVXD2c4LH/cSjRKmfCN9dab1jjVbzog73ePCRfgII0+xDwspx6+Ka9i+6eRxDF5R+nx+s=","x-forefront-antispam-report":"CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n\tIPV:NLI; SFV:NSPM; H:PAXPR04MB8285.eurprd04.prod.outlook.com; PTR:;\n\tCAT:NONE; \n\tSFS:(13230040)(376014)(366016)(23010399003)(19092799006)(1800799024)(6133799003)(18002099003)(22082099003)(38070700021)(3023799007)(56012099006)(4143699003)(11063799006)(10067099003);\n\tDIR:OUT; SFP:1101; ","x-ms-exchange-antispam-messagedata-chunkcount":"1","x-ms-exchange-antispam-messagedata-0":"=?utf-8?q?6pJtau5JA5yH/5bz5PFnTnIiO?=\n\t=?utf-8?q?u9oiZjvgUfFv8tM9spWdMPUIt8iNzHJq8cJVgZPhIdRpnR+2/6/wUbLF?=\n\t=?utf-8?q?iasjNZj7/NYX4nEuoSq4DosrJ78t8LDMzc+QpC7mquMyipeDio+7gN7r?=\n\t=?utf-8?q?9qZiB8KAdZFU0/HEuhsYx3JlCT5L+nIW8SjATAuLCd9ayzWq89LOq/gI?=\n\t=?utf-8?q?uOXWV6MgDxITOuZq3QfyG8Hz61+GwQH46tYkc4SrpwiSnOn38kGbw1ST?=\n\t=?utf-8?q?0bqLtMBUv3zsdnyGqQIJeTr6aQlR5JncyhSJ/8K7umb7w7jy9PST8CVy?=\n\t=?utf-8?q?MiqvHTnqYYSziCCjShw6Aqr9Xvgf0X+OLpFTSmIg681jtODXrUR5lkjp?=\n\t=?utf-8?q?gM4rEBqYRvEl0Pk8zJvDaoScMbOjb9REdDbZGjE969QIHG6Fh7hmsNis?=\n\t=?utf-8?q?T+4l3/D8UotreSOTcuSHXskxHxJQK51p+tPR4Cu/wxsj0TLXWN4HDXwI?=\n\t=?utf-8?q?nhfY6hjRFB2ykSJRn9f1TIZd4zdfV9Ov5zzKeVhTKFZBQBwH7S9CUX31?=\n\t=?utf-8?q?3XSDQEPdkeYi7JaYlY9rgXgDacXGPpyEzXFAkR50bJh9Nl3abqaWJylW?=\n\t=?utf-8?q?OxHt6C0UL3j0fwEPHviHJZTYxtabJqHDoICArB1AOXhYBP2yIFIbWOTy?=\n\t=?utf-8?q?gTECT16tMtRKHKDY5191v2W4SFNxLi997Ml6772UkmJW2ChTjyCyn4KA?=\n\t=?utf-8?q?l9fRrH92fevmgeiF+cKj60nJ/r1OePofY3ErMq1TowFfPYqxZmNu4gkf?=\n\t=?utf-8?q?vx/WdrOPA8PSXqGII6Q6CZTJA2YP+ZarXPcDl7NoJ7RVeJmnJBr/lNc9?=\n\t=?utf-8?q?4P0IGINMivv4TjbA6lHK9eCt4H3JuJ1NDqOcMNs1GwOjz5a1o1ehdBdJ?=\n\t=?utf-8?q?nIvldxShcRm5PMQD9KUq+sPBnmMPQwJHNZUflmv/ZPqCM5KIFLwE+k3o?=\n\t=?utf-8?q?RnPrsDCs7UvjAoBC7uC8Er0gxeL5ksZDwQHMXzerSVmjsiElC3bdfyvj?=\n\t=?utf-8?q?88KMOAxUSMM/FlepzAb8IMdmPxshf20s1ZO6wZ3CTi4Absje775cMQHr?=\n\t=?utf-8?q?SMXRGxGYsm4SXeavZly6G5vNgMFSwtC3bgP/x6GLwx7Qh4isid3QiFNi?=\n\t=?utf-8?q?67bRze6Lhn6X3H0Nm5vUlM+yyakY8FeyMaLy83/7ASxbQCK5rWXIkziw?=\n\t=?utf-8?q?cwvzSzT3GNJGhTEyzXAfk/9Y+2X3ueKjFafGNHOyo8pHsUHYQx8NLHPP?=\n\t=?utf-8?q?b+1Or+itxLBwwZxsv2SUWMnCrwW2CBdCCE2NcnbK3RJix+rV8EHuevSQ?=\n\t=?utf-8?q?k7Eh3W037bdrAFAJlVIUvFHk64NWprBS4qeLhNqiGLiNYb69Q5JOh5AV?=\n\t=?utf-8?q?3wHPSj1Sg7NeyfnvTDWG51CdwE2rYRLi6eBeCn7GhlD505ivRu/ds1Bg?=\n\t=?utf-8?q?Qgw8FHHaei6fZr8JxC6jZKpkeCoH0l66CjQPhPrryl4QchSz8BtQSZfg?=\n\t=?utf-8?q?7Q5jOwTjXD20QW716+fKtt2e8o+Wt3eUPBv9EeC3Im0uDARKhJqrUAsb?=\n\t=?utf-8?q?spW8dY0pArMckWCgFHhmSg0fCsFz/hhjYvhPlapZn9x4xa0xc+hk90ge?=\n\t=?utf-8?q?/BV+ZuJ8iUdAeregBhNCaScnPyd8SxYny5/r1VqHhqya7r5QKbgNdUN7?=\n\t=?utf-8?q?juuC5hIqjpLoF7GFGYfj9QFk6zqd1821wujrN40XRkRiH5XPy59U35ND?=\n\t=?utf-8?q?qT72aeMCLeey+EPzr4othc9878imtgnjRjPxpE59vsM0EvAK+Jtsl7NB?=\n\t=?utf-8?q?4L6D/NH1ZqHRPY63kBOBDoa?=","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","MIME-Version":"1.0","X-OriginatorOrg":"oss.nxp.com","X-MS-Exchange-CrossTenant-AuthAs":"Internal","X-MS-Exchange-CrossTenant-AuthSource":"PAXPR04MB8285.eurprd04.prod.outlook.com","X-MS-Exchange-CrossTenant-Network-Message-Id":"1c55fedc-8ea4-40ce-b539-08deebaa8f56","X-MS-Exchange-CrossTenant-originalarrivaltime":"27 Jul 2026 06:44:51.4855\n\t(UTC)","X-MS-Exchange-CrossTenant-fromentityheader":"Hosted","X-MS-Exchange-CrossTenant-id":"686ea1d3-bc2b-4c6f-a92c-d99c5c301635","X-MS-Exchange-CrossTenant-mailboxtype":"HOSTED","X-MS-Exchange-CrossTenant-userprincipalname":"cnuRErFtkXuCcgkAhNtCEtC3PHqmXfIfCFV695fv7+cdnszH4glw3ubBwHPgYZXk","X-MS-Exchange-Transport-CrossTenantHeadersStamped":"PAXPR04MB8406","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>"}}]