From f78206defc6990e079552b108b72a86253ffb8b0 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 5 Mar 2016 06:45:05 +0100 Subject: [PATCH] OpenGL modernization: draw the left scales the new way --- CMakeLists.txt | 2 + include/gui/glshadertextured.h | 52 ++++++++++++ include/gui/glspectrum.h | 7 +- sdrangel.pro | 10 ++- sdrbase/gui/glshadersimple.cpp | 18 ++++- sdrbase/gui/glshadertextured.cpp | 133 +++++++++++++++++++++++++++++++ sdrbase/gui/glspectrum.cpp | 45 +++++------ 7 files changed, 235 insertions(+), 32 deletions(-) create mode 100644 include/gui/glshadertextured.h create mode 100644 sdrbase/gui/glshadertextured.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 92e27b694..2dc5fa95b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,6 +118,7 @@ set(sdrbase_SOURCES sdrbase/gui/glscope.cpp sdrbase/gui/glscopegui.cpp sdrbase/gui/glshadersimple.cpp + sdrbase/gui/glshadertextured.cpp sdrbase/gui/glspectrum.cpp sdrbase/gui/glspectrumgui.cpp sdrbase/gui/indicator.cpp @@ -201,6 +202,7 @@ set(sdrbase_HEADERS include/gui/glscope.h include/gui/glscopegui.h include/gui/glshadersimple.h + include/gui/glshadertextured.h include/gui/glspectrum.h include/gui/glspectrumgui.h include/gui/indicator.h diff --git a/include/gui/glshadertextured.h b/include/gui/glshadertextured.h new file mode 100644 index 000000000..69546497c --- /dev/null +++ b/include/gui/glshadertextured.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 F4EXB // +// written by Edouard Griffiths // +// // +// See: http://glslstudio.com/primer/#gl2frag // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_GUI_GLSHADERTEXTURED_H_ +#define INCLUDE_GUI_GLSHADERTEXTURED_H_ + +#include + +class QOpenGLShaderProgram; +class QMatrix4x4; +class QOpenGLTexture; +class QImage; + +class GLShaderTextured +{ +public: + GLShaderTextured(); + ~GLShaderTextured(); + + void initializeGL(); + void initTexture(const QImage& image); + void drawSurface(const QMatrix4x4& transformMatrix, GLfloat* textureCoords, GLfloat *vertices, int nbVertices); + void cleanup(); + +private: + void draw(unsigned int mode, const QMatrix4x4& transformMatrix, GLfloat *textureCoords, GLfloat *vertices, int nbVertices); + + QOpenGLShaderProgram *m_program; + QOpenGLTexture *m_texture; + int m_matrixLoc; + int m_textureLoc; + static const QString m_vertexShaderSourceTextured; + static const QString m_fragmentShaderSourceTextured; +}; + +#endif /* INCLUDE_GUI_GLSHADERTEXTURED_H_ */ diff --git a/include/gui/glspectrum.h b/include/gui/glspectrum.h index be3925981..133b3ac97 100644 --- a/include/gui/glspectrum.h +++ b/include/gui/glspectrum.h @@ -30,6 +30,7 @@ #include "dsp/dsptypes.h" #include "gui/scaleengine.h" #include "gui/glshadersimple.h" +#include "gui/glshadertextured.h" #include "dsp/channelmarker.h" #include "util/export.h" @@ -127,15 +128,17 @@ private: Real m_waterfallShare; QPixmap m_leftMarginPixmap; +#ifdef GL_DEPRECATED bool m_leftMarginTextureAllocated; GLuint m_leftMarginTexture; + QRectF m_glLeftScaleRect; +#endif QPixmap m_frequencyPixmap; bool m_frequencyTextureAllocated; GLuint m_frequencyTexture; ScaleEngine m_timeScale; ScaleEngine m_powerScale; ScaleEngine m_frequencyScale; - QRectF m_glLeftScaleRect; QRectF m_glFrequencyScaleRect; QRect m_frequencyScaleRect; QMatrix4x4 m_glFrequencyScaleBoxMatrix; @@ -171,7 +174,7 @@ private: bool m_displayChanged; GLShaderSimple m_glShaderSimple; - QOpenGLShaderProgram *m_program; + GLShaderTextured m_glShaderLeftScale; int m_matrixLoc; int m_colorLoc; diff --git a/sdrangel.pro b/sdrangel.pro index 589160001..8f38efca2 100644 --- a/sdrangel.pro +++ b/sdrangel.pro @@ -1,8 +1,8 @@ -#------------------------------------------------- +#-------------------------------------------------------- # -# Pro file for Android build with Qt Creator +# Pro file for Android and Windows builds with Qt Creator # -#------------------------------------------------- +#-------------------------------------------------------- QT += core gui @@ -64,6 +64,8 @@ SOURCES += main.cpp\ sdrbase/gui/colormapper.cpp\ sdrbase/gui/glscope.cpp\ sdrbase/gui/glscopegui.cpp\ + sdrbase/gui/glshadersimple.cpp\ + sdrbase/gui/glshadertextured.cpp\ sdrbase/gui/glspectrum.cpp\ sdrbase/gui/glspectrumgui.cpp\ sdrbase/gui/indicator.cpp\ @@ -135,6 +137,8 @@ HEADERS += include/mainwindow.h\ include/gui/colormapper.h\ include/gui/glscope.h\ include/gui/glscopegui.h\ + include/gui/glshadersimple.h\ + include/gui/glshadertextured.h\ include/gui/glspectrum.h\ include/gui/glspectrumgui.h\ include/gui/indicator.h\ diff --git a/sdrbase/gui/glshadersimple.cpp b/sdrbase/gui/glshadersimple.cpp index 3bf2f9502..82f2b0df7 100644 --- a/sdrbase/gui/glshadersimple.cpp +++ b/sdrbase/gui/glshadersimple.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "gui/glshadersimple.h" @@ -35,10 +36,21 @@ GLShaderSimple::~GLShaderSimple() void GLShaderSimple::initializeGL() { m_program = new QOpenGLShaderProgram; - m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_vertexShaderSourceSimple); - m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_fragmentShaderSourceColored); + + if (!m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_vertexShaderSourceSimple)) { + qDebug() << "GLShaderSimple::initializeGL: error in vertex shader: " << m_program->log(); + } + + if (!m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_fragmentShaderSourceColored)) { + qDebug() << "GLShaderSimple::initializeGL: error in fragment shader: " << m_program->log(); + } + m_program->bindAttributeLocation("vertex", 0); - m_program->link(); + + if (!m_program->link()) { + qDebug() << "GLShaderSimple::initializeGL: error linking shader: " << m_program->log(); + } + m_program->bind(); m_matrixLoc = m_program->uniformLocation("uMatrix"); m_colorLoc = m_program->uniformLocation("uColour"); diff --git a/sdrbase/gui/glshadertextured.cpp b/sdrbase/gui/glshadertextured.cpp new file mode 100644 index 000000000..ab246f468 --- /dev/null +++ b/sdrbase/gui/glshadertextured.cpp @@ -0,0 +1,133 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 F4EXB // +// written by Edouard Griffiths // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gui/glshadertextured.h" + +GLShaderTextured::GLShaderTextured() : + m_program(0), + m_texture(0) +{ } + +GLShaderTextured::~GLShaderTextured() +{ + cleanup(); +} + +void GLShaderTextured::initializeGL() +{ + m_program = new QOpenGLShaderProgram; + + if (!m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_vertexShaderSourceTextured)) { + qDebug() << "GLShaderTextured::initializeGL: error in vertex shader: " << m_program->log(); + } + + if (!m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_fragmentShaderSourceTextured)) { + qDebug() << "GLShaderTextured::initializeGL: error in fragment shader: " << m_program->log(); + } + + m_program->bindAttributeLocation("vertex", 0); + m_program->bindAttributeLocation("texCoord", 1); + + if (!m_program->link()) { + qDebug() << "GLShaderTextured::initializeGL: error linking shader: " << m_program->log(); + } + + m_program->bind(); + m_matrixLoc = m_program->uniformLocation("uMatrix"); + m_textureLoc = m_program->uniformLocation("uTexture"); + m_program->release(); +} + +void GLShaderTextured::initTexture(const QImage& image) +{ + if (m_texture) { + delete m_texture; + } + + m_texture = new QOpenGLTexture(image); + + m_texture->setMinificationFilter(QOpenGLTexture::Linear); + m_texture->setMagnificationFilter(QOpenGLTexture::Linear); + m_texture->setWrapMode(QOpenGLTexture::Repeat); +} + +void GLShaderTextured::drawSurface(const QMatrix4x4& transformMatrix, GLfloat *textureCoords, GLfloat *vertices, int nbVertices) +{ + draw(GL_TRIANGLE_FAN, transformMatrix, textureCoords, vertices, nbVertices); +} + +void GLShaderTextured::draw(unsigned int mode, const QMatrix4x4& transformMatrix, GLfloat *textureCoords, GLfloat *vertices, int nbVertices) +{ + if (!m_texture) { + qDebug("GLShaderTextured::draw: no texture defined. Doing nothing"); + return; + } + + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + m_program->bind(); + m_program->setUniformValue(m_matrixLoc, transformMatrix); + m_texture->bind(); + m_program->setUniformValue(m_textureLoc, 0); // Use texture unit 0 which magically contains our texture + f->glEnableVertexAttribArray(0); // vertex + f->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); + f->glEnableVertexAttribArray(1); // texture coordinates + f->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureCoords); + f->glDrawArrays(mode, 0, nbVertices); + f->glDisableVertexAttribArray(0); + m_program->release(); +} + +void GLShaderTextured::cleanup() +{ + if (m_program) { + delete m_program; + m_program = 0; + } + + if (m_texture) { + delete m_texture; + m_texture = 0; + } +} + +const QString GLShaderTextured::m_vertexShaderSourceTextured = QString( + "uniform mat4 uMatrix;\n" + "attribute vec4 vertex;\n" + "attribute vec2 texCoord;\n" + "varying vec2 texCoordVar;\n" + "void main() {\n" + " gl_Position = uMatrix * vertex;\n" + " texCoordVar = texCoord;\n" + "}\n" + ); + +const QString GLShaderTextured::m_fragmentShaderSourceTextured = QString( + "uniform sampler2D uTexture;\n" + "varying vec2 texCoordVar;\n" + "void main() {\n" + " gl_FragColor = texture2D(uTexture, texCoordVar);\n" + "}\n" + ); diff --git a/sdrbase/gui/glspectrum.cpp b/sdrbase/gui/glspectrum.cpp index 72e88fb50..2025367f2 100644 --- a/sdrbase/gui/glspectrum.cpp +++ b/sdrbase/gui/glspectrum.cpp @@ -48,7 +48,9 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_displayMaxHold(false), m_currentSpectrum(0), m_displayCurrent(false), +#ifdef GL_DEPRECATED m_leftMarginTextureAllocated(false), +#endif m_frequencyTextureAllocated(false), m_waterfallBuffer(NULL), m_waterfallTextureAllocated(false), @@ -60,8 +62,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_histogramHoldoff(NULL), m_histogramTextureAllocated(false), m_displayHistogram(true), - m_displayChanged(false), - m_program(0) + m_displayChanged(false) { setAutoFillBackground(false); setAttribute(Qt::WA_OpaquePaintEvent, true); @@ -149,10 +150,12 @@ GLSpectrum::~GLSpectrum() deleteTexture(m_histogramTexture); m_histogramTextureAllocated = false; } +#ifdef GL_DEPRECATED if(m_leftMarginTextureAllocated) { deleteTexture(m_leftMarginTexture); m_leftMarginTextureAllocated = false; } +#endif if(m_frequencyTextureAllocated) { deleteTexture(m_frequencyTexture); m_frequencyTextureAllocated = false; @@ -507,6 +510,7 @@ void GLSpectrum::initializeGL() connect(glCurrentContext, &QOpenGLContext::aboutToBeDestroyed, this, &GLSpectrum::cleanup); // TODO: when migrating to QOpenGLWidget glDisable(GL_DEPTH_TEST); m_glShaderSimple.initializeGL(); + m_glShaderLeftScale.initializeGL(); } void GLSpectrum::resizeGL(int width, int height) @@ -876,6 +880,7 @@ void GLSpectrum::paintGL() // paint left scales (time and power) if (m_displayWaterfall || m_displayMaxHold || m_displayCurrent || m_displayHistogram ) { +#ifdef GL_DEPRECATED glPushMatrix(); glTranslatef(m_glLeftScaleRect.x(), m_glLeftScaleRect.y(), 0); glScalef(m_glLeftScaleRect.width(), m_glLeftScaleRect.height(), 1); @@ -886,7 +891,6 @@ void GLSpectrum::paintGL() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); -#ifdef GL_DEPRECATED glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex2f(0, 1); @@ -897,6 +901,9 @@ void GLSpectrum::paintGL() glTexCoord2f(0, 0); glVertex2f(0, 0); glEnd(); + glDisable(GL_TEXTURE_2D); + + glPopMatrix(); #else { GLfloat vtx1[] = { @@ -911,28 +918,10 @@ void GLSpectrum::paintGL() 1, 0, 0, 0 }; -#ifdef GL_ANDROID - glEnableVertexAttribArray(GL_VERTEX_ARRAY); - glEnableVertexAttribArray(GL_TEXTURE_COORD_ARRAY); - glVertexAttribPointer(GL_VERTEX_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, vtx1); - glVertexAttribPointer(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, tex1); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(GL_VERTEX_ARRAY); - glDisableVertexAttribArray(GL_TEXTURE_COORD_ARRAY); -#else - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, vtx1); - glTexCoordPointer(2, GL_FLOAT, 0, tex1); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -#endif + + m_glShaderLeftScale.drawSurface(m_glLeftScaleBoxMatrix, tex1, vtx1, 4); } #endif - glDisable(GL_TEXTURE_2D); - - glPopMatrix(); } // paint frequency scale @@ -1561,12 +1550,14 @@ void GLSpectrum::applyChanges() (float) -2*frequencyScaleHeight / (float) height() ); +#ifdef GL_DEPRECATED m_glLeftScaleRect = QRectF( (float)0, (float)0, (float)(leftMargin - 1) / (float)width(), (float)1 ); +#endif m_glLeftScaleBoxMatrix.setToIdentity(); m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); @@ -1657,12 +1648,14 @@ void GLSpectrum::applyChanges() (float) -2*frequencyScaleHeight / (float) height() ); +#ifdef GL_DEPRECATED m_glLeftScaleRect = QRectF( (float)0, (float)0, (float)(leftMargin - 1) / (float)width(), (float)1 ); +#endif m_glLeftScaleBoxMatrix.setToIdentity(); m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); @@ -1738,13 +1731,14 @@ void GLSpectrum::applyChanges() (float) -2*frequencyScaleHeight / (float) height() ); +#ifdef GL_DEPRECATED m_glLeftScaleRect = QRectF( (float)0, (float)0, (float)(leftMargin - 1) / (float)width(), (float)1 ); - +#endif m_glLeftScaleBoxMatrix.setToIdentity(); m_glLeftScaleBoxMatrix.translate(-1.0f, 1.0f); m_glLeftScaleBoxMatrix.scale( @@ -1934,6 +1928,7 @@ void GLSpectrum::applyChanges() } } } +#ifdef GL_DEPRECATED if(m_leftMarginTextureAllocated) deleteTexture(m_leftMarginTexture); m_leftMarginTexture = bindTexture(m_leftMarginPixmap, @@ -1942,6 +1937,8 @@ void GLSpectrum::applyChanges() QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); m_leftMarginTextureAllocated = true; +#endif + m_glShaderLeftScale.initTexture(m_leftMarginPixmap.toImage()); } // prepare frequency scale if(m_displayWaterfall || m_displayHistogram || m_displayMaxHold || m_displayCurrent){