Skip to content

Commit

Permalink
App: fix systematic black view 3D on macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
HuguesDelorme committed Feb 6, 2024
1 parent 8e3302f commit 32ff31d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 49 deletions.
5 changes: 1 addition & 4 deletions src/app/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ static void initGui(GuiApplication* guiApp)
if (!glVersion.isNull() && glVersion.majorVersion() >= 2) { // Requires at least OpenGL version >= 2.0
setFunctionCreateGraphicsDriver(&QOpenGLWidgetOccView::createCompatibleGraphicsDriver);
IWidgetOccView::setCreator(&QOpenGLWidgetOccView::create);
QOpenGLWidgetOccView::staticInitialization();
}
else {
qWarning() << "Can't use QOpenGLWidget because OpenGL version is too old";
Expand Down Expand Up @@ -613,10 +614,6 @@ int main(int argc, char* argv[])
#endif

// Configure and create Qt application object
#if defined(Q_OS_WIN)
// Never use ANGLE on Windows, since OCCT 3D Viewer does not expect this
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
#endif
QCoreApplication::setOrganizationName("Fougue Ltd");
QCoreApplication::setOrganizationDomain("www.fougue.pro");
QCoreApplication::setApplicationName("Mayo");
Expand Down
63 changes: 40 additions & 23 deletions src/app/widget_occ_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

#include "occt_window.h"

#include <QtCore/QCoreApplication>
#include <QtGui/QResizeEvent>
#if OCC_VERSION_HEX >= 0x070600
# include <Aspect_DisplayConnection.hxx>
# include <Aspect_NeutralWindow.hxx>
#endif

Expand Down Expand Up @@ -45,13 +47,14 @@ IWidgetOccView* IWidgetOccView::create(const Handle_V3d_View& view, QWidget* par
bool QOpenGLWidgetOccView_isCoreProfile();
void QOpenGLWidgetOccView_createOpenGlContext(std::function<void(Aspect_RenderingContext)> fnCallback);
Handle_Graphic3d_GraphicDriver QOpenGLWidgetOccView_createCompatibleGraphicsDriver();
bool QOpenGLWidgetOccView_wrapFrameBuffer(const Handle_Graphic3d_GraphicDriver&);
Graphic3d_Vec2i QOpenGLWidgetOccView_getDefaultframeBufferViewportSize(const Handle_Graphic3d_GraphicDriver&);
bool QOpenGLWidgetOccView_wrapFrameBuffer(const Handle_Graphic3d_CView&);
Graphic3d_Vec2i QOpenGLWidgetOccView_getDefaultframeBufferViewportSize(const Handle_Graphic3d_CView&);


static Handle_Aspect_NeutralWindow createNativeWindow([[maybe_unused]] QWidget* widget)
{
auto window = new Aspect_NeutralWindow;
window->SetVirtual(true);
// On non-Windows systems Aspect_Drawable is aliased to 'unsigned long' so can't init with nullptr
Aspect_Drawable nativeWin = 0;
#ifdef Q_OS_WIN
Expand All @@ -65,6 +68,24 @@ static Handle_Aspect_NeutralWindow createNativeWindow([[maybe_unused]] QWidget*
return window;
}

// Returns QSurfaceFormat object suitable for QOpenGLWidgetOccView
static QSurfaceFormat createQSurfaceFormat()
{
QSurfaceFormat glFormat;
glFormat.setDepthBufferSize(24);
glFormat.setStencilBufferSize(8);
if (QOpenGLWidgetOccView_isCoreProfile())
glFormat.setVersion(4, 5);

glFormat.setProfile(
QOpenGLWidgetOccView_isCoreProfile() ?
QSurfaceFormat::CoreProfile :
QSurfaceFormat::CompatibilityProfile
);

return glFormat;
}

QOpenGLWidgetOccView::QOpenGLWidgetOccView(const Handle_V3d_View& view, QWidget* parent)
: QOpenGLWidget(parent),
IWidgetOccView(view)
Expand All @@ -75,24 +96,7 @@ QOpenGLWidgetOccView::QOpenGLWidgetOccView(const Handle_V3d_View& view, QWidget*
this->setUpdatesEnabled(true);
this->setUpdateBehavior(QOpenGLWidget::NoPartialUpdate);

QSurfaceFormat glFormat;
glFormat.setDepthBufferSize(24);
glFormat.setStencilBufferSize(8);
if (QOpenGLWidgetOccView_isCoreProfile())
glFormat.setVersion(4, 5);

glFormat.setProfile(
QOpenGLWidgetOccView_isCoreProfile() ?
QSurfaceFormat::CoreProfile :
QSurfaceFormat::CompatibilityProfile
);
// Use QtOccFrameBuffer fallback
// To request sRGBColorSpace colorspace to meet OCCT expectations then consider code below:
// #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
// glFormat.setColorSpace(QSurfaceFormat::sRGBColorSpace);
// this->setTextureFormat(GL_SRGB8_ALPHA8);
// #endif
this->setFormat(glFormat);
this->setFormat(createQSurfaceFormat());
}

void QOpenGLWidgetOccView::redraw()
Expand All @@ -110,6 +114,19 @@ Handle_Graphic3d_GraphicDriver QOpenGLWidgetOccView::createCompatibleGraphicsDri
return QOpenGLWidgetOccView_createCompatibleGraphicsDriver();
}

void QOpenGLWidgetOccView::staticInitialization()
{
#if defined(Q_OS_WIN)
// Never use ANGLE on Windows, since OCCT 3D Viewer does not expect this
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
#endif

#ifdef Q_OS_MAC
// Suppress Qt warning "QCocoaGLContext: Falling back to unshared context"
QSurfaceFormat::setDefaultFormat(createQSurfaceFormat());
#endif
}

void QOpenGLWidgetOccView::initializeGL()
{
const QRect wrect = this->rect();
Expand All @@ -129,12 +146,12 @@ void QOpenGLWidgetOccView::paintGL()
if (!this->v3dView()->Window())
return;

const Handle(Graphic3d_GraphicDriver)& driver = this->v3dView()->Viewer()->Driver();
if (!QOpenGLWidgetOccView_wrapFrameBuffer(driver))
const Handle_Graphic3d_CView& cview = this->v3dView()->View();
if (!QOpenGLWidgetOccView_wrapFrameBuffer(cview))
return;

Graphic3d_Vec2i viewSizeOld;
const Graphic3d_Vec2i viewSizeNew = QOpenGLWidgetOccView_getDefaultframeBufferViewportSize(driver);
const Graphic3d_Vec2i viewSizeNew = QOpenGLWidgetOccView_getDefaultframeBufferViewportSize(cview);
auto window = Handle_Aspect_NeutralWindow::DownCast(this->v3dView()->Window());
window->Size(viewSizeOld.x(), viewSizeOld.y());
if (viewSizeNew != viewSizeOld) {
Expand Down
3 changes: 3 additions & 0 deletions src/app/widget_occ_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ namespace Mayo {
// IWidgetOccView does not handle input devices interaction like keyboard and mouse
class IWidgetOccView {
public:
virtual ~IWidgetOccView() = default;

const Handle_V3d_View& v3dView() const { return m_view; }

virtual void redraw() = 0;
Expand Down Expand Up @@ -54,6 +56,7 @@ class QOpenGLWidgetOccView : public QOpenGLWidget, public IWidgetOccView {

static QOpenGLWidgetOccView* create(const Handle_V3d_View& view, QWidget* parent);
static Handle_Graphic3d_GraphicDriver createCompatibleGraphicsDriver();
static void staticInitialization();

protected:
// -- QOpenGLWidget
Expand Down
39 changes: 17 additions & 22 deletions src/app/widget_occ_view_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
# include <Aspect_NeutralWindow.hxx>
# include <OpenGl_Context.hxx>
# include <OpenGl_FrameBuffer.hxx>
# include <OpenGl_View.hxx>
# include <OpenGl_Window.hxx>
#endif

#include <functional>
Expand Down Expand Up @@ -66,11 +68,17 @@ class QtOccFrameBuffer : public OpenGl_FrameBuffer {
}
};

Handle_OpenGl_Context QOpenGLWidgetOccView_getOpenGlContext(const Handle_Graphic3d_CView& view)
{
Handle_OpenGl_View glView = Handle_OpenGl_View::DownCast(view);
return glView->GlWindow()->GetGlContext();
}

} // namespace

bool QOpenGLWidgetOccView_isCoreProfile()
{
return false;
return true;
}

void QOpenGLWidgetOccView_createOpenGlContext(std::function<void(Aspect_RenderingContext)> fnCallback)
Expand All @@ -94,33 +102,20 @@ Handle_Graphic3d_GraphicDriver QOpenGLWidgetOccView_createCompatibleGraphicsDriv
gfxDriver->ChangeOptions().buffersOpaqueAlpha = true;
// Offscreen FBOs should be always used
gfxDriver->ChangeOptions().useSystemBuffer = false;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
Message::SendWarning(
"Warning! Qt 5.10+ is required for sRGB setup.\n"
"Colors in 3D Viewer might look incorrect (Qt " QT_VERSION_STR " is used).\n"
);
gfxDriver->ChangeOptions().sRGBDisable = true;
#endif

return gfxDriver;
}

bool QOpenGLWidgetOccView_wrapFrameBuffer(const Handle_Graphic3d_GraphicDriver& gfxDriver)
bool QOpenGLWidgetOccView_wrapFrameBuffer(const Handle_Graphic3d_CView& view)
{
// Wrap FBO created by QOpenGLWidget
auto driver = Handle_OpenGl_GraphicDriver::DownCast(gfxDriver);
if (!driver)
return false;

const Handle_OpenGl_Context& glCtx = driver->GetSharedContext();
Handle_OpenGl_FrameBuffer defaultFbo = glCtx->DefaultFrameBuffer();
Handle_OpenGl_Context glContext = QOpenGLWidgetOccView_getOpenGlContext(view);
Handle_OpenGl_FrameBuffer defaultFbo = glContext->DefaultFrameBuffer();
if (!defaultFbo) {
//defaultFbo = new OpenGl_FrameBuffer;
defaultFbo = new QtOccFrameBuffer;
glCtx->SetDefaultFrameBuffer(defaultFbo);
glContext->SetDefaultFrameBuffer(defaultFbo);
}

if (!defaultFbo->InitWrapper(glCtx)) {
if (!defaultFbo->InitWrapper(glContext)) {
defaultFbo.Nullify();
Message::SendFail() << "Default FBO wrapper creation failed";
return false;
Expand All @@ -129,10 +124,10 @@ bool QOpenGLWidgetOccView_wrapFrameBuffer(const Handle_Graphic3d_GraphicDriver&
return true;
}

Graphic3d_Vec2i QOpenGLWidgetOccView_getDefaultframeBufferViewportSize(const Handle_Graphic3d_GraphicDriver& gfxDriver)
Graphic3d_Vec2i QOpenGLWidgetOccView_getDefaultframeBufferViewportSize(const Handle_Graphic3d_CView& view)
{
auto driver = Handle_OpenGl_GraphicDriver::DownCast(gfxDriver);
return driver->GetSharedContext()->DefaultFrameBuffer()->GetVPSize();
Handle_OpenGl_Context glContext = QOpenGLWidgetOccView_getOpenGlContext(view);
return glContext->DefaultFrameBuffer()->GetVPSize();
}

#endif // OCC_VERSION_HEX >= 0x070600
Expand Down

0 comments on commit 32ff31d

Please sign in to comment.