diff --git a/openhantek/src/glscope.cpp b/openhantek/src/glscope.cpp index 2134372..b720831 100644 --- a/openhantek/src/glscope.cpp +++ b/openhantek/src/glscope.cpp @@ -166,7 +166,7 @@ void GlScope::initializeGL() { m_marker.create(); m_marker.bind(); m_marker.setUsagePattern(QOpenGLBuffer::StaticDraw); - m_marker.allocate(4 * sizeof(QVector3D)); + m_marker.allocate(int(vaMarker.size() * sizeof(Line))); m_program->enableAttributeArray(vertexLocation); m_program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, 0); } @@ -177,10 +177,18 @@ void GlScope::initializeGL() { void GlScope::showData(PPresult *data) { if (!m_program || !m_program->isLinked()) return; makeCurrent(); - m_GraphHistory.resize(view->digitalPhosphorDraws()); - m_GraphHistory[currentGraphInHistory].writeData(data, m_program.get(), vertexLocation); - currentGraphInHistory = (currentGraphInHistory + 1) % m_GraphHistory.size(); - doneCurrent(); + // Remove too much entries + while (view->digitalPhosphorDraws() < m_GraphHistory.size()) m_GraphHistory.pop_back(); + + // Add if missing + if (view->digitalPhosphorDraws() > m_GraphHistory.size()) { m_GraphHistory.resize(m_GraphHistory.size() + 1); } + + // Move last item to front + m_GraphHistory.splice(m_GraphHistory.begin(), m_GraphHistory, std::prev(m_GraphHistory.end())); + + // Add new entry + m_GraphHistory.front().writeData(data, m_program.get(), vertexLocation); + // doneCurrent(); } void GlScope::paintGL() { @@ -210,13 +218,13 @@ void GlScope::paintGL() { m_program->setUniformValue(matrixLocation, pmvMatrix * m); } - for (unsigned historyIndex = 0; historyIndex < m_GraphHistory.size(); ++historyIndex) { - unsigned graphID = (historyIndex + currentGraphInHistory) % m_GraphHistory.size(); - Graph &graph = m_GraphHistory[graphID]; + unsigned historyIndex = 0; + for (Graph &graph : m_GraphHistory) { for (ChannelID channel = 0; channel < scope->voltage.size(); ++channel) { drawSpectrumChannelGraph(channel, graph, (int)historyIndex); drawVoltageChannelGraph(channel, graph, (int)historyIndex); } + ++historyIndex; } gl->glDisable(GL_POINT_SMOOTH); @@ -377,18 +385,25 @@ void GlScope::drawMarkers() { m_vaoMarker.bind(); - for (unsigned marker = 0; marker < MARKER_COUNT; ++marker) { + for (unsigned marker = 0; marker < vaMarker.size(); ++marker) { if (!scope->horizontal.marker_visible[marker]) continue; vaMarker[marker] = {QVector3D((GLfloat)scope->horizontal.marker[marker], -DIVS_VOLTAGE, 0.0f), QVector3D((GLfloat)scope->horizontal.marker[marker], DIVS_VOLTAGE, 0.0f)}; + } - m_marker.bind(); - auto ptr = m_marker.mapRange(0, sizeof(Line), QOpenGLBuffer::RangeInvalidateBuffer | QOpenGLBuffer::RangeWrite); - memcpy(ptr, &vaMarker[marker], sizeof(Line)); - m_marker.unmap(); + // Write coordinates to GPU + m_marker.bind(); + m_marker.write(0, vaMarker.data(), vaMarker.size() * sizeof(Line)); + + // Draw all + gl->glLineWidth(1); + gl->glDrawArrays(GL_LINES, 0, (GLsizei)vaMarker.size() * 2); + m_marker.release(); - gl->glLineWidth((marker == selectedMarker) ? 3 : 1); - gl->glDrawArrays(GL_LINES, 0, (GLsizei)2); + // Draw selected + if (selectedMarker != NO_MARKER) { + gl->glLineWidth(3); + gl->glDrawArrays(GL_LINES, selectedMarker * 2, (GLsizei)2); } m_vaoMarker.release(); @@ -398,7 +413,6 @@ void GlScope::drawVoltageChannelGraph(ChannelID channel, Graph &graph, int histo if (!scope->voltage[channel].used) return; m_program->setUniformValue(colorLocation, view->screen.voltage[channel].darker(100 + 10 * historyIndex)); - Graph::VaoCount &v = graph.vaoVoltage[channel]; QOpenGLVertexArrayObject::Binder b(v.first); diff --git a/openhantek/src/glscope.h b/openhantek/src/glscope.h index eaa6efe..43d6cc7 100644 --- a/openhantek/src/glscope.h +++ b/openhantek/src/glscope.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include #include @@ -93,7 +94,7 @@ class GlScope : public QOpenGLWidget { void generateGrid(); // Graphs - std::vector m_GraphHistory; + std::list m_GraphHistory; unsigned currentGraphInHistory = 0; // OpenGL shader, matrix, var-locations @@ -102,4 +103,5 @@ class GlScope : public QOpenGLWidget { int colorLocation; int vertexLocation; int matrixLocation; + int selectionLocation; }; diff --git a/openhantek/src/glscopegraph.cpp b/openhantek/src/glscopegraph.cpp index 5548baa..96b7e6c 100644 --- a/openhantek/src/glscopegraph.cpp +++ b/openhantek/src/glscopegraph.cpp @@ -13,6 +13,7 @@ void Graph::writeData(PPresult *data, QOpenGLShaderProgram *program, int vertexL for (ChannelGraph &cg : data->vaChannelSpectrum) neededMemory += cg.size() * sizeof(QVector3D); buffer.bind(); + program->bind(); // Allocate space if necessary if (neededMemory > allocatedMem) { @@ -32,7 +33,10 @@ void Graph::writeData(PPresult *data, QOpenGLShaderProgram *program, int vertexL int dataSize; // Voltage channel - if (!v.first) v.first = new QOpenGLVertexArrayObject; + if (!v.first) { + v.first = new QOpenGLVertexArrayObject; + if (!v.first->create()) throw new std::runtime_error("QOpenGLVertexArrayObject create failed"); + } ChannelGraph &gVoltage = data->vaChannelVoltage[channel]; v.first->bind(); dataSize = int(gVoltage.size() * sizeof(QVector3D)); @@ -44,7 +48,10 @@ void Graph::writeData(PPresult *data, QOpenGLShaderProgram *program, int vertexL offset += dataSize; // Spectrum channel - if (!s.first) s.first = new QOpenGLVertexArrayObject; + if (!s.first) { + s.first = new QOpenGLVertexArrayObject; + if (!s.first->create()) throw new std::runtime_error("QOpenGLVertexArrayObject create failed"); + } ChannelGraph &gSpectrum = data->vaChannelSpectrum[channel]; s.first->bind(); dataSize = int(gSpectrum.size() * sizeof(QVector3D)); diff --git a/openhantek/src/glscopegraph.h b/openhantek/src/glscopegraph.h index cae9190..222bd19 100644 --- a/openhantek/src/glscopegraph.h +++ b/openhantek/src/glscopegraph.h @@ -12,10 +12,12 @@ #include "post/ppresult.h" struct Graph { - Graph(); + explicit Graph(); + Graph(const Graph &) = delete; + Graph(const Graph &&) = delete; ~Graph(); - void writeData(PPresult *data, QOpenGLShaderProgram* program, int vertexLocation); - typedef std::pair VaoCount; + void writeData(PPresult *data, QOpenGLShaderProgram *program, int vertexLocation); + typedef std::pair VaoCount; public: int allocatedMem = 0; diff --git a/openhantek/src/post/graphgenerator.cpp b/openhantek/src/post/graphgenerator.cpp index 3f6828b..4d04e77 100644 --- a/openhantek/src/post/graphgenerator.cpp +++ b/openhantek/src/post/graphgenerator.cpp @@ -62,7 +62,7 @@ void GraphGenerator::generateGraphsTYvoltage(PPresult *result) { size_t neededSize = sampleCount * 2; // Set size directly to avoid reallocations - target.resize(neededSize); + target.reserve(neededSize); // What's the horizontal distance between sampling points? float horizontalFactor = (float)(samples.interval / scope->horizontal.timebase); @@ -104,7 +104,7 @@ void GraphGenerator::generateGraphsTYspectrum(PPresult *result) { size_t neededSize = sampleCount * 2; // Set size directly to avoid reallocations - target.resize(neededSize); + target.reserve(neededSize); // What's the horizontal distance between sampling points? float horizontalFactor = (float)(samples.interval / scope->horizontal.frequencybase); @@ -160,7 +160,7 @@ void GraphGenerator::generateGraphsXY(PPresult *result, const DsoSettingsScope * // Check if the sample count has changed const size_t sampleCount = std::min(xSamples.sample.size(), ySamples.sample.size()); ChannelGraph &drawLines = result->vaChannelVoltage[channel]; - drawLines.resize(sampleCount * 2); + drawLines.reserve(sampleCount * 2); // Fill vector array std::vector::const_iterator xIterator = xSamples.sample.begin();