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){