Skip to content

Commit

Permalink
#5200: Move context setup code to wxutil::GLContext. Remove widget re…
Browse files Browse the repository at this point in the history
…gistration methods from OpenGLModule.
  • Loading branch information
codereader committed Sep 16, 2020
1 parent 564f6c3 commit 6311959
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 152 deletions.
12 changes: 0 additions & 12 deletions include/igl.h
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion include/iwxgl.h
@@ -1,6 +1,6 @@
#pragma once

#include "igl.h"
#include "imodule.h"

namespace wxutil { class GLWidget; }

Expand Down
54 changes: 54 additions & 0 deletions libs/wxutil/GLContext.h
@@ -0,0 +1,54 @@
#pragma once

#include "igl.h"
#include "itextstream.h"
#include <wx/glcanvas.h>

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<const char*>(glGetString(GL_VENDOR)) << std::endl;
rMessage() << "GL_RENDERER: "
<< reinterpret_cast<const char*>(glGetString(GL_RENDERER)) << std::endl;
rMessage() << "GL_VERSION: "
<< reinterpret_cast<const char*>(glGetString(GL_VERSION)) << std::endl;
rMessage() << "GL_EXTENSIONS: "
<< reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)) << std::endl;

GLenum err = glewInit();

if (err != GLEW_OK)
{
// glewInit failed
rError() << "GLEW error: " <<
reinterpret_cast<const char*>(glewGetErrorString(err));
}
}

~GLContext()
{
delete _context;
}

wxGLContext& get()
{
return *_context;
}
};

}
27 changes: 17 additions & 10 deletions libs/wxutil/GLWidget.cpp
Expand Up @@ -2,6 +2,9 @@

#include "igl.h"
#include "itextstream.h"
#include "iwxgl.h"

#include "GLContext.h"

#include <wx/dcclient.h>

Expand All @@ -21,9 +24,9 @@ GLWidget::GLWidget(wxWindow *parent, const std::function<bool()>& 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)
Expand All @@ -40,10 +43,10 @@ void GLWidget::SetHasPrivateContext(bool hasPrivateContext)

void GLWidget::DestroyPrivateContext()
{
if (_privateContext != NULL)
if (_privateContext != nullptr)
{
_privateContext->UnRef();
_privateContext = NULL;
_privateContext = nullptr;
}
}

Expand All @@ -53,7 +56,7 @@ GLWidget::~GLWidget()

if (_registered)
{
GlobalOpenGL().unregisterGLCanvas(this);
GlobalWxGlWidgetManager().unregisterGLWidget(this);
}
}

Expand All @@ -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<GLContext>(context));

auto wxContext = std::static_pointer_cast<GLContext>(context);
SetCurrent(wxContext->get());
}

if (_renderCallback())
Expand Down
2 changes: 1 addition & 1 deletion radiant/map/StartupMapLoader.cpp
Expand Up @@ -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;
Expand Down
106 changes: 26 additions & 80 deletions radiant/render/OpenGLModule.cpp
Expand Up @@ -15,9 +15,6 @@

OpenGLModule::OpenGLModule() :
_unknownError("Unknown error."),
_wxSharedContext(NULL),
_contextValid(false),
_wxContextValid(false),
_shaderProgramsAvailable(false)
{}

Expand Down Expand Up @@ -58,25 +55,6 @@ void OpenGLModule::assertNoErrors()

void OpenGLModule::sharedContextCreated()
{
// report OpenGL information
rMessage() << "GL_VENDOR: "
<< reinterpret_cast<const char*>(glGetString(GL_VENDOR)) << std::endl;
rMessage() << "GL_RENDERER: "
<< reinterpret_cast<const char*>(glGetString(GL_RENDERER)) << std::endl;
rMessage() << "GL_VERSION: "
<< reinterpret_cast<const char*>(glGetString(GL_VERSION)) << std::endl;
rMessage() << "GL_EXTENSIONS: "
<< reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)) << std::endl;

GLenum err = glewInit();

if (err != GLEW_OK)
{
// glewInit failed
rError() << "GLEW error: " <<
reinterpret_cast<const char*>(glewGetErrorString(err));
}

// Initialise the font before firing the extension initialised signal
_font.reset(new wxutil::GLFont(wxutil::GLFont::FONT_SANS, 12));

Expand All @@ -90,11 +68,6 @@ void OpenGLModule::sharedContextDestroyed()
GlobalRenderSystem().unrealise();
}

wxGLContext& OpenGLModule::getwxGLContext()
{
return *_wxSharedContext;
}

bool OpenGLModule::shaderProgramsAvailable() const
{
return _shaderProgramsAvailable;
Expand All @@ -107,53 +80,6 @@ void OpenGLModule::setShaderProgramsAvailable(bool available)
_shaderProgramsAvailable = available;
}

void OpenGLModule::registerGLCanvas(wxutil::GLWidget* widget)
{
std::pair<wxGLWidgets::iterator, bool> 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);
Expand 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
Expand Down
36 changes: 14 additions & 22 deletions radiant/render/OpenGLModule.h
Expand Up @@ -3,6 +3,7 @@
#include "igl.h"
#include <map>
#include <string>
#include <sigc++/connection.h>

#include "wxutil/GLFont.h"
#include "wxutil/GLWidget.h"
Expand All @@ -16,37 +17,28 @@ class OpenGLModule :

wxutil::GLFontPtr _font;

wxGLContext* _wxSharedContext;

typedef std::set<wxutil::GLWidget*> 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();
Expand Down

0 comments on commit 6311959

Please sign in to comment.