diff --git a/include/igl.h b/include/igl.h index f69f66bb95..0db1e4816f 100644 --- a/include/igl.h +++ b/include/igl.h @@ -88,18 +88,6 @@ class OpenGLBinding : // Normally, you want to use the debug::assertNoGlErrors() wrapper which does nothing in release builds virtual void assertNoErrors() = 0; - /// Returns the shared context widget holding the GL context - virtual wxGLContext& getwxGLContext() = 0; - - /// Registers a GL widget, storing the shared context if necessary - virtual void registerGLCanvas(wxutil::GLWidget* widget) = 0; - - /// Notifies the GL module that a GLWidget has been destroyed - virtual void unregisterGLCanvas(wxutil::GLWidget* widget) = 0; - - /// \brief Is true if the global shared OpenGL context is valid. - virtual bool wxContextValid() const = 0; - // Returns true if openGL supports ARB or GLSL lighting virtual bool shaderProgramsAvailable() const = 0; diff --git a/include/iwxgl.h b/include/iwxgl.h index 416ce18e6b..fc41d85b6b 100644 --- a/include/iwxgl.h +++ b/include/iwxgl.h @@ -1,6 +1,6 @@ #pragma once -#include "igl.h" +#include "imodule.h" namespace wxutil { class GLWidget; } diff --git a/libs/wxutil/GLContext.h b/libs/wxutil/GLContext.h new file mode 100644 index 0000000000..22a7d8eddf --- /dev/null +++ b/libs/wxutil/GLContext.h @@ -0,0 +1,54 @@ +#pragma once + +#include "igl.h" +#include "itextstream.h" +#include + +namespace wxutil +{ + +// IGLContext implementation based on wxGLContext +class GLContext : + public gl::IGLContext +{ +private: + wxGLContext* _context; + +public: + GLContext(wxutil::GLWidget* hostWidget) : + _context(new wxGLContext(hostWidget)) + { + hostWidget->SetCurrent(*_context); + + // report OpenGL information + rMessage() << "GL_VENDOR: " + << reinterpret_cast(glGetString(GL_VENDOR)) << std::endl; + rMessage() << "GL_RENDERER: " + << reinterpret_cast(glGetString(GL_RENDERER)) << std::endl; + rMessage() << "GL_VERSION: " + << reinterpret_cast(glGetString(GL_VERSION)) << std::endl; + rMessage() << "GL_EXTENSIONS: " + << reinterpret_cast(glGetString(GL_EXTENSIONS)) << std::endl; + + GLenum err = glewInit(); + + if (err != GLEW_OK) + { + // glewInit failed + rError() << "GLEW error: " << + reinterpret_cast(glewGetErrorString(err)); + } + } + + ~GLContext() + { + delete _context; + } + + wxGLContext& get() + { + return *_context; + } +}; + +} diff --git a/libs/wxutil/GLWidget.cpp b/libs/wxutil/GLWidget.cpp index 40a098a485..1e0f14fff0 100644 --- a/libs/wxutil/GLWidget.cpp +++ b/libs/wxutil/GLWidget.cpp @@ -2,6 +2,9 @@ #include "igl.h" #include "itextstream.h" +#include "iwxgl.h" + +#include "GLContext.h" #include @@ -21,9 +24,9 @@ GLWidget::GLWidget(wxWindow *parent, const std::function& renderCallback wxString(name.c_str(), *wxConvCurrent)), _registered(false), _renderCallback(renderCallback), - _privateContext(NULL) + _privateContext(nullptr) { - Connect(wxEVT_PAINT, wxPaintEventHandler(GLWidget::OnPaint), NULL, this); + Bind(wxEVT_PAINT, &GLWidget::OnPaint, this); } void GLWidget::SetHasPrivateContext(bool hasPrivateContext) @@ -40,10 +43,10 @@ void GLWidget::SetHasPrivateContext(bool hasPrivateContext) void GLWidget::DestroyPrivateContext() { - if (_privateContext != NULL) + if (_privateContext != nullptr) { _privateContext->UnRef(); - _privateContext = NULL; + _privateContext = nullptr; } } @@ -53,7 +56,7 @@ GLWidget::~GLWidget() if (_registered) { - GlobalOpenGL().unregisterGLCanvas(this); + GlobalWxGlWidgetManager().unregisterGLWidget(this); } } @@ -70,22 +73,26 @@ void GLWidget::OnPaint(wxPaintEvent& WXUNUSED(event)) { _registered = true; - GlobalOpenGL().registerGLCanvas(this); + GlobalWxGlWidgetManager().registerGLWidget(this); } // This is required even though dc is not used otherwise. wxPaintDC dc(this); - // Grab the contex for this widget - if (_privateContext != NULL) + // Grab the context for this widget + if (_privateContext != nullptr) { // Use the private context for this widget SetCurrent(*_privateContext); } else { - // Use the globally shared context - SetCurrent(GlobalOpenGL().getwxGLContext()); + // Use the globally shared context, we rely on this being of type GLContext + const auto& context = GlobalOpenGLContext().getSharedContext(); + assert(std::dynamic_pointer_cast(context)); + + auto wxContext = std::static_pointer_cast(context); + SetCurrent(wxContext->get()); } if (_renderCallback()) diff --git a/radiant/map/StartupMapLoader.cpp b/radiant/map/StartupMapLoader.cpp index ea19f48625..9a0be045b6 100644 --- a/radiant/map/StartupMapLoader.cpp +++ b/radiant/map/StartupMapLoader.cpp @@ -75,7 +75,7 @@ void StartupMapLoader::onMainFrameReady() void StartupMapLoader::loadMapSafe(const std::string& mapToLoad) { // Check if we have a valid openGL context, otherwise postpone the load - if (GlobalOpenGL().wxContextValid()) + if (GlobalOpenGLContext().getSharedContext()) { GlobalCommandSystem().executeCommand("OpenMap", mapToLoad); return; diff --git a/radiant/render/OpenGLModule.cpp b/radiant/render/OpenGLModule.cpp index 02a2bbd7df..75a1372cea 100644 --- a/radiant/render/OpenGLModule.cpp +++ b/radiant/render/OpenGLModule.cpp @@ -15,9 +15,6 @@ OpenGLModule::OpenGLModule() : _unknownError("Unknown error."), - _wxSharedContext(NULL), - _contextValid(false), - _wxContextValid(false), _shaderProgramsAvailable(false) {} @@ -58,25 +55,6 @@ void OpenGLModule::assertNoErrors() void OpenGLModule::sharedContextCreated() { - // report OpenGL information - rMessage() << "GL_VENDOR: " - << reinterpret_cast(glGetString(GL_VENDOR)) << std::endl; - rMessage() << "GL_RENDERER: " - << reinterpret_cast(glGetString(GL_RENDERER)) << std::endl; - rMessage() << "GL_VERSION: " - << reinterpret_cast(glGetString(GL_VERSION)) << std::endl; - rMessage() << "GL_EXTENSIONS: " - << reinterpret_cast(glGetString(GL_EXTENSIONS)) << std::endl; - - GLenum err = glewInit(); - - if (err != GLEW_OK) - { - // glewInit failed - rError() << "GLEW error: " << - reinterpret_cast(glewGetErrorString(err)); - } - // Initialise the font before firing the extension initialised signal _font.reset(new wxutil::GLFont(wxutil::GLFont::FONT_SANS, 12)); @@ -90,11 +68,6 @@ void OpenGLModule::sharedContextDestroyed() GlobalRenderSystem().unrealise(); } -wxGLContext& OpenGLModule::getwxGLContext() -{ - return *_wxSharedContext; -} - bool OpenGLModule::shaderProgramsAvailable() const { return _shaderProgramsAvailable; @@ -107,53 +80,6 @@ void OpenGLModule::setShaderProgramsAvailable(bool available) _shaderProgramsAvailable = available; } -void OpenGLModule::registerGLCanvas(wxutil::GLWidget* widget) -{ - std::pair result = _wxGLWidgets.insert(widget); - - if (result.second && _wxGLWidgets.size() == 1) - { - // First non-duplicated widget registered, take this as context holder - _wxSharedContext = new wxGLContext(widget); - - // Create a context - widget->SetCurrent(*_wxSharedContext); - assertNoErrors(); - - _wxContextValid = true; - - sharedContextCreated(); - } -} - -void OpenGLModule::unregisterGLCanvas(wxutil::GLWidget* widget) -{ - wxGLWidgets::iterator found = _wxGLWidgets.find(widget); - - assert(found != _wxGLWidgets.end()); - - if (found != _wxGLWidgets.end()) - { - if (_wxGLWidgets.size() == 1) - { - // This is the last active GL widget - _wxContextValid = false; - - sharedContextDestroyed(); - - delete _wxSharedContext; - _wxSharedContext = NULL; - } - - _wxGLWidgets.erase(found); - } -} - -bool OpenGLModule::wxContextValid() const -{ - return _wxContextValid; -} - void OpenGLModule::drawString(const std::string& string) const { ftglRenderFont(_font->getFtglFont(),string.c_str(),0xFFFF);//FTGL_RENDER_ALL); @@ -170,19 +96,39 @@ int OpenGLModule::getFontHeight() return _font->getPixelHeight(); } -// RegisterableModule implementation -const std::string& OpenGLModule::getName() const { +const std::string& OpenGLModule::getName() const +{ static std::string _name(MODULE_OPENGL); return _name; } -const StringSet& OpenGLModule::getDependencies() const { - static StringSet _dependencies; // no dependencies +const StringSet& OpenGLModule::getDependencies() const +{ + static StringSet _dependencies; + + if (_dependencies.empty()) + { + _dependencies.insert(MODULE_SHARED_GL_CONTEXT); + } + return _dependencies; } -void OpenGLModule::initialiseModule(const IApplicationContext& ctx) { - rMessage() << "OpenGL::initialiseModule called.\n"; +void OpenGLModule::initialiseModule(const IApplicationContext& ctx) +{ + rMessage() << getName() << "::initialiseModule called." << std::endl; + + _contextCreated = GlobalOpenGLContext().signal_sharedContextCreated().connect( + sigc::mem_fun(this, &OpenGLModule::sharedContextCreated)); + + _contextDestroyed = GlobalOpenGLContext().signal_sharedContextDestroyed().connect( + sigc::mem_fun(this, &OpenGLModule::sharedContextDestroyed)); +} + +void OpenGLModule::shutdownModule() +{ + _contextCreated.disconnect(); + _contextDestroyed.disconnect(); } // Define the static OpenGLModule module diff --git a/radiant/render/OpenGLModule.h b/radiant/render/OpenGLModule.h index cfaeb14e5a..c5f26f7a24 100644 --- a/radiant/render/OpenGLModule.h +++ b/radiant/render/OpenGLModule.h @@ -3,6 +3,7 @@ #include "igl.h" #include #include +#include #include "wxutil/GLFont.h" #include "wxutil/GLWidget.h" @@ -16,37 +17,28 @@ class OpenGLModule : wxutil::GLFontPtr _font; - wxGLContext* _wxSharedContext; - - typedef std::set wxGLWidgets; - wxGLWidgets _wxGLWidgets; - - bool _contextValid; - bool _wxContextValid; - bool _shaderProgramsAvailable; + sigc::connection _contextCreated; + sigc::connection _contextDestroyed; + public: OpenGLModule(); - virtual void assertNoErrors() override; - - virtual void drawString(const std::string& string) const override; - virtual void drawChar(char character) const override; - virtual int getFontHeight() override; + void assertNoErrors() override; - virtual wxGLContext& getwxGLContext() override; - virtual void registerGLCanvas(wxutil::GLWidget* widget) override; - virtual void unregisterGLCanvas(wxutil::GLWidget* widget) override; - virtual bool wxContextValid() const override; + void drawString(const std::string& string) const override; + void drawChar(char character) const override; + int getFontHeight() override; - virtual bool shaderProgramsAvailable() const override; - virtual void setShaderProgramsAvailable(bool available) override; + bool shaderProgramsAvailable() const override; + void setShaderProgramsAvailable(bool available) override; // RegisterableModule implementation - virtual const std::string& getName() const override; - virtual const StringSet& getDependencies() const override; - virtual void initialiseModule(const IApplicationContext& ctx) override; + const std::string& getName() const override; + const StringSet& getDependencies() const override; + void initialiseModule(const IApplicationContext& ctx) override; + void shutdownModule() override; private: void sharedContextCreated(); diff --git a/radiant/ui/gl/WxGLWidgetManager.cpp b/radiant/ui/gl/WxGLWidgetManager.cpp index b330bda48b..58e6645cd2 100644 --- a/radiant/ui/gl/WxGLWidgetManager.cpp +++ b/radiant/ui/gl/WxGLWidgetManager.cpp @@ -1,7 +1,11 @@ #include "WxGLWidgetManager.h" +#include "igl.h" #include "module/StaticModule.h" +#include "wxutil/GLWidget.h" +#include "wxutil/GLContext.h" + namespace ui { @@ -11,19 +15,9 @@ void WxGLWidgetManager::registerGLWidget(wxutil::GLWidget* widget) if (result.second && _wxGLWidgets.size() == 1) { - // TODO -#if 0 - // First non-duplicated widget registered, take this as context holder - _wxSharedContext = new wxGLContext(widget); - - // Create a context - widget->SetCurrent(*_wxSharedContext); - assertNoErrors(); - - _wxContextValid = true; + auto context = std::make_shared(widget); - sharedContextCreated(); -#endif + GlobalOpenGLContext().setSharedContext(context); } } @@ -35,15 +29,7 @@ void WxGLWidgetManager::unregisterGLWidget(wxutil::GLWidget* widget) if (_wxGLWidgets.empty()) { -#if 0 - // This is the last active GL widget - _wxContextValid = false; - - sharedContextDestroyed(); - - delete _wxSharedContext; - _wxSharedContext = NULL; -#endif + GlobalOpenGLContext().setSharedContext(gl::IGLContext::Ptr()); } } diff --git a/radiantcore/rendersystem/OpenGLRenderSystem.cpp b/radiantcore/rendersystem/OpenGLRenderSystem.cpp index 26d0909bfe..78a5cebfba 100644 --- a/radiantcore/rendersystem/OpenGLRenderSystem.cpp +++ b/radiantcore/rendersystem/OpenGLRenderSystem.cpp @@ -62,8 +62,8 @@ OpenGLRenderSystem::OpenGLRenderSystem() : // If the openGL module is already initialised and a shared context is created // trigger a call to extensionsInitialised(). - if (module::GlobalModuleRegistry().moduleExists(MODULE_OPENGL) && - GlobalOpenGL().wxContextValid()) + if (GlobalRadiantCore().getModuleRegistry().moduleExists(MODULE_SHARED_GL_CONTEXT) && + GlobalOpenGLContext().getSharedContext()) { extensionsInitialised(); } @@ -251,9 +251,9 @@ void OpenGLRenderSystem::unrealise() sp->unrealise(); } - if (GlobalOpenGL().wxContextValid() - && GlobalOpenGL().shaderProgramsAvailable() - && getCurrentShaderProgram() != SHADER_PROGRAM_NONE) + if (GlobalOpenGLContext().getSharedContext() && + GlobalOpenGL().shaderProgramsAvailable() && + getCurrentShaderProgram() != SHADER_PROGRAM_NONE) { // Unrealise the GLPrograms _glProgramFactory->unrealise(); diff --git a/tools/msvc/wxutillib.vcxproj b/tools/msvc/wxutillib.vcxproj index 6bbe84f58c..2f81ad56ba 100644 --- a/tools/msvc/wxutillib.vcxproj +++ b/tools/msvc/wxutillib.vcxproj @@ -152,6 +152,7 @@ + diff --git a/tools/msvc/wxutillib.vcxproj.filters b/tools/msvc/wxutillib.vcxproj.filters index 1a8e61ba74..f39fa072a7 100644 --- a/tools/msvc/wxutillib.vcxproj.filters +++ b/tools/msvc/wxutillib.vcxproj.filters @@ -104,6 +104,7 @@ +