Update TVScreen to OpenGL 3.3

pull/1291/head
Jon Beniston 2022-06-19 23:22:43 +01:00
rodzic 34ce5ae398
commit 94f93ee9ad
5 zmienionych plików z 321 dodań i 92 usunięć

Wyświetl plik

@ -20,25 +20,48 @@
#include "gui/glshadertvarray.h"
const QString GLShaderTVArray::m_strVertexShaderSourceArray = QString(
const QString GLShaderTVArray::m_strVertexShaderSourceArray2 = QString(
"uniform highp mat4 uMatrix;\n"
"attribute highp vec4 vertex;\n"
"attribute highp vec2 texCoord;\n"
"varying mediump vec2 texCoordVar;\n"
"void main() {\n"
" gl_Position = uMatrix * vertex;\n"
" texCoordVar = texCoord;\n"
"}\n");
"attribute highp vec4 vertex;\n"
"attribute highp vec2 texCoord;\n"
"varying mediump vec2 texCoordVar;\n"
"void main() {\n"
" gl_Position = uMatrix * vertex;\n"
" texCoordVar = texCoord;\n"
"}\n");
const QString GLShaderTVArray::m_strVertexShaderSourceArray = QString(
"#version 330\n"
"uniform highp mat4 uMatrix;\n"
"in highp vec4 vertex;\n"
"in highp vec2 texCoord;\n"
"out mediump vec2 texCoordVar;\n"
"void main() {\n"
" gl_Position = uMatrix * vertex;\n"
" texCoordVar = texCoord;\n"
"}\n");
const QString GLShaderTVArray::m_strFragmentShaderSourceColored2 = QString(
"uniform lowp sampler2D uTexture;\n"
"varying mediump vec2 texCoordVar;\n"
"void main() {\n"
" gl_FragColor = texture2D(uTexture, texCoordVar);\n"
"}\n");
const QString GLShaderTVArray::m_strFragmentShaderSourceColored = QString(
"#version 330\n"
"uniform lowp sampler2D uTexture;\n"
"varying mediump vec2 texCoordVar;\n"
"void main() {\n"
" gl_FragColor = texture2D(uTexture, texCoordVar);\n"
"}\n");
"in mediump vec2 texCoordVar;\n"
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = texture(uTexture, texCoordVar);\n"
"}\n");
GLShaderTVArray::GLShaderTVArray(bool blnColor) :
m_objProgram(nullptr),
m_vao(nullptr),
m_verticesBuf(nullptr),
m_textureCoordsBuf(nullptr),
m_matrixLoc(0),
m_textureLoc(0),
m_objImage(nullptr),
@ -59,7 +82,7 @@ GLShaderTVArray::~GLShaderTVArray()
cleanup();
}
void GLShaderTVArray::initializeGL(int intCols, int intRows)
void GLShaderTVArray::initializeGL(int majorVersion, int minorVersion, int intCols, int intRows)
{
QMatrix4x4 objQMatrix;
@ -73,20 +96,43 @@ void GLShaderTVArray::initializeGL(int intCols, int intRows)
if (!m_objProgram)
{
m_objProgram = new QOpenGLShaderProgram();
if (!m_objProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
m_strVertexShaderSourceArray))
if ((majorVersion > 3) || ((majorVersion == 3) && (minorVersion >= 3)))
{
qDebug() << "GLShaderArray::initializeGL: error in vertex shader: "
<< m_objProgram->log();
if (!m_objProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
m_strVertexShaderSourceArray))
{
qDebug() << "GLShaderArray::initializeGL: error in vertex shader: "
<< m_objProgram->log();
}
if (!m_objProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
m_strFragmentShaderSourceColored))
{
qDebug()
<< "GLShaderArray::initializeGL: error in fragment shader: "
<< m_objProgram->log();
}
m_vao = new QOpenGLVertexArrayObject();
m_vao->create();
m_vao->bind();
}
if (!m_objProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
m_strFragmentShaderSourceColored))
else
{
qDebug()
<< "GLShaderArray::initializeGL: error in fragment shader: "
<< m_objProgram->log();
if (!m_objProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
m_strVertexShaderSourceArray2))
{
qDebug() << "GLShaderArray::initializeGL: error in vertex shader: "
<< m_objProgram->log();
}
if (!m_objProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
m_strFragmentShaderSourceColored2))
{
qDebug()
<< "GLShaderArray::initializeGL: error in fragment shader: "
<< m_objProgram->log();
}
}
m_objProgram->bindAttributeLocation("vertex", 0);
@ -100,6 +146,16 @@ void GLShaderTVArray::initializeGL(int intCols, int intRows)
m_objProgram->bind();
m_objProgram->setUniformValue(m_matrixLoc, objQMatrix);
m_objProgram->setUniformValue(m_textureLoc, 0);
if (m_vao)
{
m_verticesBuf = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_verticesBuf->setUsagePattern(QOpenGLBuffer::DynamicDraw);
m_verticesBuf->create();
m_textureCoordsBuf = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_textureCoordsBuf->setUsagePattern(QOpenGLBuffer::DynamicDraw);
m_textureCoordsBuf->create();
m_vao->release();
}
m_objProgram->release();
}
@ -232,17 +288,41 @@ void GLShaderTVArray::RenderPixels(unsigned char *chrData)
ptrF->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_intCols, m_intRows, GL_RGBA,
GL_UNSIGNED_BYTE, m_objImage->bits());
ptrF->glEnableVertexAttribArray(0); // vertex
ptrF->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, arrVertices);
if (m_vao)
{
m_vao->bind();
ptrF->glEnableVertexAttribArray(1); // texture coordinates
ptrF->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, arrTextureCoords);
m_verticesBuf->bind();
m_verticesBuf->allocate(arrVertices, intNbVertices * 2 * sizeof(GL_FLOAT));
m_objProgram->enableAttributeArray(0);
m_objProgram->setAttributeBuffer(0, GL_FLOAT, 0, 2);
m_textureCoordsBuf->bind();
m_textureCoordsBuf->allocate(arrTextureCoords, intNbVertices * 2 * sizeof(GL_FLOAT));
m_objProgram->enableAttributeArray(1);
m_objProgram->setAttributeBuffer(1, GL_FLOAT, 0, 2);
}
else
{
ptrF->glEnableVertexAttribArray(0); // vertex
ptrF->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, arrVertices);
ptrF->glEnableVertexAttribArray(1); // texture coordinates
ptrF->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, arrTextureCoords);
}
ptrF->glDrawArrays(GL_TRIANGLES, 0, intNbVertices);
//cleanup
ptrF->glDisableVertexAttribArray(0);
ptrF->glDisableVertexAttribArray(1);
if (m_vao)
{
m_vao->release();
}
else
{
ptrF->glDisableVertexAttribArray(0);
ptrF->glDisableVertexAttribArray(1);
}
//*********************//
@ -294,6 +374,13 @@ void GLShaderTVArray::cleanup()
delete m_objImage;
m_objImage = nullptr;
}
delete m_verticesBuf;
m_verticesBuf = nullptr;
delete m_textureCoordsBuf;
m_textureCoordsBuf = nullptr;
delete m_vao;
m_vao = nullptr;
}
bool GLShaderTVArray::SelectRow(int intLine)

