From patchwork Wed Jun 3 10:25:34 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qi Hou X-Patchwork-Id: 26818 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 33830C324C for ; Wed, 3 Jun 2026 10:25:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6F32F630BA; Wed, 3 Jun 2026 12:25:45 +0200 (CEST) Received: from inva020.nxp.com (inva020.nxp.com [92.121.34.13]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A526A62FE1 for ; Wed, 3 Jun 2026 12:25:43 +0200 (CEST) Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 3F1C11A5E97; Wed, 3 Jun 2026 12:25:43 +0200 (CEST) Received: from aprdc01srsp001v.ap-rdc01.nxp.com (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 08F281A5E72; Wed, 3 Jun 2026 12:25:43 +0200 (CEST) Received: from lsvm11u0000124.swis.ap-northeast-2.aws.nxp.com (lsvm11u0000124.swis.ap-northeast-2.aws.nxp.com [10.52.8.111]) by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id DD6CE180004C; Wed, 3 Jun 2026 18:25:41 +0800 (+08) From: Qi Hou To: libcamera-devel@lists.libcamera.org Cc: jared.hu@nxp.com, qi.hou@nxp.com, julien.vuillaumier@nxp.com Subject: [PATCH] libcamera: software_isp: Probe EGL availability before creating DebayerEGL Date: Wed, 3 Jun 2026 19:25:34 +0900 Message-Id: <20260603102534.3059900-1-qi.hou@nxp.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Virus-Scanned: ClamAV using ClamSMTP X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When HAVE_DEBAYER_EGL is enabled, the SoftwareIsp constructor unconditionally creates a DebayerEGL instance. The DebayerEGL constructor always succeeds because it merely stores pointers without initialising the EGL context. The actual EGL initialisation is deferred to DebayerEGL::start(), which calls eGL::initEGLContext(). If the platform lacks a surfaceless EGL display (e.g. i.MX8MM without Mesa surfaceless support), eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA) fails and start() returns -ENODEV. At that point, the SwStatsCpu ownership has already been moved into the unusable DebayerEGL instance, making a fallback to DebayerCpu impossible. Fix this by adding a static DebayerEGL::isEGLAvailable() method that probes whether EGL surfaceless rendering can be initialised. It attempts eglGetPlatformDisplay() + eglInitialize() and immediately calls eglTerminate() to release resources. The SoftwareIsp constructor now calls this probe before creating DebayerEGL. If EGL is not available, DebayerEGL is not instantiated and the existing fallback path naturally creates a DebayerCpu instance instead. Signed-off-by: Qi Hou --- src/libcamera/software_isp/debayer_egl.cpp | 28 +++++++++++++++++++++ src/libcamera/software_isp/debayer_egl.h | 2 ++ src/libcamera/software_isp/software_isp.cpp | 10 ++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 7b9e02d9..cfe41447 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -33,6 +33,34 @@ namespace libcamera { * Implements an EGL shader based debayering solution. */ +/** + * \brief Probe whether EGL surfaceless rendering is available + * + * Performs a lightweight check by attempting to obtain an EGL display using + * EGL_PLATFORM_SURFACELESS_MESA and initialising it. The display is + * immediately released so that no resources are leaked. This allows the + * caller to decide at construction time whether to instantiate DebayerEGL + * or fall back to DebayerCpu. + * + * \return true if EGL surfaceless rendering is available, false otherwise + */ +bool DebayerEGL::isEGLAvailable() +{ + if (!eglBindAPI(EGL_OPENGL_ES_API)) + return false; + + EGLDisplay display = eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, + EGL_DEFAULT_DISPLAY, + nullptr); + if (display == EGL_NO_DISPLAY) + return false; + + EGLBoolean ret = eglInitialize(display, nullptr, nullptr); + eglTerminate(display); + + return ret == EGL_TRUE; +} + /** * \brief Construct a DebayerEGL object * \param[in] stats Statistics processing object diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 141fb288..945125cd 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -39,6 +39,8 @@ class CameraManager; class DebayerEGL : public Debayer { public: + static bool isEGLAvailable(); + DebayerEGL(std::unique_ptr stats, const CameraManager &cm); ~DebayerEGL(); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 781cf02f..403efbdb 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -119,8 +119,14 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, } } - if (!softISPMode || softISPMode == "gpu") - debayer_ = std::make_unique(std::move(stats), cm); + if (!softISPMode || softISPMode == "gpu") { + if (DebayerEGL::isEGLAvailable()) { + debayer_ = std::make_unique(std::move(stats), cm); + } else { + LOG(SoftwareIsp, Info) + << "EGL not available, falling back to CPU debayer"; + } + } #endif if (!debayer_)