Skip to content

Commit 62c54e6

Browse files
committed
Improve OpenGL robustness; refactor glscope.cpp; fix #184
If the graphic system claims to support SL version 150 but this fails, fall back automatically to legacy version 120. If this also fails, show the hint to use the command line option '--useGLES' to switch from OpenGL to OpenGLES (OpenGL for Embedded Systems), which cannot be done automatically. Signed-off-by: Martin <Ho-Ro@users.noreply.github.com>
1 parent 3f65bbf commit 62c54e6

11 files changed

+233
-122
lines changed

README.md

+17-9
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99
OpenHantek6022 is a free software for **Hantek DSO6022** USB digital signal oscilloscopes that is actively developed on
1010
[github.com/OpenHantek/OpenHantek6022](https://github.com/OpenHantek/OpenHantek6022) - but only for Hantek 6022BE/BL and compatible scopes (Voltcraft, Darkwire, Protek, Acetech, etc.).
1111

12-
The program was initially developed by [David Gräff and others](https://github.com/OpenHantek/openhantek/graphs/contributors)
13-
on [github.com/OpenHantek/openhantek](https://github.com/OpenHantek/openhantek),
14-
but David [stopped maintaining](https://github.com/OpenHantek/openhantek/issues/277) the programm in December 2018.
15-
1612
<p><img alt="Image of main window on linux" width="100%" src="docs/images/screenshot_mainwindow.png"></p>
1713

1814
#### Content
@@ -29,6 +25,7 @@ but David [stopped maintaining](https://github.com/OpenHantek/openhantek/issues/
2925
* [Contribute](#contribute)
3026
* [Other DSO open source software](#other-dso-open-source-software)
3127
* [Other related software](#other-related-software)
28+
* [History](#history)
3229

3330
## About OpenHantek6022
3431
* Supported devices:
@@ -69,7 +66,7 @@ but David [stopped maintaining](https://github.com/OpenHantek/openhantek/issues/
6966
* Histogram function for voltage channels on right screen margin.
7067
* A [zoom view](docs/images/screenshot_mainwindow_with_zoom.png) with a freely selectable range.
7168
* Cursor measurement function for voltage, time, amplitude and frequency.
72-
* Export of the graphs to CSV, JPG, PNG file or to the printer.
69+
* Export of the graphs to JPG, PNG or PDF file or to the printer; data export as CSV or JSON.
7370
* Freely configurable colors.
7471
* Automatic adaption of iconset for light and [dark themes](docs/images/screenshot_mainwindow_dark.png).
7572
* The dock views on the main window can be [customized](https://github.com/OpenHantek/OpenHantek6022/issues/161#issuecomment-799597664) by dragging them around and stacking them.
@@ -127,15 +124,21 @@ On a Linux system start the program via the menu entry *OpenHantek (Digital Stor
127124

128125
You can explore the look and feel of OpenHantek6022 without the need for real scope hardware by running it from the command line as: `OpenHantek --demoMode`.
129126

130-
OpenHantek6022 runs also on legacy HW/SW that supports at least *OpenGL* 2.1+ or *OpenGL ES* 1.2+.
131-
OpenGL is preferred, select *OpenGL ES* by starting OpenHantek
132-
from the command line like this: `OpenHantek --useGLES`.
127+
### OpenGL support
128+
OpenHantek6022 uses the *OpenGL* graphics library to display the data. It requires a graphics card that supports
129+
3D rendering and runs on legacy HW/SW that supports at least *OpenGL* 2.1+ or *OpenGL ES* 1.2+.
130+
*OpenGL* is selected by default, but if this does not work (i.e. the black scope window shows an error message
131+
or closes immediately after startup), you can choose the less resource-hungry *OpenGL ES* variant as a fallback
132+
by starting OpenHantek from the command line as follows: `OpenHantek -e` or `OpenHantek --useGLES`.
133+
134+
Especially on Windows, this option may be necessary to use the program.
133135

134136
The Raspberry Pi build uses OpenGL ES automatically, check also the [graphics driver setup](docs/build.md#raspberrypi).
135137

138+
### USB access
136139
USB access for the device is required (unless using demo mode):
137140
* On Linux, you need to copy the file `utils/udev_rules/60-openhantek.rules` to `/etc/udev/rules.d/` or `/usr/lib/udev/rules.d/` and replug your device.
138-
If OpenHantek is installed from a *.deb or *.rpm package this file is installed automatically into `/usr/lib/udev/rules.d/`.
141+
If OpenHantek is installed from a `*.deb` or `*.rpm` package this file is installed automatically into `/usr/lib/udev/rules.d/`.
139142

140143
### Windows USB access
141144
* **The original Hantek driver for Windows doesn't work!**
@@ -179,3 +182,8 @@ We welcome any reported GitHub issue if you have a problem with this software. S
179182

180183
## Other related software
181184
* [HScope for Android](https://www.martinloren.com/hscope/) A one-channel basic version is available free of charge (with in-app purchases).
185+
186+
## History
187+
The program was initially developed by [David Gräff and others](https://github.com/OpenHantek/openhantek/graphs/contributors)
188+
on [github.com/OpenHantek/openhantek](https://github.com/OpenHantek/openhantek),
189+
but David [stopped maintaining](https://github.com/OpenHantek/openhantek/issues/277) the programm in December 2018.

openhantek/src/OH_BUILD.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
// Do not edit, will be re-created at each commit!
2-
#define OH_BUILD "20210424 - commit 893"
2+
#define OH_BUILD "20210426 - commit 894"

openhantek/src/glscope.cpp

+82-70
Original file line numberDiff line numberDiff line change
@@ -24,53 +24,35 @@
2424
#include "viewsettings.h"
2525

2626

27-
GlScope *GlScope::createNormal( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent ) {
28-
GlScope *s = new GlScope( scope, view, parent );
29-
s->zoomed = false;
30-
return s;
31-
}
32-
33-
34-
GlScope *GlScope::createZoomed( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent ) {
35-
GlScope *s = new GlScope( scope, view, parent );
36-
s->zoomed = true;
37-
return s;
38-
}
39-
27+
unsigned GlScope::forceGLSLversion = 0; // static, can be set to 120 or 150 by GlScope::useOpenGLSLversion()
4028

41-
void GlScope::useQSurfaceFormat( QSurfaceFormat::RenderableType t ) {
42-
// QCoreApplication::setAttribute( Qt::AA_ShareOpenGLContexts, true ); // too late here, set early in main()
4329

30+
// this static function will be called early from main to set up OpenGL
31+
void GlScope::useQSurfaceFormat( QSurfaceFormat::RenderableType rendering ) {
32+
QCoreApplication::setAttribute( Qt::AA_ShareOpenGLContexts, true );
4433
// Prefer full desktop OpenGL without fixed pipeline
4534
QSurfaceFormat format;
46-
// from time to time the next line can give a warning
47-
format.setSamples( 4 ); // antialiasing gives warning with some HW, Qt & OpenGL versions.
35+
format.setSamples( 4 ); // ignore antialiasing warning with some HW, Qt & OpenGL versions.
4836
format.setProfile( QSurfaceFormat::CoreProfile );
49-
if ( t == QSurfaceFormat::OpenGLES ) {
50-
// format.setVersion( 2, 0 );
51-
format.setRenderableType( QSurfaceFormat::OpenGLES );
52-
QCoreApplication::setAttribute( Qt::AA_UseOpenGLES, true );
53-
} else {
54-
// format.setVersion( 3, 2 );
55-
format.setRenderableType( QSurfaceFormat::OpenGL );
56-
}
37+
format.setRenderableType( rendering );
38+
QCoreApplication::setAttribute( Qt::AA_UseOpenGLES, rendering == QSurfaceFormat::OpenGLES );
5739
QSurfaceFormat::setDefaultFormat( format );
5840
}
5941

6042

6143
GlScope::GlScope( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent )
6244
: QOpenGLWidget( parent ), scope( scope ), view( view ) {
6345
// get OpenGL version to define appropriate OpenGLSL version
64-
// reason:
65-
// some not so new intel graphic driver report a very conservative version
66-
// e.g. debian buster -> "2.1 Mesa 18.3.4"
46+
// reason: some not so new intel graphic driver report a very conservative version
47+
// even if they deliver OpenGL 4.x functions
48+
// e.g. debian buster -> "2.1 Mesa 18.3.6"
6749
QOffscreenSurface surface;
6850
surface.create();
6951
QOpenGLContext context;
7052
context.create();
7153
context.makeCurrent( &surface );
72-
QString glVersion = reinterpret_cast< const char * >( context.functions()->glGetString( GL_VERSION ) );
73-
GLSLversion = glVersion >= "3.2" ? 150 : 120; // version string "3.2 xxxx" > "3.2" is true
54+
OpenGLversion = reinterpret_cast< const char * >( context.functions()->glGetString( GL_VERSION ) );
55+
GLSLversion = OpenGLversion >= "3.2" ? 150 : 120; // version string "3.2 xxxx" > "3.2" is true
7456
// qDebug() << "OpenGL version" << glVersion << GLSLversion;
7557
surface.destroy();
7658

@@ -91,6 +73,20 @@ GlScope::~GlScope() { /* virtual destructor necessary */
9173
}
9274

9375

76+
GlScope *GlScope::createNormal( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent ) {
77+
GlScope *s = new GlScope( scope, view, parent );
78+
s->zoomed = false;
79+
return s;
80+
}
81+
82+
83+
GlScope *GlScope::createZoomed( DsoSettingsScope *scope, DsoSettingsView *view, QWidget *parent ) {
84+
GlScope *s = new GlScope( scope, view, parent );
85+
s->zoomed = true;
86+
return s;
87+
}
88+
89+
9490
QPointF GlScope::posToPosition( QPointF pos ) {
9591
QPointF position( double( pos.x() - width() / 2 ) * DIVS_TIME / double( width() ),
9692
double( height() / 2 - pos.y() ) * DIVS_VOLTAGE / double( height() ) );
@@ -275,8 +271,6 @@ void GlScope::paintEvent( QPaintEvent *event ) {
275271
}
276272

277273

278-
unsigned GlScope::forceGLSLversion = 0;
279-
280274
void GlScope::initializeGL() {
281275
if ( !QOpenGLShaderProgram::hasOpenGLShaderPrograms( context() ) ) {
282276
errorMessage = tr( "System does not support OpenGL Shading Language (GLSL)" );
@@ -289,7 +283,7 @@ void GlScope::initializeGL() {
289283

290284
auto program = std::unique_ptr< QOpenGLShaderProgram >( new QOpenGLShaderProgram( context() ) );
291285

292-
const char *vshaderES = R"(
286+
const char *vertexShaderGLES = R"(
293287
#version 100
294288
attribute highp vec3 vertex;
295289
uniform mat4 matrix;
@@ -299,13 +293,8 @@ void GlScope::initializeGL() {
299293
gl_PointSize = 1.0;
300294
}
301295
)";
302-
const char *fshaderES = R"(
303-
#version 100
304-
uniform highp vec4 colour;
305-
void main() { gl_FragColor = colour; }
306-
)";
307296

308-
const char *vshaderDesktop120 = R"(
297+
const char *vertexShaderGLSL120 = R"(
309298
#version 120
310299
attribute highp vec3 vertex;
311300
uniform mat4 matrix;
@@ -315,13 +304,8 @@ void GlScope::initializeGL() {
315304
gl_PointSize = 1.0;
316305
}
317306
)";
318-
const char *fshaderDesktop120 = R"(
319-
#version 120
320-
uniform highp vec4 colour;
321-
void main() { gl_FragColor = colour; }
322-
)";
323307

324-
const char *vshaderDesktop150 = R"(
308+
const char *vertexShaderGLSL150 = R"(
325309
#version 150
326310
in highp vec3 vertex;
327311
uniform mat4 matrix;
@@ -331,37 +315,68 @@ void GlScope::initializeGL() {
331315
gl_PointSize = 1.0;
332316
}
333317
)";
334-
const char *fshaderDesktop150 = R"(
318+
319+
const char *fragmentShaderGLES = R"(
320+
#version 100
321+
uniform highp vec4 color;
322+
void main() { gl_FragColor = color; }
323+
)";
324+
325+
const char *fragmentShaderGLSL120 = R"(
326+
#version 120
327+
uniform highp vec4 color;
328+
void main() { gl_FragColor = color; }
329+
)";
330+
331+
const char *fragmentShaderGLSL150 = R"(
335332
#version 150
336-
uniform highp vec4 colour;
333+
uniform highp vec4 color;
337334
out vec4 flatColor;
338-
void main() { flatColor = colour; }
335+
void main() { flatColor = color; }
339336
)";
340337

341338
if ( GlScope::forceGLSLversion )
342339
GLSLversion = GlScope::forceGLSLversion;
343340
// qDebug() << "compile shaders" << GlScope::forceGLSLversion << GLSLversion;
344341

345-
const char *vshaderDesktop = GLSLversion == 120 ? vshaderDesktop120 : vshaderDesktop150;
346-
const char *fshaderDesktop = GLSLversion == 120 ? fshaderDesktop120 : fshaderDesktop150;
347-
348-
// Compile vertex shader
342+
// Compile vertex and fragment shader
343+
QString hint;
349344
bool usesOpenGL = QSurfaceFormat::defaultFormat().renderableType() == QSurfaceFormat::OpenGL;
350-
if ( !program->addShaderFromSourceCode( QOpenGLShader::Vertex, usesOpenGL ? vshaderDesktop : vshaderES ) ||
351-
!program->addShaderFromSourceCode( QOpenGLShader::Fragment, usesOpenGL ? fshaderDesktop : fshaderES ) ) {
352-
errorMessage = tr( "Failed to compile OpenGL shader programs.\n" ) + program->log();
353-
return;
345+
if ( usesOpenGL ) // in case of error offer a possible solution
346+
hint = tr( "Try command line option '--useGLES'\n" );
347+
348+
if ( 150 == GLSLversion ) { // use version 150 if supported by OpenGL version >= 3.2
349+
if ( !program->addShaderFromSourceCode( QOpenGLShader::Vertex, vertexShaderGLSL150 ) ||
350+
!program->addShaderFromSourceCode( QOpenGLShader::Fragment, fragmentShaderGLSL150 ) ) {
351+
qWarning() << "\nOpenGL version" << OpenGLversion;
352+
qWarning() << "To get rid of this error message, try the command line option '--useGLSL120' or '--useGLES'";
353+
GLSLversion = 120; // in case of error try version 120 as fall back
354+
}
355+
}
356+
if ( 120 == GLSLversion ) { // this version is supported by OpenGL version >= 2.1 (very old)
357+
if ( !program->addShaderFromSourceCode( QOpenGLShader::Vertex, vertexShaderGLSL120 ) ||
358+
!program->addShaderFromSourceCode( QOpenGLShader::Fragment, fragmentShaderGLSL120 ) ) {
359+
errorMessage = tr( "Failed to compile OpenGL shader programs.\n" ) + hint + program->log();
360+
return; // in case of error propose the use of OpenGLES (OpenGL for embedded systems) and stop
361+
}
362+
}
363+
if ( !usesOpenGL ) { // use OpenGLES
364+
if ( !program->addShaderFromSourceCode( QOpenGLShader::Vertex, vertexShaderGLES ) ||
365+
!program->addShaderFromSourceCode( QOpenGLShader::Fragment, fragmentShaderGLES ) ) {
366+
errorMessage = tr( "Failed to compile OpenGL shader programs.\n" ) + program->log();
367+
return;
368+
}
354369
}
355370

356371
// Link shader pipeline
357372
if ( !program->link() || !program->bind() ) {
358-
errorMessage = tr( "Failed to link/bind OpenGL shader programs.\n" ) + program->log();
373+
errorMessage = tr( "Failed to link/bind OpenGL shader programs.\n" ) + hint + program->log();
359374
return;
360375
}
361376

362377
vertexLocation = program->attributeLocation( "vertex" );
363378
matrixLocation = program->uniformLocation( "matrix" );
364-
colorLocation = program->uniformLocation( "colour" );
379+
colorLocation = program->uniformLocation( "color" );
365380

366381
if ( vertexLocation == -1 || colorLocation == -1 || matrixLocation == -1 ) {
367382
qWarning() << tr( "Failed to locate shader variable." );
@@ -383,17 +398,15 @@ void GlScope::initializeGL() {
383398
QColor bg = view->colors->background;
384399
gl->glClearColor( GLfloat( bg.redF() ), GLfloat( bg.greenF() ), GLfloat( bg.blueF() ), GLfloat( bg.alphaF() ) );
385400

401+
m_vaoMarker.create();
402+
QOpenGLVertexArrayObject::Binder b( &m_vaoMarker );
403+
m_marker.create();
404+
m_marker.bind();
405+
m_marker.setUsagePattern( QOpenGLBuffer::StaticDraw );
406+
m_marker.allocate( int( vaMarker.size() * sizeof( Vertices ) ) );
407+
program->enableAttributeArray( vertexLocation );
408+
program->setAttributeBuffer( vertexLocation, GL_FLOAT, 0, 3, 0 );
386409

387-
{
388-
m_vaoMarker.create();
389-
QOpenGLVertexArrayObject::Binder b( &m_vaoMarker );
390-
m_marker.create();
391-
m_marker.bind();
392-
m_marker.setUsagePattern( QOpenGLBuffer::StaticDraw );
393-
m_marker.allocate( int( vaMarker.size() * sizeof( Vertices ) ) );
394-
program->enableAttributeArray( vertexLocation );
395-
program->setAttributeBuffer( vertexLocation, GL_FLOAT, 0, 3, 0 );
396-
}
397410
updateCursor();
398411

399412
m_program = std::move( program );
@@ -564,6 +577,7 @@ void GlScope::draw4Cross( std::vector< QVector3D > &va, int section, float x, fl
564577
}
565578
}
566579

580+
567581
// prepare the static grid structure that is shown by 'drawGrid()'
568582
// show a line as long as the trigger level marker is clicked or moved
569583
// index: channel, value: trigger level, pressed: marker is activated
@@ -692,7 +706,6 @@ void GlScope::generateGrid( int index, double value, bool pressed ) {
692706

693707
++item;
694708

695-
696709
{ // prepare (dynamic) trigger level marker line
697710
if ( !m_vaoGrid[ item ].isCreated() )
698711
m_vaoGrid[ item ].create();
@@ -735,7 +748,6 @@ void GlScope::drawGrid() {
735748
gl->glDrawArrays( GL_POINTS, 0, gridDrawCounts[ item ] );
736749
m_vaoGrid[ item ].release();
737750

738-
739751
// Axes and div crosses
740752
++item;
741753
m_vaoGrid[ item ].bind();

openhantek/src/glscope.h

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class GlScope : public QOpenGLWidget {
124124
unsigned currentGraphInHistory = 0;
125125

126126
// OpenGL shader, matrix, var-locations
127+
QString OpenGLversion;
127128
unsigned int GLSLversion = 150;
128129
static unsigned forceGLSLversion;
129130
bool shaderCompileSuccess = false;

openhantek/translations/openhantek_de.ts

+19-5
Original file line numberDiff line numberDiff line change
@@ -663,31 +663,45 @@
663663
<context>
664664
<name>GlScope</name>
665665
<message>
666-
<location filename="../src/glscope.cpp" line="282"/>
666+
<location filename="../src/glscope.cpp" line="276"/>
667667
<source>System does not support OpenGL Shading Language (GLSL)</source>
668668
<translation>System unterstützt nicht OpenGL Shading Language (GLSL)</translation>
669669
</message>
670670
<message>
671-
<location filename="../src/glscope.cpp" line="286"/>
671+
<location filename="../src/glscope.cpp" line="280"/>
672672
<source>OpenGL init called twice!</source>
673673
<translation>OpenGL init wurde doppelt aufgerufen!</translation>
674674
</message>
675675
<message>
676-
<location filename="../src/glscope.cpp" line="352"/>
676+
<source>Try command line option &apos;--useGLSL120&apos; or &apos;--useGLES&apos;
677+
</source>
678+
<translation type="vanished">Probiere Kommandozeilenoption &apos;--useGLSL120&apos; oder &apos;--useGLES&apos;
679+
</translation>
680+
</message>
681+
<message>
682+
<location filename="../src/glscope.cpp" line="346"/>
683+
<source>Try command line option &apos;--useGLES&apos;
684+
</source>
685+
<translation>Probiere Kommandozeilenoption &apos;--useGLES&apos;
686+
</translation>
687+
</message>
688+
<message>
689+
<location filename="../src/glscope.cpp" line="359"/>
690+
<location filename="../src/glscope.cpp" line="366"/>
677691
<source>Failed to compile OpenGL shader programs.
678692
</source>
679693
<translation>Fehler beim Übersetzen der OpenGL Shader-Programme.
680694
</translation>
681695
</message>
682696
<message>
683-
<location filename="../src/glscope.cpp" line="358"/>
697+
<location filename="../src/glscope.cpp" line="373"/>
684698
<source>Failed to link/bind OpenGL shader programs.
685699
</source>
686700
<translation>Fehler beim Linken der OpenGL Shader-Programme.
687701
</translation>
688702
</message>
689703
<message>
690-
<location filename="../src/glscope.cpp" line="367"/>
704+
<location filename="../src/glscope.cpp" line="382"/>
691705
<source>Failed to locate shader variable.</source>
692706
<translation>Kann Shader-Variable nicht lokalisieren.</translation>
693707
</message>

0 commit comments

Comments
 (0)