Commit c19372354698f6689f50be839fdb27e4e8449e5c

Authored by David Graeff
Committed by David Gräff
1 parent 0f3e1d63

Use OpenGL 3.2 instead of 3.3 to make it work on MacOSX

Fix:
* Move all GL startup calls to GLScope::fixOpenGLversion
* Depending on OpenGL or ES availability initialize the QSurfaceFormat
* Don't crash if the shader compilation failed. Show a nice message instead.

Optimize:
* Don't write the markers to the GPU each frame update, only
  do this if they actually changed position.

Code style:
* LevelSlider: Don't return a value for set* Methods.
* Don't rely on the LevelSliders step to calculate the marker position in the OpenGL view.
openhantek/src/dsowidget.cpp
... ... @@ -5,8 +5,8 @@
5 5 #include <QFileDialog>
6 6 #include <QGridLayout>
7 7 #include <QLabel>
8   -#include <QTimer>
9 8 #include <QSignalBlocker>
  9 +#include <QTimer>
10 10  
11 11 #include "dsowidget.h"
12 12  
... ... @@ -37,11 +37,12 @@ DsoWidget::DsoWidget(DsoSettingsScope *scope, DsoSettingsView *view, const Dso::
37 37 setupSliders(mainSliders);
38 38 setupSliders(zoomSliders);
39 39  
40   - connect(mainScope, &GlScope::markerMoved, [this] (int marker, double position) {
41   - double step = this->mainSliders.markerSlider->step(marker);
  40 + connect(mainScope, &GlScope::markerMoved, [this](int marker, double position) {
  41 + double value = std::round(position / MARKER_STEP) * MARKER_STEP;
42 42  
43   - this->scope->horizontal.marker[marker] =
44   - this->mainSliders.markerSlider->setValue(marker, std::round(position / step) * step);
  43 + this->scope->horizontal.marker[marker] = value;
  44 + this->mainSliders.markerSlider->setValue(marker, value);
  45 + this->mainScope->markerUpdated();
45 46 });
46 47  
47 48 // The table for the settings
... ... @@ -175,14 +176,6 @@ DsoWidget::DsoWidget(DsoSettingsScope *scope, DsoSettingsView *view, const Dso::
175 176 mainLayout->setRowMinimumHeight(row++, 8);
176 177 mainLayout->addLayout(measurementLayout, row++, 0, 1, 5);
177 178  
178   - // Apply settings and update measured values
179   - updateTriggerDetails();
180   - updateRecordLength(scope->horizontal.recordLength);
181   - updateFrequencybase(scope->horizontal.frequencybase);
182   - updateSamplerate(scope->horizontal.samplerate);
183   - updateTimebase(scope->horizontal.timebase);
184   - updateZoom(view->zoom);
185   -
186 179 // The widget itself
187 180 setPalette(palette);
188 181 setBackgroundRole(QPalette::Background);
... ... @@ -205,9 +198,6 @@ DsoWidget::DsoWidget(DsoSettingsScope *scope, DsoSettingsView *view, const Dso::
205 198 zoomScope->update();
206 199 });
207 200 zoomSliders.markerSlider->setEnabled(false);
208   -
209   - updateTriggerSource();
210   - adaptTriggerPositionSlider();
211 201 }
212 202  
213 203 void DsoWidget::setupSliders(DsoWidget::Sliders &sliders) {
... ... @@ -242,11 +232,10 @@ void DsoWidget::setupSliders(DsoWidget::Sliders &amp;sliders) {
242 232 sliders.triggerLevelSlider = new LevelSlider(Qt::LeftArrow);
243 233 for (ChannelID channel = 0; channel < spec->channels; ++channel) {
244 234 sliders.triggerLevelSlider->addSlider((int)channel);
245   - sliders.triggerLevelSlider->setColor(
246   - channel,
247   - (!scope->trigger.special && channel == scope->trigger.source)
248   - ? view->screen.voltage[channel]
249   - : view->screen.voltage[channel].darker());
  235 + sliders.triggerLevelSlider->setColor(channel,
  236 + (!scope->trigger.special && channel == scope->trigger.source)
  237 + ? view->screen.voltage[channel]
  238 + : view->screen.voltage[channel].darker());
250 239 adaptTriggerLevelSlider(sliders, channel);
251 240 sliders.triggerLevelSlider->setValue(channel, scope->voltage[channel].trigger);
252 241 sliders.triggerLevelSlider->setIndexVisible(channel, scope->voltage[channel].used);
... ... @@ -257,7 +246,7 @@ void DsoWidget::setupSliders(DsoWidget::Sliders &amp;sliders) {
257 246 for (int marker = 0; marker < MARKER_COUNT; ++marker) {
258 247 sliders.markerSlider->addSlider(QString::number(marker + 1), marker);
259 248 sliders.markerSlider->setLimits(marker, -DIVS_TIME / 2, DIVS_TIME / 2);
260   - sliders.markerSlider->setStep(marker, DIVS_TIME / 100.0);
  249 + sliders.markerSlider->setStep(marker, MARKER_STEP);
261 250 sliders.markerSlider->setValue(marker, scope->horizontal.marker[marker]);
262 251 sliders.markerSlider->setIndexVisible(marker, true);
263 252 }
... ... @@ -269,9 +258,9 @@ void DsoWidget::setExporterForNextFrame(std::unique_ptr&lt;Exporter&gt; exporter) {
269 258  
270 259 /// \brief Set the trigger level sliders minimum and maximum to the new values.
271 260 void DsoWidget::adaptTriggerLevelSlider(DsoWidget::Sliders &sliders, ChannelID channel) {
272   - sliders.triggerLevelSlider->setLimits(
273   - (int)channel, (-DIVS_VOLTAGE / 2 - scope->voltage[channel].offset) * scope->gain(channel),
274   - (DIVS_VOLTAGE / 2 - scope->voltage[channel].offset) * scope->gain(channel));
  261 + sliders.triggerLevelSlider->setLimits((int)channel,
  262 + (-DIVS_VOLTAGE / 2 - scope->voltage[channel].offset) * scope->gain(channel),
  263 + (DIVS_VOLTAGE / 2 - scope->voltage[channel].offset) * scope->gain(channel));
275 264 sliders.triggerLevelSlider->setStep((int)channel, scope->gain(channel) * 0.05);
276 265 }
277 266  
... ... @@ -292,14 +281,10 @@ void DsoWidget::setMeasurementVisible(ChannelID channel) {
292 281 }
293 282  
294 283 measurementGainLabel[channel]->setVisible(scope->voltage[channel].used);
295   - if (!scope->voltage[channel].used) {
296   - measurementGainLabel[channel]->setText(QString());
297   - }
  284 + if (!scope->voltage[channel].used) { measurementGainLabel[channel]->setText(QString()); }
298 285  
299 286 measurementMagnitudeLabel[channel]->setVisible(scope->spectrum[channel].used);
300   - if (!scope->spectrum[channel].used) {
301   - measurementMagnitudeLabel[channel]->setText(QString());
302   - }
  287 + if (!scope->spectrum[channel].used) { measurementMagnitudeLabel[channel]->setText(QString()); }
303 288 }
304 289  
305 290 /// \brief Update the label about the marker measurements
... ... @@ -411,16 +396,15 @@ void DsoWidget::updateTriggerSource() {
411 396 if (scope->trigger.special || scope->trigger.source >= spec->channels) {
412 397 mainSliders.triggerPositionSlider->setColor(0, view->screen.border);
413 398 zoomSliders.triggerPositionSlider->setColor(0, view->screen.border);
414   - }
415   - else {
  399 + } else {
416 400 mainSliders.triggerPositionSlider->setColor(0, view->screen.voltage[scope->trigger.source]);
417 401 zoomSliders.triggerPositionSlider->setColor(0, view->screen.voltage[scope->trigger.source]);
418 402 }
419 403  
420 404 for (ChannelID channel = 0; channel < spec->channels; ++channel) {
421 405 QColor color = (!scope->trigger.special && channel == scope->trigger.source)
422   - ? view->screen.voltage[channel]
423   - : view->screen.voltage[channel].darker();
  406 + ? view->screen.voltage[channel]
  407 + : view->screen.voltage[channel].darker();
424 408 mainSliders.triggerLevelSlider->setColor(channel, color);
425 409 zoomSliders.triggerLevelSlider->setColor(channel, color);
426 410 }
... ... @@ -484,8 +468,7 @@ void DsoWidget::updateZoom(bool enabled) {
484 468 zoomSliders.offsetSlider->show();
485 469 zoomSliders.triggerPositionSlider->show();
486 470 zoomSliders.triggerLevelSlider->show();
487   - }
488   - else {
  471 + } else {
489 472 zoomSliders.offsetSlider->hide();
490 473 zoomSliders.triggerPositionSlider->hide();
491 474 zoomSliders.triggerLevelSlider->hide();
... ... @@ -535,6 +518,20 @@ void DsoWidget::showNew(std::shared_ptr&lt;PPresult&gt; data) {
535 518 }
536 519 }
537 520  
  521 +void DsoWidget::showEvent(QShowEvent *event) {
  522 + QWidget::showEvent(event);
  523 + // Apply settings and update measured values
  524 + updateTriggerDetails();
  525 + updateRecordLength(scope->horizontal.recordLength);
  526 + updateFrequencybase(scope->horizontal.frequencybase);
  527 + updateSamplerate(scope->horizontal.samplerate);
  528 + updateTimebase(scope->horizontal.timebase);
  529 + updateZoom(view->zoom);
  530 +
  531 + updateTriggerSource();
  532 + adaptTriggerPositionSlider();
  533 +}
  534 +
538 535 /// \brief Handles valueChanged signal from the offset sliders.
539 536 /// \param channel The channel whose offset was changed.
540 537 /// \param value The new offset for the channel.
... ... @@ -573,8 +570,7 @@ void DsoWidget::adaptTriggerPositionSlider() {
573 570 if (m1 != m2 && m1 <= value && value <= m2) {
574 571 zoomSliders.triggerPositionSlider->setIndexVisible(0, true);
575 572 zoomSliders.triggerPositionSlider->setValue(0, (value - m1) / (m2 - m1));
576   - }
577   - else {
  573 + } else {
578 574 zoomSliders.triggerPositionSlider->setIndexVisible(0, false);
579 575 }
580 576 }
... ...
openhantek/src/dsowidget.h
... ... @@ -42,6 +42,7 @@ class DsoWidget : public QWidget {
42 42 void showNew(std::shared_ptr<PPresult> data);
43 43  
44 44 protected:
  45 + virtual void showEvent(QShowEvent *event);
45 46 void setupSliders(Sliders &sliders);
46 47 void adaptTriggerLevelSlider(DsoWidget::Sliders &sliders, ChannelID channel);
47 48 void adaptTriggerPositionSlider();
... ...
openhantek/src/glscope.cpp
... ... @@ -4,12 +4,16 @@
4 4 #include <iostream>
5 5  
6 6 #include <QColor>
  7 +#include <QCoreApplication>
7 8 #include <QDebug>
8 9 #include <QMatrix4x4>
  10 +#include <QMessageBox>
9 11 #include <QMouseEvent>
10 12 #include <QOpenGLShaderProgram>
  13 +#include <QPainter>
11 14  
12   -#include <QOpenGLFunctions_3_3_Core>
  15 +// We can't be more modern than OpenGL 3.2 or ES2 because of MacOSX.
  16 +#include <QOpenGLFunctions_3_2_Core>
13 17 #include <QOpenGLFunctions_ES2>
14 18  
15 19 #include "glscope.h"
... ... @@ -23,7 +27,7 @@
23 27 #if defined(QT_OPENGL_ES_2)
24 28 typedef QOpenGLFunctions_ES2 OPENGL_VER;
25 29 #else
26   -typedef QOpenGLFunctions_3_3_Core OPENGL_VER;
  30 +typedef QOpenGLFunctions_3_2_Core OPENGL_VER;
27 31 #endif
28 32  
29 33 GlScope *GlScope::createNormal(DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent) {
... ... @@ -38,6 +42,25 @@ GlScope *GlScope::createZoomed(DsoSettingsScope *scope, DsoSettingsView *view, Q
38 42 return s;
39 43 }
40 44  
  45 +void GlScope::fixOpenGLversion() {
  46 + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
  47 +
  48 + // Prefer full desktop OpenGL without fixed pipeline
  49 + QSurfaceFormat format;
  50 + format.setSamples(4); // Antia-Aliasing, Multisampling
  51 +#if defined(QT_OPENGL_ES_2)
  52 + format.setVersion(2, 0);
  53 + format.setProfile(QSurfaceFormat::CoreProfile);
  54 + format.setRenderableType(QSurfaceFormat::OpenGLES);
  55 + QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
  56 +#else
  57 + format.setVersion(3, 2);
  58 + format.setProfile(QSurfaceFormat::CoreProfile);
  59 + format.setRenderableType(QSurfaceFormat::OpenGL);
  60 +#endif
  61 + QSurfaceFormat::setDefaultFormat(format);
  62 +}
  63 +
41 64 GlScope::GlScope(DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent)
42 65 : QOpenGLWidget(parent), scope(scope), view(view) {
43 66 vaMarker.resize(MARKER_COUNT);
... ... @@ -51,7 +74,7 @@ void GlScope::mousePressEvent(QMouseEvent *event) {
51 74 double distance = DIVS_TIME;
52 75 selectedMarker = NO_MARKER;
53 76 // Capture nearest marker located within snap area (+/- 1% of full scale).
54   - for (int marker = 0; marker < MARKER_COUNT; ++marker) {
  77 + for (unsigned marker = 0; marker < MARKER_COUNT; ++marker) {
55 78 if (!scope->horizontal.marker_visible[marker]) continue;
56 79 if (fabs(scope->horizontal.marker[marker] - position) < std::min(distance, DIVS_TIME / 100.0)) {
57 80 distance = fabs(scope->horizontal.marker[marker] - position);
... ... @@ -89,13 +112,34 @@ void GlScope::mouseReleaseEvent(QMouseEvent *event) {
89 112 event->accept();
90 113 }
91 114  
  115 +void GlScope::paintEvent(QPaintEvent *event) {
  116 + // Draw error message if OpenGL failed
  117 + if (!shaderCompileSuccess) {
  118 + QPainter painter(this);
  119 + painter.setRenderHint(QPainter::Antialiasing, true);
  120 + QFont font = painter.font();
  121 + font.setPointSize(18);
  122 + painter.setFont(font);
  123 + painter.drawText(rect(), Qt::AlignCenter, errorMessage);
  124 + event->accept();
  125 + } else
  126 + QOpenGLWidget::paintEvent(event);
  127 +}
  128 +
92 129 void GlScope::initializeGL() {
93   - auto *gl = context()->versionFunctions<OPENGL_VER>();
  130 + if (!QOpenGLShaderProgram::hasOpenGLShaderPrograms(context())) {
  131 + errorMessage = tr("System does not support OpenGL Shading Language (GLSL)");
  132 + return;
  133 + }
  134 + if (m_program) {
  135 + qWarning() << "OpenGL init called twice!";
  136 + return;
  137 + }
94 138  
95   - m_program = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram(context()));
  139 + auto program = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram(context()));
96 140  
97 141 const char *vshaderES = R"(
98   - #version 330
  142 + #version 100
99 143 attribute highp vec3 vertex;
100 144 uniform mat4 matrix;
101 145 void main()
... ... @@ -104,9 +148,14 @@ void GlScope::initializeGL() {
104 148 gl_PointSize = 1.0;
105 149 }
106 150 )";
  151 + const char *fshaderES = R"(
  152 + #version 100
  153 + uniform highp vec4 colour;
  154 + void main() { gl_FragColor = colour; }
  155 + )";
107 156  
108 157 const char *vshaderCore = R"(
109   - #version 330
  158 + #version 150
110 159 in highp vec3 vertex;
111 160 uniform mat4 matrix;
112 161 void main()
... ... @@ -116,37 +165,39 @@ void GlScope::initializeGL() {
116 165 }
117 166 )";
118 167 const char *fshaderCore = R"(
119   - #version 330
  168 + #version 150
120 169 uniform highp vec4 colour;
121   - void main() { gl_FragColor = colour; }
  170 + out vec4 flatColor;
  171 + void main() { flatColor = colour; }
122 172 )";
123 173  
124 174 qDebug() << "compile shaders";
125 175 // Compile vertex shader
126 176 bool coreShaders = QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile;
127   - if (!m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, coreShaders ? vshaderCore : vshaderES) ||
128   - !m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fshaderCore)) {
129   - qWarning() << "Failed to compile OpenGL shader programs.\n" << m_program->log();
  177 + if (!program->addShaderFromSourceCode(QOpenGLShader::Vertex, coreShaders ? vshaderCore : vshaderES) ||
  178 + !program->addShaderFromSourceCode(QOpenGLShader::Fragment, coreShaders ? fshaderCore : fshaderES)) {
  179 + errorMessage = "Failed to compile OpenGL shader programs.\n" + program->log();
130 180 return;
131 181 }
132 182  
133 183 // Link shader pipeline
134   - if (!m_program->link() || !m_program->bind()) {
135   - qWarning() << "Failed to link/bind OpenGL shader programs";
  184 + if (!program->link() || !program->bind()) {
  185 + errorMessage = "Failed to link/bind OpenGL shader programs\n" + program->log();
136 186 return;
137 187 }
138 188  
139   - vertexLocation = m_program->attributeLocation("vertex");
140   - matrixLocation = m_program->uniformLocation("matrix");
141   - colorLocation = m_program->uniformLocation("colour");
  189 + vertexLocation = program->attributeLocation("vertex");
  190 + matrixLocation = program->uniformLocation("matrix");
  191 + colorLocation = program->uniformLocation("colour");
142 192  
143 193 if (vertexLocation == -1 || colorLocation == -1 || matrixLocation == -1) {
144 194 qWarning() << "Failed to locate shader variable";
145 195 return;
146 196 }
147 197  
148   - m_program->bind();
  198 + program->bind();
149 199  
  200 + auto *gl = context()->versionFunctions<OPENGL_VER>();
150 201 gl->glDisable(GL_DEPTH_TEST);
151 202 gl->glEnable(GL_BLEND);
152 203 // Enable depth buffer
... ... @@ -159,7 +210,7 @@ void GlScope::initializeGL() {
159 210 QColor bg = view->screen.background;
160 211 gl->glClearColor((GLfloat)bg.redF(), (GLfloat)bg.greenF(), (GLfloat)bg.blueF(), (GLfloat)bg.alphaF());
161 212  
162   - generateGrid();
  213 + generateGrid(program.get());
163 214  
164 215 {
165 216 m_vaoMarker.create();
... ... @@ -168,15 +219,18 @@ void GlScope::initializeGL() {
168 219 m_marker.bind();
169 220 m_marker.setUsagePattern(QOpenGLBuffer::StaticDraw);
170 221 m_marker.allocate(int(vaMarker.size() * sizeof(Line)));
171   - m_program->enableAttributeArray(vertexLocation);
172   - m_program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, 0);
  222 + program->enableAttributeArray(vertexLocation);
  223 + program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, 0);
173 224 }
174 225  
175   - m_program->release();
  226 + markerUpdated();
  227 +
  228 + m_program = std::move(program);
  229 + shaderCompileSuccess = true;
176 230 }
177 231  
178 232 void GlScope::showData(PPresult *data) {
179   - if (!m_program || !m_program->isLinked()) return;
  233 + if (!shaderCompileSuccess) return;
180 234 makeCurrent();
181 235 // Remove too much entries
182 236 while (view->digitalPhosphorDraws() < m_GraphHistory.size()) m_GraphHistory.pop_back();
... ... @@ -192,8 +246,23 @@ void GlScope::showData(PPresult *data) {
192 246 // doneCurrent();
193 247 }
194 248  
  249 +void GlScope::markerUpdated()
  250 +{
  251 +
  252 + for (unsigned marker = 0; marker < vaMarker.size(); ++marker) {
  253 + if (!scope->horizontal.marker_visible[marker]) continue;
  254 + vaMarker[marker] = {QVector3D((GLfloat)scope->horizontal.marker[marker], -DIVS_VOLTAGE, 0.0f),
  255 + QVector3D((GLfloat)scope->horizontal.marker[marker], DIVS_VOLTAGE, 0.0f)};
  256 + }
  257 +
  258 + // Write coordinates to GPU
  259 + makeCurrent();
  260 + m_marker.bind();
  261 + m_marker.write(0, vaMarker.data(), vaMarker.size() * sizeof(Line));
  262 +}
  263 +
195 264 void GlScope::paintGL() {
196   - if (!m_program->isLinked()) return;
  265 + if (!shaderCompileSuccess) return;
197 266  
198 267 auto *gl = context()->versionFunctions<OPENGL_VER>();
199 268  
... ... @@ -231,6 +300,7 @@ void GlScope::paintGL() {
231 300 }
232 301  
233 302 void GlScope::resizeGL(int width, int height) {
  303 + if (!shaderCompileSuccess) return;
234 304 auto *gl = context()->versionFunctions<OPENGL_VER>();
235 305 gl->glViewport(0, 0, (GLint)width, (GLint)height);
236 306  
... ... @@ -248,30 +318,7 @@ void GlScope::resizeGL(int width, int height) {
248 318 m_program->release();
249 319 }
250 320  
251   -void GlScope::drawGrid() {
252   - auto *gl = context()->versionFunctions<OPENGL_VER>();
253   - gl->glLineWidth(1);
254   -
255   - // Grid
256   - m_vaoGrid[0].bind();
257   - m_program->setUniformValue(colorLocation, view->screen.grid);
258   - gl->glDrawArrays(GL_POINTS, 0, gridDrawCounts[0]);
259   - m_vaoGrid[0].release();
260   -
261   - // Axes
262   - m_vaoGrid[1].bind();
263   - m_program->setUniformValue(colorLocation, view->screen.axes);
264   - gl->glDrawArrays(GL_LINES, 0, gridDrawCounts[1]);
265   - m_vaoGrid[1].release();
266   -
267   - // Border
268   - m_vaoGrid[2].bind();
269   - m_program->setUniformValue(colorLocation, view->screen.border);
270   - gl->glDrawArrays(GL_LINE_LOOP, 0, gridDrawCounts[2]);
271   - m_vaoGrid[2].release();
272   -}
273   -
274   -void GlScope::generateGrid() {
  321 +void GlScope::generateGrid(QOpenGLShaderProgram *program) {
275 322 gridDrawCounts[0] = 0;
276 323 gridDrawCounts[1] = 0;
277 324 gridDrawCounts[2] = 0;
... ... @@ -286,8 +333,8 @@ void GlScope::generateGrid() {
286 333 m_vaoGrid[0].create();
287 334 QOpenGLVertexArrayObject::Binder b(&m_vaoGrid[0]);
288 335 m_grid.bind();
289   - m_program->enableAttributeArray(vertexLocation);
290   - m_program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, 0);
  336 + program->enableAttributeArray(vertexLocation);
  337 + program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, 0);
291 338 }
292 339  
293 340 // Draw vertical lines
... ... @@ -318,8 +365,8 @@ void GlScope::generateGrid() {
318 365 m_vaoGrid[1].create();
319 366 QOpenGLVertexArrayObject::Binder b(&m_vaoGrid[1]);
320 367 m_grid.bind();
321   - m_program->enableAttributeArray(vertexLocation);
322   - m_program->setAttributeBuffer(vertexLocation, GL_FLOAT, int(vaGrid.size() * sizeof(QVector3D)), 3);
  368 + program->enableAttributeArray(vertexLocation);
  369 + program->setAttributeBuffer(vertexLocation, GL_FLOAT, int(vaGrid.size() * sizeof(QVector3D)), 3);
323 370 }
324 371  
325 372 // Axes
... ... @@ -353,8 +400,8 @@ void GlScope::generateGrid() {
353 400 m_vaoGrid[2].create();
354 401 QOpenGLVertexArrayObject::Binder b(&m_vaoGrid[2]);
355 402 m_grid.bind();
356   - m_program->enableAttributeArray(vertexLocation);
357   - m_program->setAttributeBuffer(vertexLocation, GL_FLOAT, int(vaGrid.size() * sizeof(QVector3D)), 3);
  403 + program->enableAttributeArray(vertexLocation);
  404 + program->setAttributeBuffer(vertexLocation, GL_FLOAT, int(vaGrid.size() * sizeof(QVector3D)), 3);
358 405 }
359 406  
360 407 // Border
... ... @@ -368,6 +415,29 @@ void GlScope::generateGrid() {
368 415 m_grid.release();
369 416 }
370 417  
  418 +void GlScope::drawGrid() {
  419 + auto *gl = context()->versionFunctions<OPENGL_VER>();
  420 + gl->glLineWidth(1);
  421 +
  422 + // Grid
  423 + m_vaoGrid[0].bind();
  424 + m_program->setUniformValue(colorLocation, view->screen.grid);
  425 + gl->glDrawArrays(GL_POINTS, 0, gridDrawCounts[0]);
  426 + m_vaoGrid[0].release();
  427 +
  428 + // Axes
  429 + m_vaoGrid[1].bind();
  430 + m_program->setUniformValue(colorLocation, view->screen.axes);
  431 + gl->glDrawArrays(GL_LINES, 0, gridDrawCounts[1]);
  432 + m_vaoGrid[1].release();
  433 +
  434 + // Border
  435 + m_vaoGrid[2].bind();
  436 + m_program->setUniformValue(colorLocation, view->screen.border);
  437 + gl->glDrawArrays(GL_LINE_LOOP, 0, gridDrawCounts[2]);
  438 + m_vaoGrid[2].release();
  439 +}
  440 +
371 441 void GlScope::drawMarkers() {
372 442 auto *gl = context()->versionFunctions<OPENGL_VER>();
373 443 QColor trColor = view->screen.markers;
... ... @@ -375,23 +445,13 @@ void GlScope::drawMarkers() {
375 445  
376 446 m_vaoMarker.bind();
377 447  
378   - for (unsigned marker = 0; marker < vaMarker.size(); ++marker) {
379   - if (!scope->horizontal.marker_visible[marker]) continue;
380   - vaMarker[marker] = {QVector3D((GLfloat)scope->horizontal.marker[marker], -DIVS_VOLTAGE, 0.0f),
381   - QVector3D((GLfloat)scope->horizontal.marker[marker], DIVS_VOLTAGE, 0.0f)};
382   - }
383   -
384   - // Write coordinates to GPU
385   - m_marker.bind();
386   - m_marker.write(0, vaMarker.data(), vaMarker.size() * sizeof(Line));
387   -
388 448 // Draw all
389 449 gl->glLineWidth(1);
390 450 gl->glDrawArrays(GL_LINES, 0, (GLsizei)vaMarker.size() * 2);
391   - m_marker.release();
392 451  
393 452 // Draw selected
394 453 if (selectedMarker != NO_MARKER) {
  454 + qWarning() << selectedMarker;
395 455 gl->glLineWidth(3);
396 456 gl->glDrawArrays(GL_LINES, selectedMarker * 2, (GLsizei)2);
397 457 }
... ...
openhantek/src/glscope.h
... ... @@ -31,10 +31,16 @@ class GlScope : public QOpenGLWidget {
31 31 QWidget *parent = 0);
32 32  
33 33 /**
  34 + * We need at least OpenGL 3.2 with shader version 150 or
  35 + * OpenGL ES 2.0 with shader version 100.
  36 + */
  37 + static void fixOpenGLversion();
  38 + /**
34 39 * Show new post processed data
35 40 * @param data
36 41 */
37 42 void showData(PPresult* data);
  43 + void markerUpdated();
38 44  
39 45 protected:
40 46 /// \brief Initializes the scope widget.
... ... @@ -42,21 +48,23 @@ class GlScope : public QOpenGLWidget {
42 48 /// \param parent The parent widget.
43 49 GlScope(DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent = 0);
44 50 virtual ~GlScope();
  51 + GlScope(const GlScope&) = delete;
45 52  
46 53 /// \brief Initializes OpenGL output.
47   - void initializeGL() override;
  54 + virtual void initializeGL() override;
48 55  
49 56 /// \brief Draw the graphs, marker and the grid.
50   - void paintGL() override;
  57 + virtual void paintGL() override;
51 58  
52 59 /// \brief Resize the widget.
53 60 /// \param width The new width of the widget.
54 61 /// \param height The new height of the widget.
55   - void resizeGL(int width, int height) override;
  62 + virtual void resizeGL(int width, int height) override;
56 63  
57   - void mousePressEvent(QMouseEvent *event) override;
58   - void mouseMoveEvent(QMouseEvent *event) override;
59   - void mouseReleaseEvent(QMouseEvent *event) override;
  64 + virtual void mousePressEvent(QMouseEvent *event) override;
  65 + virtual void mouseMoveEvent(QMouseEvent *event) override;
  66 + virtual void mouseReleaseEvent(QMouseEvent *event) override;
  67 + virtual void paintEvent(QPaintEvent *event) override;
60 68  
61 69 /// \brief Draw the grid.
62 70 void drawGrid();
... ... @@ -91,13 +99,15 @@ class GlScope : public QOpenGLWidget {
91 99 QOpenGLBuffer m_grid;
92 100 QOpenGLVertexArrayObject m_vaoGrid[3];
93 101 GLsizei gridDrawCounts[3];
94   - void generateGrid();
  102 + void generateGrid(QOpenGLShaderProgram *program);
95 103  
96 104 // Graphs
97 105 std::list<Graph> m_GraphHistory;
98 106 unsigned currentGraphInHistory = 0;
99 107  
100 108 // OpenGL shader, matrix, var-locations
  109 + bool shaderCompileSuccess = false;
  110 + QString errorMessage;
101 111 std::unique_ptr<QOpenGLShaderProgram> m_program;
102 112 QMatrix4x4 pmvMatrix; ///< projection, view matrix
103 113 int colorLocation;
... ...
openhantek/src/main.cpp
... ... @@ -24,6 +24,8 @@
24 24 #include "usb/usbdevice.h"
25 25 #include "viewconstants.h"
26 26  
  27 +#include "glscope.h"
  28 +
27 29 #ifndef VERSION
28 30 #error "You need to run the cmake buildsystem!"
29 31 #endif
... ... @@ -69,14 +71,8 @@ int main(int argc, char *argv[]) {
69 71 QCoreApplication::setApplicationName("OpenHantek");
70 72 QCoreApplication::setApplicationVersion(VERSION);
71 73  
72   - QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
73   - QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
  74 + GlScope::fixOpenGLversion();
74 75  
75   - // Prefer full desktop OpenGL without fixed pipeline
76   - QSurfaceFormat format;
77   - format.setProfile(QSurfaceFormat::CoreProfile);
78   - format.setSamples(4); // Antia-Aliasing, Multisampling
79   - QSurfaceFormat::setDefaultFormat(format);
80 76 QApplication openHantekApplication(argc, argv);
81 77  
82 78 //////// Load translations ////////
... ... @@ -155,5 +151,10 @@ int main(int argc, char *argv[]) {
155 151  
156 152 postProcessingThread.quit();
157 153 postProcessingThread.wait(10000);
  154 +
  155 + if (context && device != nullptr) {
  156 + libusb_exit(context);
  157 + }
  158 +
158 159 return res;
159 160 }
... ...
openhantek/src/scopesettings.h
... ... @@ -11,6 +11,7 @@
11 11 #include <vector>
12 12  
13 13 #define MARKER_COUNT 2 ///< Number of markers
  14 +#define MARKER_STEP (DIVS_TIME / 100.0)
14 15  
15 16 /// \brief Holds the settings for the horizontal axis.
16 17 struct DsoSettingsScopeHorizontal {
... ...
openhantek/src/widgets/levelslider.cpp
... ... @@ -196,17 +196,14 @@ double LevelSlider::maximum(int index) const {
196 196 /// \param minimum The value a slider has at the bottommost/leftmost position.
197 197 /// \param maximum The value a slider has at the topmost/rightmost position.
198 198 /// \return -1 on error, fixValue result on success.
199   -int LevelSlider::setLimits(int index, double minimum, double maximum) {
200   - if (index < 0 || index >= this->slider.count()) return -1;
  199 +void LevelSlider::setLimits(int index, double minimum, double maximum) {
  200 + if (index < 0 || index >= this->slider.count()) return;
201 201  
202 202 this->slider[index]->minimum = minimum;
203 203 this->slider[index]->maximum = maximum;
204   - int result = this->fixValue(index);
205   -
  204 + this->fixValue(index);
206 205 this->calculateRect(index);
207 206 this->repaint();
208   -
209   - return result;
210 207 }
211 208  
212 209 /// \brief Return the step width of the sliders.
... ... @@ -243,8 +240,8 @@ double LevelSlider::value(int index) const {
243 240 /// \param index The index of the slider whose value should be set.
244 241 /// \param value The new value of the slider.
245 242 /// \return The new value of the slider.
246   -double LevelSlider::setValue(int index, double value) {
247   - if (index < 0 || index >= this->slider.count()) return -1;
  243 +void LevelSlider::setValue(int index, double value) {
  244 + if (index < 0 || index >= this->slider.count()) return;
248 245  
249 246 // Apply new value
250 247 this->slider[index]->value = value;
... ... @@ -254,8 +251,6 @@ double LevelSlider::setValue(int index, double value) {
254 251 this->repaint();
255 252  
256 253 if (this->pressedSlider < 0) emit valueChanged(index, value);
257   -
258   - return this->slider[index]->value;
259 254 }
260 255  
261 256 /// \brief Return the direction of the sliders.
... ... @@ -563,17 +558,14 @@ int LevelSlider::calculateWidth() {
563 558 /// \brief Fix the value if it's outside the limits.
564 559 /// \param index The index of the slider who should be fixed.
565 560 /// \return 0 when ok, -1 on error, 1 when increased and 2 when decreased.
566   -int LevelSlider::fixValue(int index) {
567   - if (index < 0 || index >= this->slider.count()) return -1;
  561 +void LevelSlider::fixValue(int index) {
  562 + if (index < 0 || index >= this->slider.count()) return;
568 563  
569 564 double lowest = qMin(this->slider[index]->minimum, this->slider[index]->maximum);
570 565 double highest = qMax(this->slider[index]->minimum, this->slider[index]->maximum);
571 566 if (this->slider[index]->value < lowest) {
572 567 this->slider[index]->value = lowest;
573   - return 1;
574 568 } else if (this->slider[index]->value > highest) {
575 569 this->slider[index]->value = highest;
576   - return 2;
577 570 }
578   - return 0;
579 571 }
... ...
openhantek/src/widgets/levelslider.h
... ... @@ -51,11 +51,11 @@ class LevelSlider : public QWidget {
51 51  
52 52 double minimum(int index) const;
53 53 double maximum(int index) const;
54   - int setLimits(int index, double minimum, double maximum);
  54 + void setLimits(int index, double minimum, double maximum);
55 55 double step(int index) const;
56 56 double setStep(int index, double step);
57 57 double value(int index) const;
58   - double setValue(int index, double value);
  58 + void setValue(int index, double value);
59 59  
60 60 // Parameters for all sliders
61 61 Qt::ArrowType direction() const;
... ... @@ -71,7 +71,7 @@ class LevelSlider : public QWidget {
71 71  
72 72 QRect calculateRect(int sliderId);
73 73 int calculateWidth();
74   - int fixValue(int index);
  74 + void fixValue(int index);
75 75  
76 76 QList<LevelSliderParameters *> slider; ///< The parameters for each slider
77 77 int pressedSlider; ///< The currently pressed (moved) slider
... ...