Wyświetl plik

@ -26,6 +26,8 @@
#include <QOpenGLFunctions_3_0>
#include <QOpenGLTexture>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QMatrix4x4>
#include <QVector4D>
#include <QDebug>
@ -45,7 +47,7 @@ public:
void setColor(bool blnColor) { m_blnColor = blnColor; }
void setAlphaBlend(bool blnAlphaBlend) { m_blnAlphaBlend = blnAlphaBlend; }
void setAlphaReset() { m_blnAlphaReset = true; }
void initializeGL(int intCols, int intRows);
void initializeGL(int majorVersion, int minorVersion, int intCols, int intRows);
void cleanup();
QRgb *GetRowBuffer(int intRow);
void RenderPixels(unsigned char *chrData);
@ -57,10 +59,15 @@ public:
protected:
QOpenGLShaderProgram *m_objProgram;
QOpenGLVertexArrayObject *m_vao;
QOpenGLBuffer *m_verticesBuf;
QOpenGLBuffer *m_textureCoordsBuf;
int m_matrixLoc;
int m_textureLoc;
//int m_objColorLoc;
static const QString m_strVertexShaderSourceArray2;
static const QString m_strVertexShaderSourceArray;
static const QString m_strFragmentShaderSourceColored2;
static const QString m_strFragmentShaderSourceColored;
QImage *m_objImage;

Wyświetl plik

@ -178,7 +178,13 @@ void TVScreen::paintGL()
if ((m_askedCols != 0) && (m_askedRows != 0))
{
m_glShaderArray.initializeGL(m_askedCols, m_askedRows);
int major = 0, minor = 0;
if (QOpenGLContext::currentContext())
{
major = QOpenGLContext::currentContext()->format().majorVersion();
minor = QOpenGLContext::currentContext()->format().minorVersion();
}
m_glShaderArray.initializeGL(major, minor, m_askedCols, m_askedRows);
m_askedCols = 0;
m_askedRows = 0;
}

Wyświetl plik

@ -21,52 +21,101 @@
#include "tvscreenanalog.h"
static const char* vertexShaderSource2 =
"attribute highp vec4 vertex;\n"
"attribute highp vec2 texCoord;\n"
"varying highp vec2 texCoordVar;\n"
"void main() {\n"
" gl_Position = vertex;\n"
" texCoordVar = texCoord;\n"
"}\n";
static const char* vertexShaderSource =
"attribute highp vec4 vertex;\n"
"attribute highp vec2 texCoord;\n"
"varying highp vec2 texCoordVar;\n"
"void main() {\n"
" gl_Position = vertex;\n"
" texCoordVar = texCoord;\n"
"}\n";
"#version 330\n"
"in highp vec4 vertex;\n"
"in highp vec2 texCoord;\n"
"out highp vec2 texCoordVar;\n"
"void main() {\n"
" gl_Position = vertex;\n"
" texCoordVar = texCoord;\n"
"}\n";
static const char* fragmentShaderSource2 =
"uniform highp sampler2D tex1;\n"
"uniform highp sampler2D tex2;\n"
"uniform highp float imw;\n"
"uniform highp float imh;\n"
"uniform highp float tlw;\n"
"uniform highp float tlh;\n"
"varying highp vec2 texCoordVar;\n"
"void main() {\n"
" float tlhw = 0.5 * tlw;"
" float tlhh = 0.5 * tlh;"
" float tys = (texCoordVar.y + tlhh) * imh;\n"
" float p1y = floor(tys) * tlh - tlhh;\n"
" float p3y = p1y + tlh;\n"
" float tshift1 = texture2D(tex2, vec2(0.0, p1y)).r;\n"
" float tshift3 = texture2D(tex2, vec2(0.0, p3y)).r;\n"
" float shift1 = (1.0 - tshift1 * 2.0) * tlw;\n"
" float shift3 = (1.0 - tshift3 * 2.0) * tlw;\n"
" float txs1 = (texCoordVar.x + shift1 + tlhw) * imw;\n"
" float txs3 = (texCoordVar.x + shift3 + tlhw) * imw;\n"
" float p1x = floor(txs1) * tlw - tlhw;\n"
" float p3x = floor(txs3) * tlw - tlhw;\n"
" float p2x = p1x + tlw;\n"
" float p4x = p3x + tlw;\n"
" float p1 = texture2D(tex1, vec2(p1x, p1y)).r;\n"
" float p2 = texture2D(tex1, vec2(p2x, p1y)).r;\n"
" float p3 = texture2D(tex1, vec2(p3x, p3y)).r;\n"
" float p4 = texture2D(tex1, vec2(p4x, p3y)).r;\n"
" float p12 = mix(p1, p2, fract(txs1));\n"
" float p34 = mix(p3, p4, fract(txs3));\n"
" float p = mix(p12, p34, fract(tys));\n"
" gl_FragColor = vec4(p);\n"
"}\n";
static const char* fragmentShaderSource =
"uniform highp sampler2D tex1;\n"
"uniform highp sampler2D tex2;\n"
"uniform highp float imw;\n"
"uniform highp float imh;\n"
"uniform highp float tlw;\n"
"uniform highp float tlh;\n"
"varying highp vec2 texCoordVar;\n"
"void main() {\n"
" float tlhw = 0.5 * tlw;"
" float tlhh = 0.5 * tlh;"
" float tys = (texCoordVar.y + tlhh) * imh;\n"
" float p1y = floor(tys) * tlh - tlhh;\n"
" float p3y = p1y + tlh;\n"
" float tshift1 = texture2D(tex2, vec2(0.0, p1y)).r;\n"
" float tshift3 = texture2D(tex2, vec2(0.0, p3y)).r;\n"
" float shift1 = (1.0 - tshift1 * 2.0) * tlw;\n"
" float shift3 = (1.0 - tshift3 * 2.0) * tlw;\n"
" float txs1 = (texCoordVar.x + shift1 + tlhw) * imw;\n"
" float txs3 = (texCoordVar.x + shift3 + tlhw) * imw;\n"
" float p1x = floor(txs1) * tlw - tlhw;\n"
" float p3x = floor(txs3) * tlw - tlhw;\n"
" float p2x = p1x + tlw;\n"
" float p4x = p3x + tlw;\n"
" float p1 = texture2D(tex1, vec2(p1x, p1y)).r;\n"
" float p2 = texture2D(tex1, vec2(p2x, p1y)).r;\n"
" float p3 = texture2D(tex1, vec2(p3x, p3y)).r;\n"
" float p4 = texture2D(tex1, vec2(p4x, p3y)).r;\n"
" float p12 = mix(p1, p2, fract(txs1));\n"
" float p34 = mix(p3, p4, fract(txs3));\n"
" float p = mix(p12, p34, fract(tys));\n"
" gl_FragColor = vec4(p);\n"
"}\n";
"#version 330\n"
"uniform highp sampler2D tex1;\n"
"uniform highp sampler2D tex2;\n"
"uniform highp float imw;\n"
"uniform highp float imh;\n"
"uniform highp float tlw;\n"
"uniform highp float tlh;\n"
"in highp vec2 texCoordVar;\n"
"out vec4 fragColor;\n"
"void main() {\n"
" float tlhw = 0.5 * tlw;"
" float tlhh = 0.5 * tlh;"
" float tys = (texCoordVar.y + tlhh) * imh;\n"
" float p1y = floor(tys) * tlh - tlhh;\n"
" float p3y = p1y + tlh;\n"
" float tshift1 = texture2D(tex2, vec2(0.0, p1y)).r;\n"
" float tshift3 = texture2D(tex2, vec2(0.0, p3y)).r;\n"
" float shift1 = (1.0 - tshift1 * 2.0) * tlw;\n"
" float shift3 = (1.0 - tshift3 * 2.0) * tlw;\n"
" float txs1 = (texCoordVar.x + shift1 + tlhw) * imw;\n"
" float txs3 = (texCoordVar.x + shift3 + tlhw) * imw;\n"
" float p1x = floor(txs1) * tlw - tlhw;\n"
" float p3x = floor(txs3) * tlw - tlhw;\n"
" float p2x = p1x + tlw;\n"
" float p4x = p3x + tlw;\n"
" float p1 = texture(tex1, vec2(p1x, p1y)).r;\n"
" float p2 = texture(tex1, vec2(p2x, p1y)).r;\n"
" float p3 = texture(tex1, vec2(p3x, p3y)).r;\n"
" float p4 = texture(tex1, vec2(p4x, p3y)).r;\n"
" float p12 = mix(p1, p2, fract(txs1));\n"
" float p34 = mix(p3, p4, fract(txs3));\n"
" float p = mix(p12, p34, fract(tys));\n"
" fragColor = vec4(p);\n"
"}\n";
TVScreenAnalog::TVScreenAnalog(QWidget *parent) :
QOpenGLWidget(parent),
m_shader(nullptr),
m_vao(nullptr),
m_verticesBuf(nullptr),
m_textureCoordsBuf(nullptr),
m_imageTexture(nullptr),
m_lineShiftsTexture(nullptr)
{
@ -107,7 +156,14 @@ void TVScreenAnalog::cleanup()
delete m_lineShiftsTexture;
m_lineShiftsTexture = nullptr;
}
}
delete m_verticesBuf;
m_verticesBuf = nullptr;
delete m_textureCoordsBuf;
m_textureCoordsBuf = nullptr;
delete m_vao;
m_vao = nullptr;
}
TVScreenAnalogBuffer *TVScreenAnalog::getBackBuffer()
{
@ -147,21 +203,52 @@ void TVScreenAnalog::initializeGL()
m_shader = new QOpenGLShaderProgram(this);
if (!m_shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource))
{
qWarning()
<< "TVScreenAnalog::initializeGL: error in vertex shader:"
<< m_shader->log();
return;
}
int majorVersion = 0, minorVersion = 0;
if (QOpenGLContext::currentContext())
{
majorVersion = QOpenGLContext::currentContext()->format().majorVersion();
minorVersion = QOpenGLContext::currentContext()->format().minorVersion();
}
if ((majorVersion > 3) || ((majorVersion == 3) && (minorVersion >= 3)))
{
if (!m_shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource))
{
qWarning()
<< "TVScreenAnalog::initializeGL: error in vertex shader:"
<< m_shader->log();
return;
}
if (!m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource))
{
qWarning()
<< "TVScreenAnalog::initializeGL: error in fragment shader:"
<< m_shader->log();
return;
}
if (!m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource))
{
qWarning()
<< "TVScreenAnalog::initializeGL: error in fragment shader:"
<< m_shader->log();
return;
}
m_vao = new QOpenGLVertexArrayObject();
m_vao->create();
m_vao->bind();
}
else
{
if (!m_shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource2))
{
qWarning()
<< "TVScreenAnalog::initializeGL: error in vertex shader:"
<< m_shader->log();
return;
}
if (!m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource2))
{
qWarning()
<< "TVScreenAnalog::initializeGL: error in fragment shader:"
<< m_shader->log();
return;
}
}
if (!m_shader->link())
{
@ -179,6 +266,16 @@ void TVScreenAnalog::initializeGL()
m_imageHeightLoc = m_shader->uniformLocation("imh");
m_texelWidthLoc = m_shader->uniformLocation("tlw");
m_texelHeightLoc = m_shader->uniformLocation("tlh");
if (m_vao)
{
m_verticesBuf = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_verticesBuf->setUsagePattern(QOpenGLBuffer::DynamicDraw);
m_verticesBuf->create();
m_textureCoordsBuf = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_textureCoordsBuf->setUsagePattern(QOpenGLBuffer::DynamicDraw);
m_textureCoordsBuf->create();
m_vao->release();
}
}
void TVScreenAnalog::initializeTextures(TVScreenAnalogBuffer *buffer)
@ -280,13 +377,40 @@ void TVScreenAnalog::paintGL()
1.0f, 1.0f
};
glVertexAttribPointer(m_vertexAttribIndex, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(m_vertexAttribIndex);
glVertexAttribPointer(m_texCoordAttribIndex, 2, GL_FLOAT, GL_FALSE, 0, arrTextureCoords);
glEnableVertexAttribArray(m_texCoordAttribIndex);
if (m_vao)
{
m_vao->bind();
m_verticesBuf->bind();
m_verticesBuf->allocate(vertices, 4 * 2 * sizeof(GL_FLOAT));
m_shader->enableAttributeArray(m_vertexAttribIndex);
m_shader->setAttributeBuffer(m_vertexAttribIndex, GL_FLOAT, 0, 2);
// As these coords are constant, this could be moved into the init method
m_textureCoordsBuf->bind();
m_textureCoordsBuf->allocate(arrTextureCoords, 4 * 2 * sizeof(GL_FLOAT));
m_shader->enableAttributeArray(m_texCoordAttribIndex);
m_shader->setAttributeBuffer(m_texCoordAttribIndex, GL_FLOAT, 0, 2);
}
else
{
glVertexAttribPointer(m_vertexAttribIndex, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(m_vertexAttribIndex);
glVertexAttribPointer(m_texCoordAttribIndex, 2, GL_FLOAT, GL_FALSE, 0, arrTextureCoords);
glEnableVertexAttribArray(m_texCoordAttribIndex);
}
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableVertexAttribArray(m_vertexAttribIndex);
glDisableVertexAttribArray(m_texCoordAttribIndex);
if (m_vao)
{
m_vao->release();
}
else
{
glDisableVertexAttribArray(m_vertexAttribIndex);
glDisableVertexAttribArray(m_texCoordAttribIndex);
}
m_shader->release();
}

Wyświetl plik

@ -31,6 +31,8 @@
#include <QOpenGLTexture>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
class TVScreenAnalogBuffer
{
@ -130,6 +132,9 @@ class SDRGUI_API TVScreenAnalog : public QOpenGLWidget, protected QOpenGLFunctio
TVScreenAnalogBuffer *m_backBuffer;
QOpenGLShaderProgram *m_shader;
QOpenGLVertexArrayObject *m_vao;
QOpenGLBuffer *m_verticesBuf;
QOpenGLBuffer *m_textureCoordsBuf;
QOpenGLTexture *m_imageTexture;
QOpenGLTexture *m_lineShiftsTexture;