[4/7] software-isp: Allow drawing into existing EGL textures
diff mbox series

Message ID 20261016202916.1405813-5-halfline@gmail.com
State Rejected
Headers show
Series
  • tests: Separate suites and check software ISP crops
Related show

Commit Message

Ray Strode Oct. 16, 2026, 8:29 p.m. UTC
From: Ray Strode <rstrode@redhat.com>

This commit lets EGL debayering use textures supplied by the caller for its
input and output.

The drawing path currently obtains its textures from frame buffers, and the
output requires DMA-BUF import. Integration tests need to exercise the same
shaders, uniforms, projection and viewport with CPU-uploaded textures on
software renderers that do not support that import path.

The frame-processing path uses the same drawing operation after obtaining
its textures. Buffer import, synchronization and statistics stay with frame
processing. Drawing reports an incomplete output framebuffer as an error.

Signed-off-by: Ray Strode <rstrode@redhat.com>
---
 src/libcamera/software_isp/debayer_egl.cpp | 25 ++++++++++++++++++++--
 src/libcamera/software_isp/debayer_egl.h   |  3 +++
 2 files changed, 26 insertions(+), 2 deletions(-)

Comments

Bryan O'Donoghue Oct. 30, 2026, 3:29 p.m. UTC | #1
On 16/10/2026 21:29, Ray Strode wrote:
> From: Ray Strode <rstrode@redhat.com>
> 
> This commit lets EGL debayering use textures supplied by the caller for its
> input and output.
> 
> The drawing path currently obtains its textures from frame buffers, and the
> output requires DMA-BUF import. Integration tests need to exercise the same
> shaders, uniforms, projection and viewport with CPU-uploaded textures on
> software renderers that do not support that import path.
> 
> The frame-processing path uses the same drawing operation after obtaining
> its textures. Buffer import, synchronization and statistics stay with frame
> processing. Drawing reports an incomplete output framebuffer as an error.
> 
> Signed-off-by: Ray Strode <rstrode@redhat.com>
> ---
>   src/libcamera/software_isp/debayer_egl.cpp | 25 ++++++++++++++++++++--
>   src/libcamera/software_isp/debayer_egl.h   |  3 +++
>   2 files changed, 26 insertions(+), 2 deletions(-)
> 
> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
> index cd9ad888..afe78384 100644
> --- a/src/libcamera/software_isp/debayer_egl.cpp
> +++ b/src/libcamera/software_isp/debayer_egl.cpp
> @@ -573,8 +573,29 @@ int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const Debaye
>   	if (!eglImageOut)
>   		return -ENOMEM;
> 
> -	egl_.attachTextureToFBO(*eglImageOut);
> -	setShaderVariableValues(*eglImageIn, params);
> +	return render(*eglImageIn, *eglImageOut, params);
> +}
> +
> +/**
> + * \brief Render the configured debayer operation into existing textures
> + * \param[in] input Texture containing the configured Bayer input
> + * \param[in,out] output Texture receiving the configured output image
> + * \param[in] params Image processing parameters
> + *
> + * The caller owns the texture storage and must start the debayer before
> + * rendering. Textures must belong to the debayer's current EGL context.
> + *
> + * \return 0 on success or a negative error code otherwise
> + */
> +int DebayerEGL::render(eGLImage &input, eGLImage &output, const DebayerParams &params)
> +{
> +	egl_.assertThread();
> +
> +	int ret = egl_.attachTextureToFBO(output);
> +	if (ret)
> +		return ret;
> +
> +	setShaderVariableValues(input, params);
> 
>   	glViewport(0, 0, width_, height_);
>   	glClear(GL_COLOR_BUFFER_BIT);
> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
> index 5a4cd2d8..d18dc3fb 100644
> --- a/src/libcamera/software_isp/debayer_egl.h
> +++ b/src/libcamera/software_isp/debayer_egl.h
> @@ -62,6 +62,9 @@ public:
>   	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;
>   	Rectangle inputCrop() const override { return inputCrop_; }
> 
> +protected:
> +	int render(eGLImage &input, eGLImage &output, const DebayerParams &params);
> +
>   private:
>   	static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
>   	int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat);
> --
> 2.56.0

Without reading the rest of the series I _assume_ you're extending this 
class into some kind of CI/test object, in which case protected makes sense.

Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

Patch
diff mbox series

diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
index cd9ad888..afe78384 100644
--- a/src/libcamera/software_isp/debayer_egl.cpp
+++ b/src/libcamera/software_isp/debayer_egl.cpp
@@ -573,8 +573,29 @@  int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const Debaye
 	if (!eglImageOut)
 		return -ENOMEM;
 
-	egl_.attachTextureToFBO(*eglImageOut);
-	setShaderVariableValues(*eglImageIn, params);
+	return render(*eglImageIn, *eglImageOut, params);
+}
+
+/**
+ * \brief Render the configured debayer operation into existing textures
+ * \param[in] input Texture containing the configured Bayer input
+ * \param[in,out] output Texture receiving the configured output image
+ * \param[in] params Image processing parameters
+ *
+ * The caller owns the texture storage and must start the debayer before
+ * rendering. Textures must belong to the debayer's current EGL context.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int DebayerEGL::render(eGLImage &input, eGLImage &output, const DebayerParams &params)
+{
+	egl_.assertThread();
+
+	int ret = egl_.attachTextureToFBO(output);
+	if (ret)
+		return ret;
+
+	setShaderVariableValues(input, params);
 
 	glViewport(0, 0, width_, height_);
 	glClear(GL_COLOR_BUFFER_BIT);
diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
index 5a4cd2d8..d18dc3fb 100644
--- a/src/libcamera/software_isp/debayer_egl.h
+++ b/src/libcamera/software_isp/debayer_egl.h
@@ -62,6 +62,9 @@  public:
 	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;
 	Rectangle inputCrop() const override { return inputCrop_; }
 
+protected:
+	int render(eGLImage &input, eGLImage &output, const DebayerParams &params);
+
 private:
 	static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
 	int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat);