Skip to content

Commit 7364b37

Browse files
committed
Partially reset GL global state before/after Qt/OCCT to avoid artifacts
Sample code for testing at the end of OcctQOpenGLWidgetViewer::paintGL(): ``` { QPainter p(this); p.setPen(Qt::yellow); QFont font; font.setFamily("Arial"); font.setPixelSize(32); p.setFont(font); p.drawText(QPoint(400, 50), QLatin1String("ABCDEFG")); } ```
1 parent ef4bbe6 commit 7364b37

4 files changed

Lines changed: 74 additions & 3 deletions

File tree

occt-qopenglwidget/OcctQOpenGLWidgetViewer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,16 @@ void OcctQOpenGLWidgetViewer::paintGL()
480480
#endif
481481
}
482482

483+
// reset global GL state from Qt before redrawing OCCT
484+
OcctGlTools::ResetGlStateBeforeOcct(myView);
485+
483486
// flush pending input events and redraw the viewer
484487
Handle(V3d_View) aView = !myFocusView.IsNull() ? myFocusView : myView;
485488
aView->InvalidateImmediate();
486489
AIS_ViewController::FlushViewEvents(myContext, aView, true);
490+
491+
// reset global GL state after OCCT before redrawing Qt
492+
OcctGlTools::ResetGlStateAfterOcct(myView);
487493
}
488494

489495
// ================================================================

occt-qt-tools/OcctGlTools.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "OcctGlTools.h"
44

55
#include <OpenGl_GraphicDriver.hxx>
6+
#include <OpenGl_GlCore20.hxx>
67
#include <OpenGl_FrameBuffer.hxx>
78
#include <OpenGl_View.hxx>
89
#include <OpenGl_Window.hxx>
@@ -15,3 +16,54 @@ Handle(OpenGl_Context) OcctGlTools::GetGlContext(const Handle(V3d_View)& theView
1516
Handle(OpenGl_View) aGlView = Handle(OpenGl_View)::DownCast(theView->View());
1617
return aGlView->GlWindow()->GetGlContext();
1718
}
19+
20+
// ================================================================
21+
// Function : ResetGlStateBeforeOcct
22+
// ================================================================
23+
void OcctGlTools::ResetGlStateBeforeOcct(const Handle(V3d_View)& theView)
24+
{
25+
Handle(OpenGl_Context) aGlCtx = GetGlContext(theView);
26+
if (aGlCtx.IsNull())
27+
return;
28+
29+
if (aGlCtx->core20fwd != nullptr)
30+
{
31+
// shouldn't be a problem in most cases, but make sure to unbind active GLSL program
32+
aGlCtx->core20fwd->glUseProgram(0);
33+
}
34+
35+
// Qt leaves GL_BLEND enabled after drawing semitransparent elements,
36+
// but OCCT doesn't reset its state before drawing opaque objects.
37+
// Disable also texture bindings left by Qt.
38+
aGlCtx->core11fwd->glBindTexture(GL_TEXTURE_2D, 0);
39+
aGlCtx->core11fwd->glDisable(GL_BLEND);
40+
if (aGlCtx->core11ffp != nullptr)
41+
{
42+
aGlCtx->core11fwd->glDisable(GL_ALPHA_TEST);
43+
aGlCtx->core11fwd->glDisable(GL_TEXTURE_2D);
44+
}
45+
}
46+
47+
// ================================================================
48+
// Function : ResetGlStateAfterOcct
49+
// ================================================================
50+
void OcctGlTools::ResetGlStateAfterOcct(const Handle(V3d_View)& theView)
51+
{
52+
Handle(OpenGl_Context) aGlCtx = GetGlContext(theView);
53+
if (aGlCtx.IsNull())
54+
return;
55+
56+
// Qt expects default OpenGL pack/unpack alignment setup,
57+
// while OCCT manages it dynamically;
58+
// without resetting alignment setup, Qt will draw
59+
// some textures corrupted (like fonts)
60+
aGlCtx->core11fwd->glPixelStorei(GL_PACK_ALIGNMENT, 4);
61+
aGlCtx->core11fwd->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
62+
63+
if (aGlCtx->core15fwd != nullptr)
64+
{
65+
// Qt expects first texture object to be bound,
66+
// but OCCT might leave another object bound within multi-texture mapping
67+
aGlCtx->core15fwd->glActiveTexture(GL_TEXTURE0);
68+
}
69+
}

occt-qt-tools/OcctGlTools.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ class OcctGlTools
1313
public:
1414
//! Return GL context.
1515
static Handle(OpenGl_Context) GetGlContext(const Handle(V3d_View)& theView);
16+
17+
//! Cleanup up global GL state after Qt before redrawing OCCT Viewer.
18+
static void ResetGlStateBeforeOcct(const Handle(V3d_View)& theView);
19+
20+
//! Cleanup up global GL state after OCCT before redrawing Qt.
21+
//! Alternative to QQuickOpenGLUtils::resetOpenGLState().
22+
static void ResetGlStateAfterOcct(const Handle(V3d_View)& theView);
1623
};
1724

1825
#endif // _OcctGlTools_HeaderFile

occt-qtquick/OcctQQuickFramebufferViewer.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -561,14 +561,20 @@ void OcctQQuickFramebufferViewer::render(QOpenGLFramebufferObject* theFbo)
561561
dumpGlInfo(true, false);
562562
}
563563

564+
// reset global GL state from Qt before redrawing OCCT
565+
OcctGlTools::ResetGlStateBeforeOcct(myView);
566+
564567
// flush pending input events and redraw the viewer
565568
myView->InvalidateImmediate();
566569
AIS_ViewController::FlushViewEvents(myContext, myView, true);
567570

568-
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
569-
//QQuickOpenGLUtils::resetOpenGLState()
571+
// reset global GL state after OCCT before redrawing Qt
572+
// (alternative to QQuickOpenGLUtils::resetOpenGLState())
573+
OcctGlTools::ResetGlStateAfterOcct(myView);
574+
/*#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
575+
QQuickOpenGLUtils::resetOpenGLState()
570576
#else
571577
if (aQWindow != nullptr)
572578
aQWindow->resetOpenGLState();
573-
#endif
579+
#endif*/
574580
}

0 commit comments

Comments
 (0)