qcam: viewfinder_gl: Support #define in shaders

Prepare the infrastructure to support defining preprocessor macros in
shaders:

- Rename the fragmentShaderSrc_ member to fragmentShaderFile_ to reflect
  better that it contains a file name, not shader source code
- Add a new fragmentShaderDefines_ member to store preprocessor macros
- Prepend the macros to the shader source before compiling it

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
Laurent Pinchart 2020-09-16 17:03:46 +03:00
parent 440028d6c9
commit 0bc03960da
2 changed files with 35 additions and 18 deletions

View file

@ -7,6 +7,8 @@
#include "viewfinder_gl.h" #include "viewfinder_gl.h"
#include <QByteArray>
#include <QFile>
#include <QImage> #include <QImage>
#include <libcamera/formats.h> #include <libcamera/formats.h>
@ -24,7 +26,7 @@ static const QList<libcamera::PixelFormat> supportedFormats{
ViewFinderGL::ViewFinderGL(QWidget *parent) ViewFinderGL::ViewFinderGL(QWidget *parent)
: QOpenGLWidget(parent), buffer_(nullptr), yuvData_(nullptr), : QOpenGLWidget(parent), buffer_(nullptr), yuvData_(nullptr),
fragmentShader_(nullptr), vertexShader_(nullptr), vertexShader_(nullptr), fragmentShader_(nullptr),
vertexBuffer_(QOpenGLBuffer::VertexBuffer), vertexBuffer_(QOpenGLBuffer::VertexBuffer),
textureU_(QOpenGLTexture::Target2D), textureU_(QOpenGLTexture::Target2D),
textureV_(QOpenGLTexture::Target2D), textureV_(QOpenGLTexture::Target2D),
@ -97,46 +99,49 @@ void ViewFinderGL::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format) bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format)
{ {
bool ret = true; bool ret = true;
fragmentShaderDefines_.clear();
switch (format) { switch (format) {
case libcamera::formats::NV12: case libcamera::formats::NV12:
horzSubSample_ = 2; horzSubSample_ = 2;
vertSubSample_ = 2; vertSubSample_ = 2;
fragmentShaderSrc_ = ":YUV_2_planes_UV.frag"; fragmentShaderFile_ = ":YUV_2_planes_UV.frag";
break; break;
case libcamera::formats::NV21: case libcamera::formats::NV21:
horzSubSample_ = 2; horzSubSample_ = 2;
vertSubSample_ = 2; vertSubSample_ = 2;
fragmentShaderSrc_ = ":YUV_2_planes_VU.frag"; fragmentShaderFile_ = ":YUV_2_planes_VU.frag";
break; break;
case libcamera::formats::NV16: case libcamera::formats::NV16:
horzSubSample_ = 2; horzSubSample_ = 2;
vertSubSample_ = 1; vertSubSample_ = 1;
fragmentShaderSrc_ = ":YUV_2_planes_UV.frag"; fragmentShaderFile_ = ":YUV_2_planes_UV.frag";
break; break;
case libcamera::formats::NV61: case libcamera::formats::NV61:
horzSubSample_ = 2; horzSubSample_ = 2;
vertSubSample_ = 1; vertSubSample_ = 1;
fragmentShaderSrc_ = ":YUV_2_planes_VU.frag"; fragmentShaderFile_ = ":YUV_2_planes_VU.frag";
break; break;
case libcamera::formats::NV24: case libcamera::formats::NV24:
horzSubSample_ = 1; horzSubSample_ = 1;
vertSubSample_ = 1; vertSubSample_ = 1;
fragmentShaderSrc_ = ":YUV_2_planes_UV.frag"; fragmentShaderFile_ = ":YUV_2_planes_UV.frag";
break; break;
case libcamera::formats::NV42: case libcamera::formats::NV42:
horzSubSample_ = 1; horzSubSample_ = 1;
vertSubSample_ = 1; vertSubSample_ = 1;
fragmentShaderSrc_ = ":YUV_2_planes_VU.frag"; fragmentShaderFile_ = ":YUV_2_planes_VU.frag";
break; break;
case libcamera::formats::YUV420: case libcamera::formats::YUV420:
horzSubSample_ = 2; horzSubSample_ = 2;
vertSubSample_ = 2; vertSubSample_ = 2;
fragmentShaderSrc_ = ":YUV_3_planes.frag"; fragmentShaderFile_ = ":YUV_3_planes.frag";
break; break;
case libcamera::formats::YVU420: case libcamera::formats::YVU420:
horzSubSample_ = 2; horzSubSample_ = 2;
vertSubSample_ = 2; vertSubSample_ = 2;
fragmentShaderSrc_ = ":YUV_3_planes.frag"; fragmentShaderFile_ = ":YUV_3_planes.frag";
break; break;
default: default:
ret = false; ret = false;
@ -168,11 +173,24 @@ bool ViewFinderGL::createFragmentShader()
int attributeVertex; int attributeVertex;
int attributeTexture; int attributeTexture;
/* Create Fragment Shader */ /*
* Create the fragment shader, compile it, and add it to the shader
* program. The #define macros stored in fragmentShaderDefines_, if
* any, are prepended to the source code.
*/
fragmentShader_ = new QOpenGLShader(QOpenGLShader::Fragment, this); fragmentShader_ = new QOpenGLShader(QOpenGLShader::Fragment, this);
/* Compile the fragment shader */ QFile file(fragmentShaderFile_);
if (!fragmentShader_->compileSourceFile(fragmentShaderSrc_)) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Shader" << fragmentShaderFile_ << "not found";
return false;
}
QString defines = fragmentShaderDefines_.join('\n') + "\n";
QByteArray src = file.readAll();
src.prepend(defines.toUtf8());
if (!fragmentShader_->compileSourceCode(src)) {
qWarning() << "[ViewFinderGL]:" << fragmentShader_->log(); qWarning() << "[ViewFinderGL]:" << fragmentShader_->log();
return false; return false;
} }

View file

@ -65,17 +65,16 @@ private:
QSize size_; QSize size_;
unsigned char *yuvData_; unsigned char *yuvData_;
/* OpenGL components for rendering */ /* Shaders */
QOpenGLShader *fragmentShader_;
QOpenGLShader *vertexShader_;
QOpenGLShaderProgram shaderProgram_; QOpenGLShaderProgram shaderProgram_;
QOpenGLShader *vertexShader_;
QOpenGLShader *fragmentShader_;
QString fragmentShaderFile_;
QStringList fragmentShaderDefines_;
/* Vertex buffer */ /* Vertex buffer */
QOpenGLBuffer vertexBuffer_; QOpenGLBuffer vertexBuffer_;
/* Fragment shader file name */
QString fragmentShaderSrc_;
/* YUV texture planars and parameters */ /* YUV texture planars and parameters */
GLuint textureUniformU_; GLuint textureUniformU_;
GLuint textureUniformV_; GLuint textureUniformV_;