From 44d199cfab495921669f6f5168691a9e0e5ae20b Mon Sep 17 00:00:00 2001 From: Vort Date: Tue, 4 Aug 2020 17:02:06 +0300 Subject: [PATCH] Move TVScreen data to separate object --- plugins/channelrx/demodatv/atvdemodsink.cpp | 2 + plugins/channelrx/demodatv/atvdemodsink.h | 8 +- sdrgui/gui/tvscreenanalog.cpp | 127 ++++++++------------ sdrgui/gui/tvscreenanalog.h | 106 +++++++++++++--- 4 files changed, 145 insertions(+), 98 deletions(-) diff --git a/plugins/channelrx/demodatv/atvdemodsink.cpp b/plugins/channelrx/demodatv/atvdemodsink.cpp index 2688640bd..75c73cae8 100644 --- a/plugins/channelrx/demodatv/atvdemodsink.cpp +++ b/plugins/channelrx/demodatv/atvdemodsink.cpp @@ -486,6 +486,7 @@ void ATVDemodSink::applyChannelSettings(int channelSampleRate, int channelFreque m_samplesPerLine - m_numberSamplesPerLineSignals, m_settings.m_nbLines - m_numberOfBlackLines ); + m_tvScreenData = m_registeredTVScreen->getData(); } m_fieldIndex = 0; @@ -579,6 +580,7 @@ void ATVDemodSink::applySettings(const ATVDemodSettings& settings, bool force) m_samplesPerLine - m_numberSamplesPerLineSignals, m_settings.m_nbLines - m_numberOfBlackLines ); + m_tvScreenData = m_registeredTVScreen->getData(); } m_fieldIndex = 0; diff --git a/plugins/channelrx/demodatv/atvdemodsink.h b/plugins/channelrx/demodatv/atvdemodsink.h index 3469241f5..8c250cb31 100644 --- a/plugins/channelrx/demodatv/atvdemodsink.h +++ b/plugins/channelrx/demodatv/atvdemodsink.h @@ -20,6 +20,7 @@ #include #include +#include #include "dsp/channelsamplesink.h" #include "dsp/basebandsamplesink.h" @@ -108,6 +109,7 @@ private: //*************** ATV PARAMETERS *************** TVScreenAnalog *m_registeredTVScreen; + std::shared_ptr m_tvScreenData; //int m_intNumberSamplePerLine; int m_numberSamplesPerHTopNom; //!< number of samples per horizontal synchronization pulse (pulse in ultra-black) - nominal value @@ -198,7 +200,7 @@ private: inline void processSample(float& sample, int& sampleVideo) { // Filling pixel on the current line - reference index 0 at start of sync pulse - m_registeredTVScreen->setDataColor(m_sampleIndex - m_numberSamplesPerHSync, sampleVideo); + m_tvScreenData->setSampleValue(m_sampleIndex - m_numberSamplesPerHSync, sampleVideo); if (m_settings.m_hSync) { @@ -325,7 +327,7 @@ private: float shiftSamples = 0.0f; if (m_hSyncShiftCount != 0) shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount; - m_registeredTVScreen->selectRow(rowIndex, + m_tvScreenData->selectRow(rowIndex, shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples)); } @@ -358,7 +360,7 @@ private: // TODO: CHANGE float shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount; - m_registeredTVScreen->selectRow(m_rowIndex, + m_tvScreenData->setSampleValue(m_rowIndex, shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples)); } }; diff --git a/sdrgui/gui/tvscreenanalog.cpp b/sdrgui/gui/tvscreenanalog.cpp index c1ba3898a..d61300a9f 100644 --- a/sdrgui/gui/tvscreenanalog.cpp +++ b/sdrgui/gui/tvscreenanalog.cpp @@ -31,8 +31,8 @@ static const char* vertexShaderSource = "}\n"; static const char* fragmentShaderSource = -"uniform highp sampler2D uTexture1;\n" -"uniform highp sampler2D uTexture2;\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" @@ -44,8 +44,8 @@ static const char* fragmentShaderSource = " float tys = (texCoordVar.y + tlhh) * imh;\n" " float p1y = floor(tys) * tlh - tlhh;\n" " float p3y = p1y + tlh;\n" -" float tshift1 = texture2D(uTexture2, vec2(0.0, p1y)).r;\n" -" float tshift3 = texture2D(uTexture2, vec2(0.0, p3y)).r;\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" @@ -54,10 +54,10 @@ static const char* fragmentShaderSource = " float p3x = floor(txs3) * tlw - tlhw;\n" " float p2x = p1x + tlw;\n" " float p4x = p3x + tlw;\n" -" float p1 = texture2D(uTexture1, vec2(p1x, p1y)).r;\n" -" float p2 = texture2D(uTexture1, vec2(p2x, p1y)).r;\n" -" float p3 = texture2D(uTexture1, vec2(p3x, p3y)).r;\n" -" float p4 = texture2D(uTexture1, vec2(p4x, p3y)).r;\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" @@ -67,11 +67,8 @@ static const char* fragmentShaderSource = TVScreenAnalog::TVScreenAnalog(QWidget *parent) : QGLWidget(parent) { - m_objCurrentRow = nullptr; m_isDataChanged = false; - m_time = 0.0f; - m_cols = 1; - m_rows = 1; + m_data = std::make_shared(5, 1); connect(&m_objTimer, SIGNAL(timeout()), this, SLOT(tick())); m_objTimer.start(40); // capped at 25 FPS @@ -81,15 +78,21 @@ void TVScreenAnalog::cleanup() { m_shader = nullptr; m_imageTexture = nullptr; - m_objCurrentRow = nullptr; m_lineShiftsTexture = nullptr; } +std::shared_ptr TVScreenAnalog::getData() +{ + return m_data; +} + void TVScreenAnalog::resizeTVScreen(int intCols, int intRows) { qDebug("TVScreen::resizeTVScreen: cols: %d, rows: %d", intCols, intRows); - m_cols = intCols + 4; - m_rows = intRows; + + int colsAdj = intCols + 4; + if (m_data->getWidth() != colsAdj || m_data->getHeight() != intRows) + m_data = std::make_shared(colsAdj, intRows); } void TVScreenAnalog::resizeGL(int intWidth, int intHeight) @@ -99,7 +102,6 @@ void TVScreenAnalog::resizeGL(int intWidth, int intHeight) void TVScreenAnalog::initializeGL() { - m_objMutex.lock(); initializeOpenGLFunctions(); m_shader = std::make_shared(this); @@ -109,31 +111,30 @@ void TVScreenAnalog::initializeGL() m_vertexAttribIndex = m_shader->attributeLocation("vertex"); m_texCoordAttribIndex = m_shader->attributeLocation("texCoord"); - m_objTextureLoc1 = m_shader->uniformLocation("uTexture1"); - m_objTextureLoc2 = m_shader->uniformLocation("uTexture2"); - m_objImageWidthLoc = m_shader->uniformLocation("imw"); - m_objImageHeightLoc = m_shader->uniformLocation("imh"); - m_objTexelWidthLoc = m_shader->uniformLocation("tlw"); - m_objTexelHeightLoc = m_shader->uniformLocation("tlh"); - - - initializeTextures(); + 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"); connect(QOpenGLContext::currentContext(), &QOpenGLContext::aboutToBeDestroyed, this, &TVScreenAnalog::cleanup); // TODO: when migrating to QOpenGLWidget - - m_objMutex.unlock(); } void TVScreenAnalog::initializeTextures() { - m_image = std::make_shared(m_cols, m_rows, QImage::Format_ARGB32); - m_lineShifts = std::make_shared(1, m_rows, QImage::Format_ARGB32); - m_image->fill(0); - m_lineShifts->fill(127); + m_imageTexture = std::make_shared(QOpenGLTexture::Target2D); + m_lineShiftsTexture = std::make_shared(QOpenGLTexture::Target2D); + m_imageTexture->setSize(m_data->getWidth(), m_data->getHeight()); + m_lineShiftsTexture->setSize(1, m_data->getHeight()); + 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); - m_imageTexture = std::make_shared(*m_image, QOpenGLTexture::DontGenerateMipMaps); - m_lineShiftsTexture = std::make_shared(*m_lineShifts, QOpenGLTexture::DontGenerateMipMaps); m_imageTexture->setMinificationFilter(QOpenGLTexture::Nearest); m_imageTexture->setMagnificationFilter(QOpenGLTexture::Nearest); m_lineShiftsTexture->setMinificationFilter(QOpenGLTexture::Nearest); @@ -151,69 +152,45 @@ void TVScreenAnalog::renderImage() void TVScreenAnalog::tick() { - if (m_isDataChanged) { + if (m_isDataChanged) + { update(); } } -void TVScreenAnalog::selectRow(int intLine, float shift) -{ - if (!m_image || m_image->height() != m_rows) - return; - - if ((intLine < m_rows) && (intLine >= 0)) - { - m_objCurrentRow = (int*)m_image->scanLine(intLine); - m_lineShifts->setPixel(0, intLine, (1.0f + shift) * 127.5f); - } - else - { - m_objCurrentRow = nullptr; - } -} - -void TVScreenAnalog::setDataColor(int intCol, int objColor) -{ - if ((intCol < m_cols - 2) && - (intCol >= -2) && - (m_objCurrentRow != nullptr)) - { - m_objCurrentRow[intCol + 2] = objColor; - } -} - void TVScreenAnalog::paintGL() { - if (!m_objMutex.tryLock(2)) - return; - m_isDataChanged = false; - if (m_image->width() != m_cols || m_image->height() != m_rows) + if (!m_imageTexture || + m_imageTexture->width() != m_data->getWidth() || + m_imageTexture->height() != m_data->getHeight()) + { initializeTextures(); + } - float imageWidth = m_image->width(); - float imageHeight = m_image->height(); + float imageWidth = m_data->getWidth(); + float imageHeight = m_data->getHeight(); float texelWidth = 1.0f / imageWidth; float texelHeight = 1.0f / imageHeight; m_shader->bind(); - m_shader->setUniformValue(m_objTextureLoc1, 0); - m_shader->setUniformValue(m_objTextureLoc2, 1); - m_shader->setUniformValue(m_objImageWidthLoc, imageWidth); - m_shader->setUniformValue(m_objImageHeightLoc, imageHeight); - m_shader->setUniformValue(m_objTexelWidthLoc, texelWidth); - m_shader->setUniformValue(m_objTexelHeightLoc, texelHeight); + 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); glActiveTexture(GL_TEXTURE0); m_imageTexture->bind(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - m_image->width(), m_image->height(), GL_RGBA, GL_UNSIGNED_BYTE, m_image->constScanLine(0)); + m_data->getWidth(), m_data->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, m_data->getImageData()); glActiveTexture(GL_TEXTURE1); m_lineShiftsTexture->bind(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - 1, m_image->height(), GL_RGBA, GL_UNSIGNED_BYTE, m_lineShifts->constScanLine(0)); + 1, m_data->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, m_data->getLineShiftData()); float rectHalfWidth = 1.0f + 4 * texelWidth; GLfloat vertices[] = @@ -241,6 +218,4 @@ void TVScreenAnalog::paintGL() glDisableVertexAttribArray(m_texCoordAttribIndex); m_shader->release(); - - m_objMutex.unlock(); } \ No newline at end of file diff --git a/sdrgui/gui/tvscreenanalog.h b/sdrgui/gui/tvscreenanalog.h index 70a1cedb8..080eda2f8 100644 --- a/sdrgui/gui/tvscreenanalog.h +++ b/sdrgui/gui/tvscreenanalog.h @@ -26,6 +26,7 @@ #include "export.h" #include +#include #include #include @@ -35,43 +36,110 @@ #include #include +class TVScreenAnalogData +{ +public: + TVScreenAnalogData(int width, int height) + { + m_width = width; + m_height = height; + + m_imageData = new int[width * height]; + m_lineShiftData = new int[height]; + m_outOfBoundsLine = new int[width]; + m_currentLine = m_outOfBoundsLine; + + std::fill(m_imageData, m_imageData + width * height, 0); + std::fill(m_lineShiftData, m_lineShiftData + height, 127); + } + + ~TVScreenAnalogData() + { + delete[] m_imageData; + delete[] m_lineShiftData; + delete[] m_outOfBoundsLine; + } + + int getWidth() + { + return m_width; + } + + int getHeight() + { + return m_height; + } + + const int* getImageData() + { + return m_imageData; + } + + const int* getLineShiftData() + { + return m_lineShiftData; + } + + void selectRow(int line, float shift) + { + if ((line < m_height) && (line >= 0)) + { + m_currentLine = m_imageData + line * m_width; + m_lineShiftData[line] = (1.0f + shift) * 127.5f; + } + else + { + m_currentLine = m_outOfBoundsLine; + } + } + + void setSampleValue(int column, int value) + { + if ((column < m_width - 2) && (column >= -2)) + { + m_currentLine[column + 2] = value; + } + } + +private: + int m_width; + int m_height; + + int* m_imageData; + int* m_lineShiftData; + + int* m_currentLine; + int* m_outOfBoundsLine; +}; + class SDRGUI_API TVScreenAnalog : public QGLWidget, protected QOpenGLFunctions { Q_OBJECT QTimer m_objTimer; - QMutex m_objMutex; bool m_isDataChanged; - int m_objTextureLoc1; - int m_objTextureLoc2; - int m_objImageWidthLoc; - int m_objImageHeightLoc; - int m_objTexelWidthLoc; - int m_objTexelHeightLoc; + int m_textureLoc1; + int m_textureLoc2; + int m_imageWidthLoc; + int m_imageHeightLoc; + int m_texelWidthLoc; + int m_texelHeightLoc; int m_vertexAttribIndex; int m_texCoordAttribIndex; + + std::shared_ptr m_data; + std::shared_ptr m_shader; - - float m_time; - - int m_cols; - int m_rows; - - int* m_objCurrentRow; - - std::shared_ptr m_image; - std::shared_ptr m_lineShifts; std::shared_ptr m_imageTexture; std::shared_ptr m_lineShiftsTexture; public: TVScreenAnalog(QWidget *parent); + std::shared_ptr getData(); void resizeTVScreen(int intCols, int intRows); - void selectRow(int intLine, float shift); - void setDataColor(int intCol, int objColor); void renderImage(); private: