Skip to content

Opengl refactor#3367

Draft
Lestropie wants to merge 2 commits into
devfrom
opengl_refactor
Draft

Opengl refactor#3367
Lestropie wants to merge 2 commits into
devfrom
opengl_refactor

Conversation

@Lestropie
Copy link
Copy Markdown
Member

I was trying to deal with issues arising from cpp/gui/opengl/gl_core_3_3.(cpp|h) due to name violations and clang-tidy parsing issues (#3349), and I recalled that these files have an unusual (ambiguous?) origin story and have been the topic of various discussions (though wasn't able to find anything suitable to link). Certainly the topic of mass refactoring has come up, eg. to Vulcan.

I thought I'd test the prospect of something not quite so intrusive, asking Claude about modern best practise for OpenGL in C++. Its primary criticism was that given the (justified) use of Qt, there should be no need to use a bespoke loader: QOpenGLFunctions_3_3_Core should possess all of the required functionality. Moreover, we've historically fought a continuous fight regarding grabbing and ensuring consistency in the relevant context when dealing with multiple GL windows / widgets; this is supposedly intrinsically addressed by use of the Qt loader, since the context is stored per object and therefore embedded into each function call.

Posting here as draft PR because it's far from the top priority right now, but wanted it recorded so can come back to it later. Also so that if any mrview fault is reproduced this branch can be tested. Compiles and runs on both Qt5 and Qt6 for me, but haven't tested GUI extensively.

Lestropie added 2 commits May 19, 2026 15:27
Replace the vendored, auto-generated gl_core_3_3 OpenGL loader with a thin
gl:: compatibility facade backed by Qt's per-context
QOpenGLFunctions_3_3_Core. The gl:: namespace, call syntax, and enumerant
constants are preserved verbatim so existing call sites are unchanged, while
function dispatch now binds to the OpenGL context current on the calling
thread rather than a single process-global table. Qt5 and Qt6 are both
supported, with the version-specific function acquisition isolated to a
single helper. The Shader wrapper classes gain the same context-checking
member as the other GL resource wrappers, and a debug trap asserts that GL
calls occur with a current context. The obsolete loader files are removed
entirely.

Session prompts:
1. > Investigate the interface between MRtrix3 and OpenGL for the GUI commands mrview and shview. Cross-reference with accepted modern best practise for compilation of OpenGL 3.3+ programs in C++, such as window management, input device interfacing, and extension loaders. Summarise (without yet generating a comprehensive plan) the most suitable third-party libraries or code refactoring strategies to bring the MRtrix3 implementation up-to-date.
2. > Is it necessary to drop Qt5 support to move to QOpenGLFunctions_3_3_Core? Or is the rationale for dropping Qt5 support as part of refactoring merely opportunistic if refactoring is taking place?
3. > Elaborate on how replacing "gl_core_3_3" with "QOpenGLFunctions_3_3_Core" "makes function dispatch context-cprrect". Would this entirely obviate the use of GL::assert_context_is_current()?
4. > Draft a comprehensive plan for refactoring. Tabulate the mapping from existing functions and classes that are MRtrix-specific or from gl_core_3_3.* to QOpenGLFunctions_3_3_Core. Preserve Qt5 & Qt6 compatibility. Ensure that files cpp/gui/opengl/gl_core_3_3.* can be removed entirely. Preserve MRtrix assertions on context even if redundant. Audit usage of Context::Grab and makeCurrent() and ensure that it is included in all appropriate locations.

Generated-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

Comment thread cpp/gui/opengl/gl.h
assert(context != nullptr && //
"OpenGL call issued with no current context: missing "
"MR::GUI::GL::Context::Grab or QOpenGLWidget::makeCurrent()");
thread_local QOpenGLContext *cached_context = nullptr;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'cached_context' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables]

  thread_local QOpenGLContext *cached_context = nullptr;
                               ^

Comment thread cpp/gui/opengl/gl.h
"OpenGL call issued with no current context: missing "
"MR::GUI::GL::Context::Grab or QOpenGLWidget::makeCurrent()");
thread_local QOpenGLContext *cached_context = nullptr;
thread_local QOpenGLFunctions_3_3_Core *cached_functions = nullptr;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'cached_functions' provides global access to a non-const object; consider making the pointed-to data 'const' [cppcoreguidelines-avoid-non-const-global-variables]

  thread_local QOpenGLFunctions_3_3_Core *cached_functions = nullptr;
                                          ^

Comment thread cpp/gui/opengl/gl.h
// QOpenGLFunctions_3_3_Core, so &QOpenGLFunctions_3_3_Core::gl<Name> is
// unambiguous. To add a function, append a single MRTRIX_GL_FN(<Name>) line;
// if Qt ever overloads one of these the build fails loudly here.
#define MRTRIX_GL_FN(name) \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function-like macro 'MRTRIX_GL_FN' used; consider a 'constexpr' template function [cppcoreguidelines-macro-usage]

#define MRTRIX_GL_FN(name)                                                                                             \
        ^

Comment thread cpp/gui/opengl/gl.h
// unambiguous. To add a function, append a single MRTRIX_GL_FN(<Name>) line;
// if Qt ever overloads one of these the build fails loudly here.
#define MRTRIX_GL_FN(name) \
constexpr auto name = &::MR::GUI::GL::detail::Forward<decltype(&QOpenGLFunctions_3_3_Core::gl##name), \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]

Suggested change
constexpr auto name = &::MR::GUI::GL::detail::Forward<decltype(&QOpenGLFunctions_3_3_Core::gl##name), \
constexpr auto (name) = &::MR::GUI::GL::detail::Forward<decltype(&QOpenGLFunctions_3_3_Core::gl##name), \

Comment thread cpp/gui/opengl/shader.h

protected:
GLuint index_;
Context::Checker check_context;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'check_context' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  Context::Checker check_context;
                   ^

Comment thread cpp/gui/opengl/shader.h

protected:
GLuint index_;
Context::Checker check_context;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable 'check_context' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

  Context::Checker check_context;
                   ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant