[{"id":39903,"web_url":"https://patchwork.libcamera.org/comment/39903/","msgid":"<92c93a4f-e9c9-46ea-98fd-1ae549a5eab4@ideasonboard.com>","date":"2026-07-29T10:05:20","subject":"Re: [PATCH v3] libcamera: egl: Pass EGLDisplay to eGL constructor to\n\tavoid double init","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 07. 29. 4:55 keltezéssel, qi.hou@oss.nxp.com írta:\n> From: Qi Hou <qi.hou@nxp.com>\n> \n> isAvailable() previously called probeDisplay() to run a full EGL\n> initialisation sequence and then immediately terminated the display with\n> eglTerminate(). When SoftwareIsp subsequently created a DebayerEGL\n> instance, initEGLContext() would call probeDisplay() again, repeating\n> the full initialisation.\n> \n> Fix this by reusing the display obtained during the availability check.\n> probeDisplay() is promoted to a public static method and isAvailable()\n> is removed. The eGL constructor now takes the EGLDisplay as a parameter\n> and stores it directly, so initEGLContext() no longer needs to call\n> probeDisplay(). DebayerEGL is updated to accept and forward the display\n> to eGL, and SoftwareIsp calls eGL::probeDisplay() once, passing the\n> result straight to DebayerEGL when EGL is available.\n> \n> Signed-off-by: Qi Hou <qi.hou@nxp.com>\n> ---\n\nTested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # intel-ipu6 + ov2740 + mesa 26.1.5\n\nIt seems to work, no output with `MESA_DEBUG=1`, and I might have very\nwell missed it, but I couldn't find any obvious prohibition of what\nis suggested here.\n\n\n>   include/libcamera/internal/egl.h            |  5 +--\n>   src/libcamera/egl.cpp                       | 42 +++++++--------------\n>   src/libcamera/software_isp/debayer_egl.cpp  |  5 ++-\n>   src/libcamera/software_isp/debayer_egl.h    |  2 +-\n>   src/libcamera/software_isp/software_isp.cpp |  5 ++-\n>   5 files changed, 23 insertions(+), 36 deletions(-)\n> \n> diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h\n> index 1e31d490b..7ef1ca0d9 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>   \n> diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp\n> index 7ec7a654d..01e51cda8 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,15 +302,17 @@ 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 successful, otherwise \\a EGL_NO_DISPLAY\n> + */\n>   EGLDisplay eGL::probeDisplay()\n>   {\n>   \tEGLDisplay display;\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> @@ -325,24 +330,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,9 +390,8 @@ 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> +\tif (!eglBindAPI(EGL_OPENGL_ES_API)) {\n> +\t\tLOG(eGL, Error) << \"API bind fail\";\n>   \t\tgoto fail;\n>   \t}\n>   \n> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n> index dd2041219..20b478b1c 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>   \n> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n> index e613639f5..30e51a477 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,\n> diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n> index c73a16ce0..c7165771c 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\";","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 0382FC328C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 Jul 2026 10:05:26 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 46D8667FB3;\n\tWed, 29 Jul 2026 12:05:25 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6607967EC4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 Jul 2026 12:05:24 +0200 (CEST)","from [192.168.33.16] (185.182.215.156.nat.pool.zt.hu\n\t[185.182.215.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 30A0C163;\n\tWed, 29 Jul 2026 12:04:19 +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=\"NCtqN9hw\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1785319459;\n\tbh=pRgG+4If31iJQLVhNiZQwYav10kgWXNI+CHneqoxRUQ=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=NCtqN9hwrHKFqx91plsug9kmvlFNxQRfMBNDcc3rLDgxJjCWEO8vI0+k0rn0ExcGK\n\tRRSAoFEV6KLBYBdYQ97BJLwvlhsi4/jB3tiaUKdnJmUwO7eJA+pWZWURYlLhULOg+y\n\thIyiImOudeJjMFLTN+FKm3pFOuyukcTH/T9WU3Q4=","Message-ID":"<92c93a4f-e9c9-46ea-98fd-1ae549a5eab4@ideasonboard.com>","Date":"Wed, 29 Jul 2026 12:05:20 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3] libcamera: egl: Pass EGLDisplay to eGL constructor to\n\tavoid double init","To":"qi.hou@oss.nxp.com, libcamera-devel@lists.libcamera.org","Cc":"jared.hu@nxp.com, julien.vuillaumier@nxp.com","References":"<20260729025557.2261274-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":"<20260729025557.2261274-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>"}}]