@@ -153,7 +153,6 @@ int eGL::attachTextureToFBO(eGLImage &eglImage)
int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output)
{
EGLint drm_format;
- int ret;
ASSERT(tid_ == Thread::currentId());
@@ -213,10 +212,7 @@ int eGL::createDMABufTexture2D(eGLImage &eglImage, int fd, bool output)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- if (output)
- ret = attachTextureToFBO(eglImage);
-
- return ret;
+ return 0;
}
/**
@@ -41,7 +41,7 @@ namespace libcamera {
* \param[in] cm The camera manager
*/
SoftwareIspPipelineGpu::SoftwareIspPipelineGpu(std::unique_ptr<SwStatsCpu> stats, const CameraManager &cm)
- : SoftwareIspPipeline(cm), stats_(std::move(stats))
+ : SoftwareIspPipeline(cm), stats_(std::move(stats)), gpuIspShaderPassDemosiac_(egl_)
{
}
@@ -109,186 +109,13 @@ int SoftwareIspPipelineGpu::getOutputConfig(PixelFormat outputFormat, DebayerOut
return -EINVAL;
}
-int SoftwareIspPipelineGpu::getShaderVariableLocations(void)
-{
- attributeVertex_ = glGetAttribLocation(programId_, "vertexIn");
- attributeTexture_ = glGetAttribLocation(programId_, "textureIn");
-
- textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y");
- ccmUniformDataIn_ = glGetUniformLocation(programId_, "ccm");
- blackLevelUniformDataIn_ = glGetUniformLocation(programId_, "blacklevel");
- gammaUniformDataIn_ = glGetUniformLocation(programId_, "gamma");
- contrastExpUniformDataIn_ = glGetUniformLocation(programId_, "contrastExp");
-
- textureUniformStep_ = glGetUniformLocation(programId_, "tex_step");
- textureUniformSize_ = glGetUniformLocation(programId_, "tex_size");
- textureUniformStrideFactor_ = glGetUniformLocation(programId_, "stride_factor");
- textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red");
- textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix");
-
- LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
- << " tex_y " << textureUniformBayerDataIn_
- << " ccm " << ccmUniformDataIn_
- << " blacklevel " << blackLevelUniformDataIn_
- << " gamma " << gammaUniformDataIn_
- << " contrastExp " << contrastExpUniformDataIn_
- << " tex_step " << textureUniformStep_
- << " tex_size " << textureUniformSize_
- << " stride_factor " << textureUniformStrideFactor_
- << " tex_bayer_first_red " << textureUniformBayerFirstRed_
- << " proj_matrix " << textureUniformProjMatrix_;
- return 0;
-}
-
int SoftwareIspPipelineGpu::initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat)
{
- std::vector<std::string> shaderEnv;
- unsigned int fragmentShaderDataLen = 0;
- const unsigned char *fragmentShaderData = 0;
- unsigned int vertexShaderDataLen = 0;
- const unsigned char *vertexShaderData = 0;
- GLenum err;
-
- /* Target gles 100 glsl requires "#version x" as first directive in shader */
- egl_.pushEnv(shaderEnv, "#version 100");
-
- /* Specify GL_OES_EGL_image_external */
- egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable");
-
- /*
- * Tell shaders how to re-order output taking account of how the pixels
- * are actually stored by EGL.
- */
- switch (outputFormat) {
- case formats::ARGB8888:
- case formats::XRGB8888:
- break;
- case formats::ABGR8888:
- case formats::XBGR8888:
- egl_.pushEnv(shaderEnv, "#define SWAP_BLUE");
- break;
- default:
- LOG(Debayer, Error) << "Unsupported output format";
- return -EINVAL;
- }
-
- /* Pixel location parameters */
- glFormat_ = GL_LUMINANCE;
- bytesPerPixel_ = 1;
- shaderStridePixels_ = inputConfig_.stride;
-
- switch (inputFormat) {
- case libcamera::formats::SBGGR8:
- case libcamera::formats::SBGGR10_CSI2P:
- case libcamera::formats::SBGGR12_CSI2P:
- firstRed_x_ = 1.0;
- firstRed_y_ = 1.0;
- break;
- case libcamera::formats::SGBRG8:
- case libcamera::formats::SGBRG10_CSI2P:
- case libcamera::formats::SGBRG12_CSI2P:
- firstRed_x_ = 0.0;
- firstRed_y_ = 1.0;
- break;
- case libcamera::formats::SGRBG8:
- case libcamera::formats::SGRBG10_CSI2P:
- case libcamera::formats::SGRBG12_CSI2P:
- firstRed_x_ = 1.0;
- firstRed_y_ = 0.0;
- break;
- case libcamera::formats::SRGGB8:
- case libcamera::formats::SRGGB10_CSI2P:
- case libcamera::formats::SRGGB12_CSI2P:
- firstRed_x_ = 0.0;
- firstRed_y_ = 0.0;
- break;
- default:
- LOG(Debayer, Error) << "Unsupported input format";
- return -EINVAL;
- };
-
- /* Shader selection */
- switch (inputFormat) {
- case libcamera::formats::SBGGR8:
- case libcamera::formats::SGBRG8:
- case libcamera::formats::SGRBG8:
- case libcamera::formats::SRGGB8:
- fragmentShaderData = bayer_unpacked_frag;
- fragmentShaderDataLen = bayer_unpacked_frag_len;
- vertexShaderData = bayer_unpacked_vert;
- vertexShaderDataLen = bayer_unpacked_vert_len;
- break;
- case libcamera::formats::SBGGR10_CSI2P:
- case libcamera::formats::SGBRG10_CSI2P:
- case libcamera::formats::SGRBG10_CSI2P:
- case libcamera::formats::SRGGB10_CSI2P:
- egl_.pushEnv(shaderEnv, "#define RAW10P");
- if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) {
- fragmentShaderData = bayer_unpacked_frag;
- fragmentShaderDataLen = bayer_unpacked_frag_len;
- vertexShaderData = bayer_unpacked_vert;
- vertexShaderDataLen = bayer_unpacked_vert_len;
- glFormat_ = GL_RG;
- bytesPerPixel_ = 2;
- } else {
- fragmentShaderData = bayer_1x_packed_frag;
- fragmentShaderDataLen = bayer_1x_packed_frag_len;
- vertexShaderData = identity_vert;
- vertexShaderDataLen = identity_vert_len;
- shaderStridePixels_ = width_;
- }
- break;
- case libcamera::formats::SBGGR12_CSI2P:
- case libcamera::formats::SGBRG12_CSI2P:
- case libcamera::formats::SGRBG12_CSI2P:
- case libcamera::formats::SRGGB12_CSI2P:
- egl_.pushEnv(shaderEnv, "#define RAW12P");
- if (BayerFormat::fromPixelFormat(inputFormat).packing == BayerFormat::Packing::None) {
- fragmentShaderData = bayer_unpacked_frag;
- fragmentShaderDataLen = bayer_unpacked_frag_len;
- vertexShaderData = bayer_unpacked_vert;
- vertexShaderDataLen = bayer_unpacked_vert_len;
- glFormat_ = GL_RG;
- bytesPerPixel_ = 2;
- } else {
- fragmentShaderData = bayer_1x_packed_frag;
- fragmentShaderDataLen = bayer_1x_packed_frag_len;
- vertexShaderData = identity_vert;
- vertexShaderDataLen = identity_vert_len;
- shaderStridePixels_ = width_;
- }
- break;
- };
-
- if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv)) {
- LOG(Debayer, Error) << "Compile vertex shader fail";
- return -ENODEV;
- }
- utils::scope_exit vShaderGuard([&] { glDeleteShader(vertexShaderId_); });
-
- if (egl_.compileFragmentShader(fragmentShaderId_, fragmentShaderData, fragmentShaderDataLen, shaderEnv)) {
- LOG(Debayer, Error) << "Compile fragment shader fail";
- return -ENODEV;
- }
- utils::scope_exit fShaderGuard([&] { glDeleteShader(fragmentShaderId_); });
+ int ret;
- if (egl_.linkProgram(programId_, vertexShaderId_, fragmentShaderId_)) {
- LOG(Debayer, Error) << "Linking program fail";
- return -ENODEV;
- }
-
- egl_.dumpShaderSource(vertexShaderId_);
- egl_.dumpShaderSource(fragmentShaderId_);
-
- /* Ensure we set the programId_ */
- egl_.useProgram(programId_);
- err = glGetError();
- if (err != GL_NO_ERROR) {
- LOG(Debayer, Error) << "Use program error " << err;
- return -ENODEV;
- }
+ ret = gpuIspShaderPassDemosiac_.initShaders(inputFormat, outputFormat);
- return getShaderVariableLocations();
+ return ret;
}
int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg,
@@ -351,6 +178,12 @@ int SoftwareIspPipelineGpu::configure(const StreamConfiguration &inputCfg,
*/
stats_->setWindow(Rectangle(window_.size()));
+ /* Configure for one pass */
+ PassConfig rawSensorIn = { inputCfg.size, inputConfig_.stride, inputPixelFormat_, window_ };
+ PassConfig rgbaOut = { outputCfg.size, outputConfig_.stride, outputPixelFormat_, Rectangle(outputSize_) };
+
+ gpuIspShaderPassDemosiac_.configure(rawSensorIn, rgbaOut);
+
return 0;
}
@@ -388,132 +221,10 @@ SoftwareIspPipelineGpu::strideAndFrameSize(const PixelFormat &outputFormat, cons
return std::make_tuple(stride, stride * size.height);
}
-void SoftwareIspPipelineGpu::setShaderVariableValues(const DebayerParams ¶ms)
-{
- /*
- * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-bit formats
- * are stored in a GL_LUMINANCE texture. The texture width is
- * equal to the stride.
- */
- GLfloat firstRed[] = { firstRed_x_, firstRed_y_ };
- GLfloat imgSize[] = { (GLfloat)width_,
- (GLfloat)height_ };
- GLfloat Step[] = { static_cast<float>(bytesPerPixel_) / (inputConfig_.stride - 1),
- 1.0f / (height_ - 1) };
- GLfloat Stride = (GLfloat)width_ / (shaderStridePixels_ / bytesPerPixel_);
- /*
- * Scale input to output size, keeping the aspect ratio and preferring
- * cropping over black bars.
- */
- GLfloat scale = std::max((GLfloat)window_.width / width_,
- (GLfloat)window_.height / height_);
- GLfloat trans = -(1.0f - scale);
- GLfloat projMatrix[] = {
- scale, 0, 0, 0,
- 0, scale, 0, 0,
- 0, 0, 1, 0,
- trans, trans, 0, 1
- };
- /* Static const coordinates */
- static const GLfloat vcoordinates[4][2] = {
- { -1.0f, -1.0f },
- { -1.0f, +1.0f },
- { +1.0f, +1.0f },
- { +1.0f, -1.0f },
- };
- static const GLfloat tcoordinates[4][2] = {
- { 0.0f, 0.0f },
- { 0.0f, 1.0f },
- { 1.0f, 1.0f },
- { 1.0f, 0.0f },
- };
-
- /* vertexIn - bayer_8.vert */
- glEnableVertexAttribArray(attributeVertex_);
- glVertexAttribPointer(attributeVertex_, 2, GL_FLOAT, GL_TRUE,
- 2 * sizeof(GLfloat), vcoordinates);
-
- /* textureIn - bayer_8.vert */
- glEnableVertexAttribArray(attributeTexture_);
- glVertexAttribPointer(attributeTexture_, 2, GL_FLOAT, GL_TRUE,
- 2 * sizeof(GLfloat), tcoordinates);
-
- /*
- * Set the sampler2D to the respective texture unit for each texutre
- * To simultaneously sample multiple textures we need to use multiple
- * texture units
- */
- glUniform1i(textureUniformBayerDataIn_, eglImageBayerIn_->texture_unit_uniform_id_);
-
- /*
- * These values are:
- * firstRed = tex_bayer_first_red - bayer_8.vert
- * imgSize = tex_size - bayer_8.vert
- * step = tex_step - bayer_8.vert
- * Stride = stride_factor identity.vert
- * textureUniformProjMatri = No scaling
- */
- glUniform2fv(textureUniformBayerFirstRed_, 1, firstRed);
- glUniform2fv(textureUniformSize_, 1, imgSize);
- glUniform2fv(textureUniformStep_, 1, Step);
- glUniform1f(textureUniformStrideFactor_, Stride);
- glUniformMatrix4fv(textureUniformProjMatrix_, 1, GL_FALSE, projMatrix);
-
- LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
- << " tex_y " << textureUniformBayerDataIn_
- << " tex_step " << textureUniformStep_
- << " tex_size " << textureUniformSize_
- << " stride_factor " << textureUniformStrideFactor_
- << " tex_bayer_first_red " << textureUniformBayerFirstRed_;
-
- LOG(Debayer, Debug) << "textureUniformY_ = 0 "
- << " firstRed.x " << firstRed[0]
- << " firstRed.y " << firstRed[1]
- << " textureUniformSize_.width " << imgSize[0]
- << " textureUniformSize_.height " << imgSize[1]
- << " textureUniformStep_.x " << Step[0]
- << " textureUniformStep_.y " << Step[1]
- << " textureUniformStrideFactor_ " << Stride
- << " textureUniformProjMatrix_ " << textureUniformProjMatrix_;
-
- GLfloat ccm[9] = {
- params.combinedMatrix[0][0],
- params.combinedMatrix[0][1],
- params.combinedMatrix[0][2],
- params.combinedMatrix[1][0],
- params.combinedMatrix[1][1],
- params.combinedMatrix[1][2],
- params.combinedMatrix[2][0],
- params.combinedMatrix[2][1],
- params.combinedMatrix[2][2],
- };
- glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm);
- LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix;
-
- /*
- * 0 = Red, 1 = Green, 2 = Blue
- */
- glUniform3f(blackLevelUniformDataIn_, params.blackLevel[0], params.blackLevel[1], params.blackLevel[2]);
- LOG(Debayer, Debug) << " blackLevelUniformDataIn_ " << blackLevelUniformDataIn_ << " data " << params.blackLevel;
-
- /*
- * Gamma
- */
- glUniform1f(gammaUniformDataIn_, params.gamma);
- LOG(Debayer, Debug) << " gammaUniformDataIn_ " << gammaUniformDataIn_ << " data " << params.gamma;
-
- /*
- * Contrast
- */
- glUniform1f(contrastExpUniformDataIn_, params.contrastExp);
- LOG(Debayer, Debug) << " contrastExpUniformDataIn_ " << contrastExpUniformDataIn_ << " data " << params.contrastExp;
-
- return;
-}
-
int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)
{
bool dmabuf_import_succeeded = false;
+ int pipelineResult = 0;
/* eGL context switch */
egl_.makeCurrent();
@@ -540,20 +251,17 @@ int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output,
/* Generate the output render framebuffer as render to texture */
egl_.createOutputDMABufTexture2D(*eglImageRGBAOut_, output->planes()[0].fd.get());
- setShaderVariableValues(params);
- glViewport(0, 0, width_, height_);
- glClear(GL_COLOR_BUFFER_BIT);
- glDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS);
+ pipelineResult = gpuIspShaderPassDemosiac_.process(*eglImageBayerIn_, *eglImageRGBAOut_, width_, height_, params);
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
LOG(eGL, Error) << "Drawing scene fail " << err;
- return -ENODEV;
+ pipelineResult = -ENODEV;
} else {
egl_.flushOutput();
}
- return 0;
+ return pipelineResult;
}
void SoftwareIspPipelineGpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms)
@@ -623,7 +331,7 @@ int SoftwareIspPipelineGpu::start()
return -EINVAL;
/* Raw bayer input as texture */
- eglImageBayerIn_ = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0);
+ eglImageBayerIn_ = std::make_unique<eGLImage>(gpuIspShaderPassDemosiac_.glFormat_, inputConfig_.stride / gpuIspShaderPassDemosiac_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0);
/* Texture we will render to */
eglImageRGBAOut_ = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);
@@ -636,8 +344,7 @@ void SoftwareIspPipelineGpu::stop()
eglImageRGBAOut_.reset();
eglImageBayerIn_.reset();
- if (programId_)
- glDeleteProgram(programId_);
+ gpuIspShaderPassDemosiac_.stop();
}
SizeRange SoftwareIspPipelineGpu::sizes(PixelFormat inputFormat, const Size &inputSize)
@@ -23,16 +23,12 @@
#include "libcamera/internal/software_isp/benchmark.h"
#include "libcamera/internal/software_isp/swstats_cpu.h"
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES3/gl32.h>
-
#include "software_isp_pipeline.h"
+#include "gpu_pipeline_shader_pass_demosiac.h"
namespace libcamera {
#define DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS 4
-#define DEBAYER_OPENGL_COORDS 4
class CameraManager;
@@ -68,48 +64,17 @@ private:
int processGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional<MappedFrameBuffer> *mappedInputBuffer, std::optional<DmaSyncer> *inputBufferDmaSyncer);
void configureTexture(GLuint &texture);
- /* Shader program identifiers */
- GLuint vertexShaderId_ = 0;
- GLuint fragmentShaderId_ = 0;
- GLuint programId_ = 0;
-
/* Pointer to object representing input texture */
std::unique_ptr<eGLImage> eglImageBayerIn_;
std::unique_ptr<eGLImage> eglImageRGBAOut_;
- /* Shader parameters */
- float firstRed_x_;
- float firstRed_y_;
- GLint attributeVertex_;
- GLint attributeTexture_;
- GLint textureUniformStep_;
- GLint textureUniformSize_;
- GLint textureUniformStrideFactor_;
- GLint textureUniformBayerFirstRed_;
- GLint textureUniformProjMatrix_;
-
- GLint textureUniformBayerDataIn_;
-
- /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */
- GLint ccmUniformDataIn_;
-
- /* Black Level compensation */
- GLint blackLevelUniformDataIn_;
-
- /* Gamma */
- GLint gammaUniformDataIn_;
-
- /* Contrast */
- GLint contrastExpUniformDataIn_;
-
Rectangle window_;
std::unique_ptr<SwStatsCpu> stats_;
eGL egl_;
uint32_t width_;
uint32_t height_;
- GLint glFormat_;
- unsigned int bytesPerPixel_;
- uint32_t shaderStridePixels_;
+
+ GpuIspShaderPassDemosiac gpuIspShaderPassDemosiac_;
};
} /* namespace libcamera */
Switch to using GpuIspShaderPassDemosiac as the first instance of our multi-pass GPUISP implementation. Subsequent patches will move elements of this leviathan into discreet elements with an objective of eliminating register spill, separation of concerns and de-spaghettification. Code red patches are always best. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> --- src/libcamera/egl.cpp | 6 +- .../software_isp_pipeline_gpu.cpp | 325 +----------------- .../software_isp/software_isp_pipeline_gpu.h | 41 +-- 3 files changed, 20 insertions(+), 352 deletions(-)