| Message ID | 20260618122245.946138-6-bryan.odonoghue@linaro.org |
|---|---|
| State | RFC |
| Headers | show |
| Series |
|
| Related | show |
Bryan O'Donoghue <bryan.odonoghue@linaro.org> writes: > Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> > --- > .../software_isp/gpu_pipeline_shader_pass.cpp | 74 +++++++++++++++++ > .../software_isp/gpu_pipeline_shader_pass.h | 83 +++++++++++++++++++ > src/libcamera/software_isp/meson.build | 1 + > 3 files changed, 158 insertions(+) > create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp > create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass.h > > diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp > new file mode 100644 > index 000000000..669a1c1b6 > --- /dev/null > +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp > @@ -0,0 +1,74 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2026, Linaro Ltd > + * > + * Simple software ISP implementation > + */ > + > +#include <cmath> > +#include <stdint.h> > +#include <sys/mman.h> > +#include <sys/types.h> > +#include <unistd.h> > + > +#include <libcamera/base/log.h> > +#include <libcamera/base/thread.h> > +#include <libcamera/base/utils.h> > + > +#include <libcamera/controls.h> > +#include <libcamera/formats.h> > +#include <libcamera/stream.h> > + > +#include "libcamera/internal/framebuffer.h" > +#include "libcamera/internal/ipa_manager.h" > +#include "libcamera/internal/software_isp/debayer_params.h" > + > +#include "gpu_pipeline_shader_pass.h" > + > +/** > + * \file software_isp.cpp > + * \brief Simple software ISP implementation > + */ > + > +namespace libcamera { > + > +LOG_DEFINE_CATEGORY(GpuShaderPass) > + > +int GpuIspShaderPass::process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint32_t width, uint32_t height, const DebayerParams ¶ms) > +{ > + /* Switch to the output framebuffer */ > + egl_.useProgram(programId_); > + egl_.attachTextureToFBO(eglImageOut); > + > + setShaderVariableValues(params, eglImageIn); > + glViewport(0, 0, width, height); > + glClear(GL_COLOR_BUFFER_BIT); > + glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS); > + > + GLenum err = glGetError(); > + if (err != GL_NO_ERROR) { > + LOG(GpuShaderPass, Error) << "Drawing scene fail " << err; > + return -ENODEV; I wonder in some places what device is missing... > + } > + > + return 0; > +} > + > +int GpuIspShaderPass::start() > +{ > + return 0; > +} > + > +void GpuIspShaderPass::stop() > +{ > + if (programId_) > + glDeleteProgram(programId_); > +} > + > +void GpuIspShaderPass::configure(const struct PassConfig &passInputCfg, const struct PassConfig &passOutputCfg) > +{ > + passInputCfg_ = passInputCfg; > + passOutputCfg_ = passOutputCfg; > +} > + > +} > diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h > new file mode 100644 > index 000000000..d4d4cf34d > --- /dev/null > +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h > @@ -0,0 +1,83 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2026, Linaro Ltd > + * > + * Authors: > + * Bryan O'Donoghue <bryan.odonoghue@linaro.org> > + * > + * GpuIspIspShaderPass base class > + */ > + > +#pragma once > + > +#include <stdint.h> > + > +#include <libcamera/base/log.h> > +#include <libcamera/base/object.h> > +#include <libcamera/base/signal.h> > + > +#include <libcamera/geometry.h> > +#include <libcamera/stream.h> > + > +#include "libcamera/internal/egl.h" > +#include "libcamera/internal/software_isp/debayer_params.h" > + > +#include <EGL/egl.h> > +#include <EGL/eglext.h> > +#include <GLES3/gl32.h> > + > +#include "../glsl_shaders.h" > + > +namespace libcamera { > + > +#define DEBAYER_OPENGL_COORDS 4 > + > +class FrameBuffer; > + > +struct PassConfig { > + Size size; > + unsigned int stride; > + PixelFormat format; > + Rectangle window; > +}; > + > +class GpuIspShaderPass : public Object > +{ > +public: > + GpuIspShaderPass(eGL& egl) : egl_(egl) {} > + ~GpuIspShaderPass() {} > + > + virtual int process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint32_t width, uint32_t height, const DebayerParams ¶ms); > + virtual int start(); > + virtual void stop(); > + virtual void configure(const struct PassConfig &passInputCfg, const struct PassConfig &passOutputCfg); > + virtual int initShaders(PixelFormat inputFormat, PixelFormat outputFormat) = 0; > + virtual int getShaderVariableLocations(void) = 0; s/void// > + virtual void setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn) = 0; > + virtual const char *name() const { return "GpuIspShaderPass"; } > + > + unsigned int getBytesPerPixel() { return bytesPerPixel_; }; > + > + /* glFormat_ is a special case we are moving to one shader which will use GL_R > + * so rather than do a hack make ShaderPasses do the Textrue allocation and thus have s/Textrue/texture/ > + * access to glFormat_. Make glFormat_ available to the upper level class. > + * This variabile will be dropped at the end of the series anyway. > + */ > + GLint glFormat_; > + > +protected: > + eGL& egl_; > + > + /* Shader calculates this getter provides ability to interrogate if needed */ I can't parse this sentence. > + unsigned int bytesPerPixel_; > + > + /* Shader program identifiers */ > + GLuint vertexShaderId_ = 0; > + GLuint fragmentShaderId_ = 0; > + GLuint programId_ = 0; > + > + struct PassConfig passInputCfg_; > + struct PassConfig passOutputCfg_; > +}; Looks reasonable at the first glance, let's see how it evolves in the followup patches. > + > +} /* namespace libcamera */ > diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build > index 51cc6ac3e..f8bce5203 100644 > --- a/src/libcamera/software_isp/meson.build > +++ b/src/libcamera/software_isp/meson.build > @@ -32,6 +32,7 @@ if mesa_works > libcamera_internal_sources += files([ > '../egl.cpp', > 'software_isp_pipeline_gpu.cpp', > + 'gpu_pipeline_shader_pass.cpp', > ]) > libcamera_deps += [ > libegl,
diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp new file mode 100644 index 000000000..669a1c1b6 --- /dev/null +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Linaro Ltd + * + * Simple software ISP implementation + */ + +#include <cmath> +#include <stdint.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <unistd.h> + +#include <libcamera/base/log.h> +#include <libcamera/base/thread.h> +#include <libcamera/base/utils.h> + +#include <libcamera/controls.h> +#include <libcamera/formats.h> +#include <libcamera/stream.h> + +#include "libcamera/internal/framebuffer.h" +#include "libcamera/internal/ipa_manager.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +#include "gpu_pipeline_shader_pass.h" + +/** + * \file software_isp.cpp + * \brief Simple software ISP implementation + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(GpuShaderPass) + +int GpuIspShaderPass::process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint32_t width, uint32_t height, const DebayerParams ¶ms) +{ + /* Switch to the output framebuffer */ + egl_.useProgram(programId_); + egl_.attachTextureToFBO(eglImageOut); + + setShaderVariableValues(params, eglImageIn); + glViewport(0, 0, width, height); + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS); + + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + LOG(GpuShaderPass, Error) << "Drawing scene fail " << err; + return -ENODEV; + } + + return 0; +} + +int GpuIspShaderPass::start() +{ + return 0; +} + +void GpuIspShaderPass::stop() +{ + if (programId_) + glDeleteProgram(programId_); +} + +void GpuIspShaderPass::configure(const struct PassConfig &passInputCfg, const struct PassConfig &passOutputCfg) +{ + passInputCfg_ = passInputCfg; + passOutputCfg_ = passOutputCfg; +} + +} diff --git a/src/libcamera/software_isp/gpu_pipeline_shader_pass.h b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h new file mode 100644 index 000000000..d4d4cf34d --- /dev/null +++ b/src/libcamera/software_isp/gpu_pipeline_shader_pass.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2026, Linaro Ltd + * + * Authors: + * Bryan O'Donoghue <bryan.odonoghue@linaro.org> + * + * GpuIspIspShaderPass base class + */ + +#pragma once + +#include <stdint.h> + +#include <libcamera/base/log.h> +#include <libcamera/base/object.h> +#include <libcamera/base/signal.h> + +#include <libcamera/geometry.h> +#include <libcamera/stream.h> + +#include "libcamera/internal/egl.h" +#include "libcamera/internal/software_isp/debayer_params.h" + +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES3/gl32.h> + +#include "../glsl_shaders.h" + +namespace libcamera { + +#define DEBAYER_OPENGL_COORDS 4 + +class FrameBuffer; + +struct PassConfig { + Size size; + unsigned int stride; + PixelFormat format; + Rectangle window; +}; + +class GpuIspShaderPass : public Object +{ +public: + GpuIspShaderPass(eGL& egl) : egl_(egl) {} + ~GpuIspShaderPass() {} + + virtual int process(eGLImage &eglImageIn, eGLImage &eglImageOut, uint32_t width, uint32_t height, const DebayerParams ¶ms); + virtual int start(); + virtual void stop(); + virtual void configure(const struct PassConfig &passInputCfg, const struct PassConfig &passOutputCfg); + virtual int initShaders(PixelFormat inputFormat, PixelFormat outputFormat) = 0; + virtual int getShaderVariableLocations(void) = 0; + virtual void setShaderVariableValues(const DebayerParams ¶ms, eGLImage &eglImageIn) = 0; + virtual const char *name() const { return "GpuIspShaderPass"; } + + unsigned int getBytesPerPixel() { return bytesPerPixel_; }; + + /* glFormat_ is a special case we are moving to one shader which will use GL_R + * so rather than do a hack make ShaderPasses do the Textrue allocation and thus have + * access to glFormat_. Make glFormat_ available to the upper level class. + * This variabile will be dropped at the end of the series anyway. + */ + GLint glFormat_; + +protected: + eGL& egl_; + + /* Shader calculates this getter provides ability to interrogate if needed */ + unsigned int bytesPerPixel_; + + /* Shader program identifiers */ + GLuint vertexShaderId_ = 0; + GLuint fragmentShaderId_ = 0; + GLuint programId_ = 0; + + struct PassConfig passInputCfg_; + struct PassConfig passOutputCfg_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index 51cc6ac3e..f8bce5203 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -32,6 +32,7 @@ if mesa_works libcamera_internal_sources += files([ '../egl.cpp', 'software_isp_pipeline_gpu.cpp', + 'gpu_pipeline_shader_pass.cpp', ]) libcamera_deps += [ libegl,
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> --- .../software_isp/gpu_pipeline_shader_pass.cpp | 74 +++++++++++++++++ .../software_isp/gpu_pipeline_shader_pass.h | 83 +++++++++++++++++++ src/libcamera/software_isp/meson.build | 1 + 3 files changed, 158 insertions(+) create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass.cpp create mode 100644 src/libcamera/software_isp/gpu_pipeline_shader_pass.h