| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2020 Vort                                                       //
 | 
					
						
							|  |  |  | // Copyright (C) 2018 F4HKW                                                      //
 | 
					
						
							|  |  |  | // for F4EXB / SDRAngel                                                          //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // OpenGL interface modernization.                                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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                  //
 | 
					
						
							|  |  |  | // (at your option) any later version.                                           //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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 <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "tvscreenanalog.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  | 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"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | static const char* vertexShaderSource = | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  |     "#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"; | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | static const char* fragmentShaderSource = | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  |     "#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"; | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 18:13:08 +01:00
										 |  |  | TVScreenAnalog::TVScreenAnalog(QWidget *parent)	: | 
					
						
							|  |  |  | 	QOpenGLWidget(parent), | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 	m_shader(nullptr), | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  |     m_vao(nullptr), | 
					
						
							|  |  |  |     m_verticesBuf(nullptr), | 
					
						
							|  |  |  |     m_textureCoordsBuf(nullptr), | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 	m_imageTexture(nullptr), | 
					
						
							|  |  |  | 	m_lineShiftsTexture(nullptr) | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | { | 
					
						
							|  |  |  | 	m_isDataChanged = false; | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 	m_frontBuffer = new TVScreenAnalogBuffer(5, 1); | 
					
						
							|  |  |  | 	m_backBuffer = new TVScreenAnalogBuffer(5, 1); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 	connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(tick())); | 
					
						
							|  |  |  | 	m_updateTimer.start(40); // capped at 25 FPS
 | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | TVScreenAnalog::~TVScreenAnalog() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	delete m_backBuffer; | 
					
						
							|  |  |  | 	delete m_frontBuffer; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | void TVScreenAnalog::cleanup() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-18 19:15:17 +01:00
										 |  |  | 	if (!QOpenGLContext::currentContext()) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 	if (m_shader) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		delete m_shader; | 
					
						
							|  |  |  | 		m_shader = nullptr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (m_imageTexture) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		delete m_imageTexture; | 
					
						
							|  |  |  | 		m_imageTexture = nullptr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (m_lineShiftsTexture) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		delete m_lineShiftsTexture; | 
					
						
							|  |  |  | 		m_lineShiftsTexture = nullptr; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     delete m_verticesBuf; | 
					
						
							|  |  |  |     m_verticesBuf = nullptr; | 
					
						
							|  |  |  |     delete m_textureCoordsBuf; | 
					
						
							|  |  |  |     m_textureCoordsBuf = nullptr; | 
					
						
							|  |  |  |     delete m_vao; | 
					
						
							|  |  |  |     m_vao = nullptr; | 
					
						
							|  |  |  |  } | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | TVScreenAnalogBuffer *TVScreenAnalog::getBackBuffer() | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 	return m_backBuffer; | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | void TVScreenAnalog::resizeTVScreen(int intCols, int intRows) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-12 20:04:18 +01:00
										 |  |  | 	qDebug("TVScreenAnalog::resizeTVScreen: cols: %d, rows: %d", intCols, intRows); | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int colsAdj = intCols + 4; | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 	QMutexLocker lock(&m_buffersMutex); | 
					
						
							|  |  |  | 	if (m_frontBuffer->getWidth() != colsAdj || m_frontBuffer->getHeight() != intRows) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 		delete m_backBuffer; | 
					
						
							|  |  |  | 		delete m_frontBuffer; | 
					
						
							|  |  |  | 		m_frontBuffer = new TVScreenAnalogBuffer(colsAdj, intRows); | 
					
						
							|  |  |  | 		m_backBuffer = new TVScreenAnalogBuffer(colsAdj, intRows); | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TVScreenAnalog::resizeGL(int intWidth, int intHeight) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	glViewport(0, 0, intWidth, intHeight); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TVScreenAnalog::initializeGL() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	initializeOpenGLFunctions(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 18:13:08 +01:00
										 |  |  | 	connect( | 
					
						
							|  |  |  | 		QOpenGLContext::currentContext(), | 
					
						
							|  |  |  | 		&QOpenGLContext::aboutToBeDestroyed, | 
					
						
							|  |  |  | 		this, | 
					
						
							|  |  |  | 		&TVScreenAnalog::cleanup | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2020-08-05 19:36:07 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 	m_shader = new QOpenGLShaderProgram(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  |     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; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 19:36:07 +03:00
										 |  |  | 	if (!m_shader->link()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		qWarning() | 
					
						
							|  |  |  | 			<< "TVScreenAnalog::initializeGL: error linking shader:" | 
					
						
							|  |  |  | 			<< m_shader->log(); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_vertexAttribIndex = m_shader->attributeLocation("vertex"); | 
					
						
							|  |  |  | 	m_texCoordAttribIndex = m_shader->attributeLocation("texCoord"); | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 	m_textureLoc1 = m_shader->uniformLocation("tex1"); | 
					
						
							|  |  |  | 	m_textureLoc2 = m_shader->uniformLocation("tex2"); | 
					
						
							|  |  |  | 	m_imageWidthLoc = m_shader->uniformLocation("imw"); | 
					
						
							|  |  |  | 	m_imageHeightLoc = m_shader->uniformLocation("imh"); | 
					
						
							|  |  |  | 	m_texelWidthLoc = m_shader->uniformLocation("tlw"); | 
					
						
							|  |  |  | 	m_texelHeightLoc = m_shader->uniformLocation("tlh"); | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  |     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(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | void TVScreenAnalog::initializeTextures(TVScreenAnalogBuffer *buffer) | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 	m_imageTexture = new QOpenGLTexture(QOpenGLTexture::Target2D); | 
					
						
							|  |  |  | 	m_lineShiftsTexture = new QOpenGLTexture(QOpenGLTexture::Target2D); | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 	m_imageTexture->setSize(buffer->getWidth(), buffer->getHeight()); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->setSize(1, buffer->getHeight()); | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 	m_imageTexture->setFormat(QOpenGLTexture::RGBA8_UNorm); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->setFormat(QOpenGLTexture::RGBA8_UNorm); | 
					
						
							|  |  |  | 	m_imageTexture->setAutoMipMapGenerationEnabled(false); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->setAutoMipMapGenerationEnabled(false); | 
					
						
							|  |  |  | 	m_imageTexture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_imageTexture->setMinificationFilter(QOpenGLTexture::Nearest); | 
					
						
							|  |  |  | 	m_imageTexture->setMagnificationFilter(QOpenGLTexture::Nearest); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->setMinificationFilter(QOpenGLTexture::Nearest); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->setMagnificationFilter(QOpenGLTexture::Nearest); | 
					
						
							|  |  |  | 	m_imageTexture->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToBorder); | 
					
						
							|  |  |  | 	m_imageTexture->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | TVScreenAnalogBuffer *TVScreenAnalog::swapBuffers() | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 	QMutexLocker lock(&m_buffersMutex); | 
					
						
							|  |  |  | 	std::swap(m_frontBuffer, m_backBuffer); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 	m_isDataChanged = true; | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 	return m_backBuffer; | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TVScreenAnalog::tick() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 	if (m_isDataChanged) | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 		update(); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TVScreenAnalog::paintGL() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_isDataChanged = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 19:36:07 +03:00
										 |  |  | 	if (!m_shader) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		glClearColor(0.2f, 0.0f, 0.0f, 1.0f); | 
					
						
							|  |  |  | 		glClear(GL_COLOR_BUFFER_BIT); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | 	TVScreenAnalogBuffer *buffer = m_frontBuffer; | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 	if (!m_imageTexture || | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 		m_imageTexture->width() != buffer->getWidth() || | 
					
						
							|  |  |  | 		m_imageTexture->height() != buffer->getHeight()) | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 		initializeTextures(buffer); | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 	float imageWidth = buffer->getWidth(); | 
					
						
							|  |  |  | 	float imageHeight = buffer->getHeight(); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 	float texelWidth = 1.0f / imageWidth; | 
					
						
							|  |  |  | 	float texelHeight = 1.0f / imageHeight; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_shader->bind(); | 
					
						
							| 
									
										
										
										
											2020-08-04 17:02:06 +03:00
										 |  |  | 	m_shader->setUniformValue(m_textureLoc1, 0); | 
					
						
							|  |  |  | 	m_shader->setUniformValue(m_textureLoc2, 1); | 
					
						
							|  |  |  | 	m_shader->setUniformValue(m_imageWidthLoc, imageWidth); | 
					
						
							|  |  |  | 	m_shader->setUniformValue(m_imageHeightLoc, imageHeight); | 
					
						
							|  |  |  | 	m_shader->setUniformValue(m_texelWidthLoc, texelWidth); | 
					
						
							|  |  |  | 	m_shader->setUniformValue(m_texelHeightLoc, texelHeight); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	glActiveTexture(GL_TEXTURE0); | 
					
						
							|  |  |  | 	m_imageTexture->bind(); | 
					
						
							|  |  |  | 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 		buffer->getWidth(), buffer->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, buffer->getImageData()); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	glActiveTexture(GL_TEXTURE1); | 
					
						
							|  |  |  | 	m_lineShiftsTexture->bind(); | 
					
						
							|  |  |  | 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, | 
					
						
							| 
									
										
										
										
											2020-08-10 15:54:34 +03:00
										 |  |  | 		1, buffer->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, buffer->getLineShiftData()); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 19:36:07 +03:00
										 |  |  | 	float rectHalfWidth = 1.0f + 4.0f / (imageWidth - 4.0f); | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 	GLfloat vertices[] = | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		-rectHalfWidth, -1.0f, | 
					
						
							|  |  |  | 		-rectHalfWidth,  1.0f, | 
					
						
							|  |  |  | 		 rectHalfWidth,  1.0f, | 
					
						
							|  |  |  | 		 rectHalfWidth, -1.0f | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static const GLfloat arrTextureCoords[] = | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		0.0f, 1.0f, | 
					
						
							|  |  |  | 		0.0f, 0.0f, | 
					
						
							|  |  |  | 		1.0f, 0.0f, | 
					
						
							|  |  |  | 		1.0f, 1.0f | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  |     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); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 	glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 
					
						
							| 
									
										
										
										
											2022-06-19 23:22:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_vao) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_vao->release(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  | 	   glDisableVertexAttribArray(m_vertexAttribIndex); | 
					
						
							|  |  |  | 	   glDisableVertexAttribArray(m_texCoordAttribIndex); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-03 19:31:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	m_shader->release(); | 
					
						
							| 
									
										
										
										
											2020-12-10 07:28:55 +01:00
										 |  |  | } |