diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h
index 790ec4b22..b80d65877 100644
--- a/include/libcamera/internal/egl.h
+++ b/include/libcamera/internal/egl.h
@@ -107,8 +107,12 @@ public:
 
 	int createInputDMABufTexture2D(eGLImage &eglImage, int fd);
 	int createOutputDMABufTexture2D(eGLImage &eglImage, int fd);
-	void createTexture2D(eGLImage &eglImage, void *data, GLint filter);
-	void updateTexture2D(eGLImage &eglImage, void *data);
+	void createTexture2D(eGLImage &eglImage,
+			     GLint internalFormat,
+			     GLenum type,
+			     const void *data,
+			     GLint filter);
+	void updateTexture2D(eGLImage &eglImage, const void *data);
 	void createOutputTexture2D(eGLImage &eglImage);
 
 	int attachTextureToFBO(eGLImage &eglImage);
diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp
index 32e7e0e9c..cbae3a664 100644
--- a/src/libcamera/egl.cpp
+++ b/src/libcamera/egl.cpp
@@ -277,6 +277,8 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd)
 /**
  * \brief Create a 2D texture from a memory buffer
  * \param[in,out] eglImage EGL image to associate with the texture
+ * \param[in] internalFormat OpenGL internal storage format (e.g., GL_RGB8, GL_RGBA8)
+ * \param[in] type OpenGL pixel data type (e.g., GL_UNSIGNED_BYTE, GL_FLOAT)
  * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture
  * \param[in] filter GL texture filter setting
  *
@@ -285,14 +287,18 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd)
  * is useful for uploading static data like lookup tables or uniform color
  * matrices to the GPU.
  */
-void eGL::createTexture2D(eGLImage &eglImage, void *data, GLint filter)
+void eGL::createTexture2D(eGLImage &eglImage,
+			  GLint internalFormat,
+			  GLenum type,
+			  const void *data,
+			  GLint filter)
 {
 	ASSERT(tid_ == Thread::currentId());
 
 	activateBindTexture(eglImage);
 
 	// Generate texture, bind, associate image to texture, configure, unbind
-	glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data);
+	glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, eglImage.width_, eglImage.height_, 0, eglImage.format_, type, data);
 
 	// Nearest filtering
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
@@ -338,7 +344,7 @@ EGLDisplay eGL::probeDisplay()
  *
  * Updates a 2D texture in VRAM.
  */
-void eGL::updateTexture2D(eGLImage &eglImage, void *data)
+void eGL::updateTexture2D(eGLImage &eglImage, const void *data)
 {
 	ASSERT(tid_ == Thread::currentId());
 
@@ -357,7 +363,7 @@ void eGL::updateTexture2D(eGLImage &eglImage, void *data)
  */
 void eGL::createOutputTexture2D(eGLImage &eglImage)
 {
-	createTexture2D(eglImage, NULL, GL_NEAREST);
+	createTexture2D(eglImage, eglImage.format_, GL_UNSIGNED_BYTE, NULL, GL_NEAREST);
 	attachTextureToFBO(eglImage);
 }
 
diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
index e03fef684..5227d2bbd 100644
--- a/src/libcamera/software_isp/debayer_egl.cpp
+++ b/src/libcamera/software_isp/debayer_egl.cpp
@@ -536,7 +536,11 @@ eGLImage *DebayerEGL::getCachedInputFrameBuffer(FrameBuffer *input, std::optiona
 		return nullptr;
 	}
 	if (cache_miss)
-		egl_.createTexture2D(*eglImageIn, inMapped->value().planes()[0].data(), GL_NEAREST);
+		egl_.createTexture2D(*eglImageIn,
+				     eglImageIn->format_,
+				     GL_UNSIGNED_BYTE,
+				     inMapped->value().planes()[0].data(),
+				     GL_NEAREST);
 	else
 		egl_.updateTexture2D(*eglImageIn, inMapped->value().planes()[0].data());
 
