From patchwork Tue Aug 11 13:00:35 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27751 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 2BE54C3263 for ; Tue, 11 Aug 2026 13:00:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E80966826E; Tue, 11 Aug 2026 15:00:47 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WD1PzlNe"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0C72B68252 for ; Tue, 11 Aug 2026 15:00:46 +0200 (CEST) Received: from pb-laptop.local (185.221.141.208.nat.pool.zt.hu [185.221.141.208]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 21B04196B; Tue, 11 Aug 2026 14:59:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1786453171; bh=sNX2VGgeZVQa6/n2u4mUhGrjQMk5xZu3aTidjQ72WA0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WD1PzlNeR5fzWCpyDGh95JN9PzhALgONRdIz3LI++lZdcrvkHMTz++kz+GevUkAzB ESp4kLbrbfAnqzOy2fm8rPAMSR2pEvU0XD/T3Ztgw28PvU7C5AxDjLVGZWonvMSn5r uXueAg1miDR2lQHIwvr535LWWrJGbNmd1bR4syJ4= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Jacopo Mondi Subject: [PATCH v3 1/8] libcamera: egl: Remove `gl{Use,Delete}Program()` Date: Tue, 11 Aug 2026 15:00:35 +0200 Message-ID: <20260811130042.213139-2-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> References: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 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" `eGL::deleteProgram()` is currently unused, and the only user of `eGL::useProgram()` is `debayer_egl.cpp`, which is already using numerous gl calls directly without going through the `eGL` type. So remove these trivial wrappers. Signed-off-by: Barnabás Pőcze Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- include/libcamera/internal/egl.h | 2 -- src/libcamera/egl.cpp | 28 ---------------------- src/libcamera/software_isp/debayer_egl.cpp | 2 +- 3 files changed, 1 insertion(+), 31 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 7ef1ca0d93..c43684808d 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -123,8 +123,6 @@ public: Span shaderEnv); int linkProgram(GLuint &programId, GLuint fragmentshaderId, GLuint vertexshaderId); void dumpShaderSource(GLuint shaderId); - void useProgram(GLuint programId); - void deleteProgram(GLuint programId); void syncOutput(); void flushOutput(); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 01e51cda8e..780b7bc2d5 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -464,34 +464,6 @@ void eGL::makeCurrent() } } -/** - * \brief Activate a shader program for rendering - * \param[in] programId OpenGL program object ID - * - * Sets the specified program as the current rendering program. All - * subsequent draw calls will use this program's shaders. - */ -void eGL::useProgram(GLuint programId) -{ - ASSERT(tid_ == Thread::currentId()); - - glUseProgram(programId); -} - -/** - * \brief Delete a shader program - * \param[in] programId OpenGL program object ID - * - * Deletes a shader program and frees associated resources. The program - * must not be currently in use. - */ -void eGL::deleteProgram(GLuint programId) -{ - ASSERT(tid_ == Thread::currentId()); - - glDeleteProgram(programId); -} - /** * \brief Add a preprocessor definition to shader environment * \param[in,out] shaderEnv Vector of shader environment strings diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 20b478b1c3..ede3be2352 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -261,7 +261,7 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm egl_.dumpShaderSource(fragmentShaderId_); /* Ensure we set the programId_ */ - egl_.useProgram(programId_); + glUseProgram(programId_); err = glGetError(); if (err != GL_NO_ERROR) { LOG(Debayer, Error) << "Use program error " << err; From patchwork Tue Aug 11 13:00:36 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27752 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 7A236C3264 for ; Tue, 11 Aug 2026 13:00:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1DE1E68259; Tue, 11 Aug 2026 15:00:50 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="eMhZOAhx"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3F5D36824B for ; Tue, 11 Aug 2026 15:00:46 +0200 (CEST) Received: from pb-laptop.local (185.221.141.208.nat.pool.zt.hu [185.221.141.208]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5A81C1CF0; Tue, 11 Aug 2026 14:59:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1786453171; bh=VTaaTCE5ugWkX8R91wpStIeEvrJKEee5JvEs3lU424I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eMhZOAhx9qwHplPBnboUv8VSxt7hYDFquE4YKNlHtL+jezelWWKE2BJEbvXJbDbC3 pLRFL4F7l8q4EYcRbuTnZEEsEzWMDtZbspEyhz2a7+JtyREo3pHSSSoMxsX6eV9sL2 Imk8uhKW5GaVSmZnSxpZ9F6dXFe5Y9O4h12P8lXc= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Jacopo Mondi Subject: [PATCH v3 2/8] libcamera: egl: Remove `eGL::surface_` Date: Tue, 11 Aug 2026 15:00:36 +0200 Message-ID: <20260811130042.213139-3-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> References: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 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" This member has always been unused, so remove it. Signed-off-by: Barnabás Pőcze Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- include/libcamera/internal/egl.h | 1 - src/libcamera/egl.cpp | 8 -------- 2 files changed, 9 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index c43684808d..f8ae486a8d 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -133,7 +133,6 @@ private: EGLDisplay display_ = EGL_NO_DISPLAY; EGLContext context_ = EGL_NO_CONTEXT; - EGLSurface surface_ = EGL_NO_SURFACE; int compileShader(int shaderType, GLuint &shaderId, Span shaderData, Span shaderEnv); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 780b7bc2d5..900d2174df 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -57,11 +57,6 @@ LOG_DEFINE_CATEGORY(eGL) *\brief EGL context handle */ -/** - *\var eGL::surface_ - *\brief EGL sufrace handle - */ - /** * \brief Construct an EGL helper * \param[in] display The EGL display to use @@ -84,9 +79,6 @@ eGL::~eGL() { if (context_ != EGL_NO_CONTEXT) eglDestroyContext(display_, context_); - - if (surface_ != EGL_NO_SURFACE) - eglDestroySurface(display_, surface_); } /** From patchwork Tue Aug 11 13:00:37 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27753 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 58C4DC328C for ; Tue, 11 Aug 2026 13:00:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DB0B868279; Tue, 11 Aug 2026 15:00:52 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="j3qCGkly"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6E5F268259 for ; Tue, 11 Aug 2026 15:00:46 +0200 (CEST) Received: from pb-laptop.local (185.221.141.208.nat.pool.zt.hu [185.221.141.208]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 947071049; Tue, 11 Aug 2026 14:59:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1786453171; bh=cqtdNsQ8DQJebmmjVOlTdcyQ0T5Ridym17zn9QO4mGg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=j3qCGklynob3m4MX9E1wwe9oIlJHm6bR/EKUbAnMafPGtIEegSdppiPil2BxxXxiz fNJH3aK2z9z0urzJ6EwXlltn7q/SqnFWxsXsbJid0Vby/l6DPkiy8kw+PfTzW0+3Rk dPO+RIOCEjYKeq7qmryst22kJ46kS8cCu+GaHogA= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Jacopo Mondi Subject: [PATCH v3 3/8] libcamera: egl: Do not load `glGetString` dynamically Date: Tue, 11 Aug 2026 15:00:37 +0200 Message-ID: <20260811130042.213139-4-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> References: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 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" `glGetString()` should be available in all version of OpenGL and OpenGL ES, so there should be no need to load it with `eglGetProcAddress()` like it is done for extension functions. Signed-off-by: Barnabás Pőcze Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- include/libcamera/internal/egl.h | 1 - src/libcamera/egl.cpp | 6 ------ 2 files changed, 7 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index f8ae486a8d..6abb02bf3b 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -142,6 +142,5 @@ private: PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; - PFNGLGETSTRINGPROC glGetString; }; } //namespace libcamera diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 900d2174df..0768a840e6 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -410,12 +410,6 @@ int eGL::initEGLContext() goto fail; } - glGetString = (PFNGLGETSTRINGPROC)eglGetProcAddress("glGetString"); - if (!glGetString) { - LOG(eGL, Error) << "glGetString not found"; - goto fail; - } - if (eglChooseConfig(display_, configAttribs, &config, 1, &numConfigs) != EGL_TRUE) { LOG(eGL, Error) << "eglChooseConfig fail"; goto fail; From patchwork Tue Aug 11 13:00:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27754 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 2834CC32CE for ; Tue, 11 Aug 2026 13:00:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 64ED46827C; Tue, 11 Aug 2026 15:00:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WSeB6hpQ"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A659B68258 for ; Tue, 11 Aug 2026 15:00:46 +0200 (CEST) Received: from pb-laptop.local (185.221.141.208.nat.pool.zt.hu [185.221.141.208]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CEEDD1D03; Tue, 11 Aug 2026 14:59:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1786453171; bh=UFbPW3oQUfCrKuk0SSjXQ3Y+LhAvORJHZ1q9JCHx5sE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WSeB6hpQxPnFA3x9Gijoz/FwvJyq0AswZD63+1A06VcNXH91zFqyNoyRhfQABo7U8 aV0Zj9cgIBJSdSo4hkPpvSwPONk80Piln+ke/klBlPB4iqAemufietOHS+QhG9yVMq d5CSNvmvg2O9wpJPNuBj0ERykH3DXaGf72p5XKrU= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Jacopo Mondi Subject: [PATCH v3 4/8] libcamera: egl: Ensure all members are always initialized Date: Tue, 11 Aug 2026 15:00:38 +0200 Message-ID: <20260811130042.213139-5-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> References: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 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" The `tid_` and function pointer members were not previously initialize before calling `initEGLContext()`, fix that. Signed-off-by: Barnabás Pőcze Reviewed-by: Milan Zamazal Acked-by: Jacopo Mondi --- include/libcamera/internal/egl.h | 10 ++++++---- src/libcamera/egl.cpp | 24 +++++++++++++----------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 6abb02bf3b..fb77225ac4 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -129,7 +129,7 @@ public: private: LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL) - pid_t tid_; + pid_t tid_ = -1; EGLDisplay display_ = EGL_NO_DISPLAY; EGLContext context_ = EGL_NO_CONTEXT; @@ -139,8 +139,10 @@ private: int createDMABufTexture2D(eGLImage &eglImage, int fd, bool output); - PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; - PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; - PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; + struct VTable { + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; + } vtable_ = {}; }; } //namespace libcamera diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 0768a840e6..3de5fab816 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -199,9 +199,9 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) }; // clang-format on - EGLImageKHR image = eglCreateImageKHR(display_, EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, - NULL, image_attrs); + EGLImageKHR image = vtable_.eglCreateImageKHR(display_, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + NULL, image_attrs); if (image == EGL_NO_IMAGE_KHR) { LOG(eGL, Debug) << "eglCreateImageKHR fail"; @@ -212,8 +212,8 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) activateBindTexture(eglImage); // Generate texture with filter semantics - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); - eglDestroyImageKHR(display_, image); + vtable_.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + vtable_.eglDestroyImageKHR(display_, image); // Nearest filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -379,6 +379,7 @@ int eGL::initEGLContext() EGL_NONE }; + VTable vtable = {}; EGLint numConfigs; EGLConfig config; @@ -392,20 +393,20 @@ int eGL::initEGLContext() LOG(eGL, Info) << "EGL: EGL_CLIENT_APIS: " << eglQueryString(display_, EGL_CLIENT_APIS); LOG(eGL, Info) << "EGL: EGL_EXTENSIONS: " << eglQueryString(display_, EGL_EXTENSIONS); - eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); - if (!eglCreateImageKHR) { + vtable.eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); + if (!vtable.eglCreateImageKHR) { LOG(eGL, Error) << "eglCreateImageKHR not found"; goto fail; } - eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); - if (!eglDestroyImageKHR) { + vtable.eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); + if (!vtable.eglDestroyImageKHR) { LOG(eGL, Error) << "eglDestroyImageKHR not found"; goto fail; } - glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); - if (!glEGLImageTargetTexture2DOES) { + vtable.glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + if (!vtable.glEGLImageTargetTexture2DOES) { LOG(eGL, Error) << "glEGLImageTargetTexture2DOES not found"; goto fail; } @@ -422,6 +423,7 @@ int eGL::initEGLContext() } tid_ = Thread::currentId(); + vtable_ = vtable; makeCurrent(); From patchwork Tue Aug 11 13:00:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27755 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 2A4F8C32FE for ; Tue, 11 Aug 2026 13:00:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1AEC26827E; Tue, 11 Aug 2026 15:00:56 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="C3t4/CfX"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DBA2C68260 for ; Tue, 11 Aug 2026 15:00:46 +0200 (CEST) Received: from pb-laptop.local (185.221.141.208.nat.pool.zt.hu [185.221.141.208]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1117D1E99 for ; Tue, 11 Aug 2026 14:59:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1786453172; bh=4yD+yhpiKrZRksGje93mRTG+SyCDTDmNQx3KfAWmBT4=; h=From:To:Subject:Date:In-Reply-To:References:From; b=C3t4/CfXrBvKaCYS8iGjhKM8iS3LDJ+JMCs1/HoOp77DwWL+QvB0KRZXgyINVnygq CNKCZfrckQYMn/L2mcXLY8a1Bj/hZGHQ6T1h99flq7udKXlz8PIaicSC1M169EcmE3 nx8ufPPYFxmw/KPFFmBPjtYbOr5jcQoxI2I5lClE= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 5/8] libcamera: egl: Add `assertThread()` Date: Tue, 11 Aug 2026 15:00:39 +0200 Message-ID: <20260811130042.213139-6-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> References: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 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" Add a public function that does the thread check, and use that everywhere. This is very similar to `Object::assertThreadBound()`, but without actually making `eGL` an `Object`. That would be an option, but handling the moving between threads with the egl context is not easily implementable currently. Signed-off-by: Barnabás Pőcze Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- include/libcamera/internal/egl.h | 6 ++++++ src/libcamera/egl.cpp | 30 +++++++++++++++++++----------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index fb77225ac4..13df65e6b2 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -14,6 +14,7 @@ #include #include +#include #include /* @@ -126,6 +127,11 @@ public: void syncOutput(); void flushOutput(); + void assertThread() const + { + ASSERT(tid_ == Thread::currentId()); + } + private: LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL) diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 3de5fab816..2a1f577845 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -89,7 +89,7 @@ eGL::~eGL() */ void eGL::syncOutput() { - ASSERT(tid_ == Thread::currentId()); + assertThread(); glFinish(); } @@ -102,11 +102,19 @@ void eGL::syncOutput() */ void eGL::flushOutput() { - ASSERT(tid_ == Thread::currentId()); + assertThread(); glFlush(); } +/** + * \fn eGL::assertThread() + * \brief Assert that the execution is in the right thread + * + * Asserts that the execution is in the thread for which + * the created EGL context has been made current. + */ + /** * \brief Attach a texture to a frame-buffer-object * @@ -167,7 +175,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) EGLint drm_format; int ret = 0; - ASSERT(tid_ == Thread::currentId()); + assertThread(); switch (eglImage.format_) { case GL_RED: @@ -242,7 +250,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output) */ int eGL::createInputDMABufTexture2D(eGLImage &eglImage, int fd) { - ASSERT(tid_ == Thread::currentId()); + assertThread(); return createDMABufTexture2D(eglImage, fd, false); } @@ -261,7 +269,7 @@ int eGL::createInputDMABufTexture2D(eGLImage &eglImage, int fd) */ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) { - ASSERT(tid_ == Thread::currentId()); + assertThread(); return createDMABufTexture2D(eglImage, fd, true); } @@ -278,7 +286,7 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) */ void eGL::createTexture2D(eGLImage &eglImage, void *data) { - ASSERT(tid_ == Thread::currentId()); + assertThread(); activateBindTexture(eglImage); @@ -331,7 +339,7 @@ EGLDisplay eGL::probeDisplay() */ void eGL::updateTexture2D(eGLImage &eglImage, void *data) { - ASSERT(tid_ == Thread::currentId()); + assertThread(); activateBindTexture(eglImage); @@ -445,7 +453,7 @@ fail: */ void eGL::makeCurrent() { - ASSERT(tid_ == Thread::currentId()); + assertThread(); if (eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, context_) != EGL_TRUE) { LOG(eGL, Error) << "eglMakeCurrent fail"; @@ -523,7 +531,7 @@ int eGL::compileShader(int shaderType, GLuint &shaderId, GLint success; size_t i; - ASSERT(tid_ == Thread::currentId()); + assertThread(); auto count = 1 + shaderEnv.size(); auto shaderSourceData = std::make_unique(count); @@ -570,7 +578,7 @@ void eGL::dumpShaderSource(GLuint shaderId) { GLint shaderLength = 0; - ASSERT(tid_ == Thread::currentId()); + assertThread(); glGetShaderiv(shaderId, GL_SHADER_SOURCE_LENGTH, &shaderLength); @@ -603,7 +611,7 @@ int eGL::linkProgram(GLuint &programId, GLuint vertexshaderId, GLuint fragmentsh GLenum err; int ret = -ENODEV; - ASSERT(tid_ == Thread::currentId()); + assertThread(); programId = glCreateProgram(); if (!programId) { From patchwork Tue Aug 11 13:00:40 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27756 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 78D7CC3303 for ; Tue, 11 Aug 2026 13:00:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3E86468269; Tue, 11 Aug 2026 15:00:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BUKVqpcL"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 15C2868263 for ; Tue, 11 Aug 2026 15:00:47 +0200 (CEST) Received: from pb-laptop.local (185.221.141.208.nat.pool.zt.hu [185.221.141.208]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3CE5F20A4 for ; Tue, 11 Aug 2026 14:59:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1786453172; bh=rN3DA/7nB+j9UW01VKrB7vPGFHnxv0wJkWsgS7YsG9M=; h=From:To:Subject:Date:In-Reply-To:References:From; b=BUKVqpcLnXgStdZq7F+HG3mGRq0W01Rfcca+WwnicKUiwV27OFt0GDucpyaahHRup WhU6F/+uHTXR8xrNwkwigkKpPdKPGJe6HZJQhwex1YH9HPpHeGnwm/mrGkbq9vTSCq oWWVnyoa0caDlCfv11//CtmSA1/G5UoDK8qxdj2A= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 6/8] libcamera: software_isp: debayer_egl: Remove EGL context switch Date: Tue, 11 Aug 2026 15:00:40 +0200 Message-ID: <20260811130042.213139-7-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> References: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 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" `eGL::initEGLContext()`, which is called from the worker thread already includes a call to `eGL::makeCurrent()`, so calling it for each `process()` is not necessary, so skip it. Instead call `eGL::assertThread()` in `process()` to ensure that the thread is correct. And lastly, make `eGL::makeCurrent()` a private function as now there are no external calleras. Signed-off-by: Barnabás Pőcze asd Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- include/libcamera/internal/egl.h | 3 ++- src/libcamera/software_isp/debayer_egl.cpp | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 13df65e6b2..608d53151c 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -116,7 +116,6 @@ public: void activateBindTexture(eGLImage &eglImage); void pushEnv(std::vector &shaderEnv, const char *str); - void makeCurrent(); int compileVertexShader(GLuint &shaderId, Span shaderData, Span shaderEnv); @@ -145,6 +144,8 @@ private: int createDMABufTexture2D(eGLImage &eglImage, int fd, bool output); + void makeCurrent(); + struct VTable { PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index ede3be2352..7b2b367305 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -578,9 +578,6 @@ int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const Debaye eGLImage *eglImageIn; eGLImage *eglImageOut; - /* eGL context switch */ - egl_.makeCurrent(); - eglImageIn = getCachedInputFrameBuffer(input, inMapped, inDmaSyncer); if (!eglImageIn) return -ENOMEM; @@ -608,6 +605,7 @@ int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const Debaye void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) { + egl_.assertThread(); bench_.startFrame(); /* Copy metadata from the input buffer */ From patchwork Tue Aug 11 13:00:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27757 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 14A64C3306 for ; Tue, 11 Aug 2026 13:00:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CD92668276; Tue, 11 Aug 2026 15:00:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="VPCkpJ9c"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 40AFA68264 for ; Tue, 11 Aug 2026 15:00:47 +0200 (CEST) Received: from pb-laptop.local (185.221.141.208.nat.pool.zt.hu [185.221.141.208]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 687E32345 for ; Tue, 11 Aug 2026 14:59:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1786453172; bh=4kEfIcU1lbOM39u1YsdzTKTpC5Ku/YGWGQ97t2RjVN4=; h=From:To:Subject:Date:In-Reply-To:References:From; b=VPCkpJ9c2RA9m16wXWiGYHF2wZVeZzB45j2GfdSOWFehCxfhIj46/Lz1dfGK+cu3A lmpIbY4HhMmoz2AjppfO7vOxgCTLk7hwG04ITXs8lgyl9MmOHS/PfxuKUfFLRM17FV 5ZrcYw0AHERUHxKCKzn7uoqCwTKWHXoQ+1GcTmVM= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 7/8] libcamera: software_isp: debayer_egl: Avoid EGL context leaks Date: Tue, 11 Aug 2026 15:00:41 +0200 Message-ID: <20260811130042.213139-8-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> References: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 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" Currently each `start()` invocation causes a new EGL context to be acquired, and only the last allocation will be properly freed in the `eGL` destructor. To avoid that, add and use `eGL::resetEGLContext()` in `stop()`; and also make `eGL` destructor stricter by requring no active EGL context. Signed-off-by: Barnabás Pőcze Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- include/libcamera/internal/egl.h | 1 + src/libcamera/egl.cpp | 27 +++++++++++++++++++--- src/libcamera/software_isp/debayer_egl.cpp | 2 ++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 608d53151c..8f2ef296c3 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -104,6 +104,7 @@ public: ~eGL(); int initEGLContext(); + void resetEGLContext(); static EGLDisplay probeDisplay(); int createInputDMABufTexture2D(eGLImage &eglImage, int fd); diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 2a1f577845..1f9e743c2f 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -73,12 +73,13 @@ eGL::eGL(EGLDisplay display) /** * \brief Destroy the EGL helper * - * Destroys the EGL context and surface if they were successfully created. + * An instance must only be destroyed if there is no active EGL context. + * + * \sa resetEGLContext() */ eGL::~eGL() { - if (context_ != EGL_NO_CONTEXT) - eglDestroyContext(display_, context_); + ASSERT(context_ == EGL_NO_CONTEXT); } /** @@ -368,6 +369,8 @@ void eGL::createOutputTexture2D(eGLImage &eglImage) * - eglCreateImageKHR / eglDestroyImageKHR * - glEGLImageTargetTexture2DOES * + * Each successful invocation must be followed by a call to resetEGLContext(). + * * \return 0 on success, or -ENODEV on failure */ int eGL::initEGLContext() @@ -444,6 +447,24 @@ fail: return -ENODEV; } +/** + * \brief Destroy the EGL context + * + * This function destroys the EGL context created by initEGLContext(). + * If there is no valid EGL context, this function has no effect. + */ +void eGL::resetEGLContext() +{ + if (context_ != EGL_NO_CONTEXT) { + assertThread(), + eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(display_, std::exchange(context_, EGL_NO_CONTEXT)); + } + + tid_ = -1; + vtable_ = {}; +} + /** * \brief Make the EGL context current for the calling thread * diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 7b2b367305..97aa037935 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -680,6 +680,8 @@ void DebayerEGL::stop() if (programId_) glDeleteProgram(programId_); + + egl_.resetEGLContext(); } SizeRange DebayerEGL::sizes(PixelFormat inputFormat, const Size &inputSize) From patchwork Tue Aug 11 13:00:42 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27758 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 DBEC6C330A for ; Tue, 11 Aug 2026 13:00:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 82F9C68278; Tue, 11 Aug 2026 15:00:58 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="AU8lepEL"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 71D246826D for ; Tue, 11 Aug 2026 15:00:47 +0200 (CEST) Received: from pb-laptop.local (185.221.141.208.nat.pool.zt.hu [185.221.141.208]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9B75D1E99; Tue, 11 Aug 2026 14:59:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1786453172; bh=ZoakN/o5HRKQAvw5CQCqGlXSgfkU+wD79pJwu1w9YHk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AU8lepELYT9FathKo72LmL4/dX8Xb+zPEYYfPLkR21wD2BE1kRGl5SAc+Ju1hp35y ZLVZsvZ1eW2iE0X9moz+BGl+kX4H3LW9JLVGRL23bAEr7Ht/mdu0oq8BAA7jIZ7Q6E aqii4Jati3lyjmIjD7hz6OX/9LgiqnJb2iGXn0P0= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Jacopo Mondi Subject: [PATCH v3 8/8] libcamera: egl: initEGLContext(): Avoid double init Date: Tue, 11 Aug 2026 15:00:42 +0200 Message-ID: <20260811130042.213139-9-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> References: <20260811130042.213139-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 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" If the initialization is already done, reject further attempts, otherwise resources would be leaked. Signed-off-by: Barnabás Pőcze Reviewed-by: Milan Zamazal Reviewed-by: Jacopo Mondi --- src/libcamera/egl.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index 1f9e743c2f..410d27b98c 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -371,7 +371,10 @@ void eGL::createOutputTexture2D(eGLImage &eglImage) * * Each successful invocation must be followed by a call to resetEGLContext(). * - * \return 0 on success, or -ENODEV on failure + * If a valid EGL context is already present, initialization attempts + * will be rejected. + * + * \return 0 on success, or negative error code on failure */ int eGL::initEGLContext() { @@ -394,6 +397,9 @@ int eGL::initEGLContext() EGLint numConfigs; EGLConfig config; + if (context_ != EGL_NO_CONTEXT) + return -EEXIST; + if (!eglBindAPI(EGL_OPENGL_ES_API)) { LOG(eGL, Error) << "API bind fail"; goto fail;