Make Window manage GLContext

This commit is contained in:
mrkubax10 2024-02-10 22:35:09 +01:00
parent 7fef75d8c7
commit d097e346b2
11 changed files with 150 additions and 202 deletions

View File

@ -24,17 +24,9 @@ SOFTWARE.
#include "game/renderer/gl/gl_context.hpp"
#include <config.hpp>
#include "game/window/window.hpp"
#if defined(WINDOW_WIN32)
#include "game/renderer/gl/win32_gl_context.hpp"
#if defined(RENDERER_GL)
#include <GL/gl.h>
#endif
#if defined(WINDOW_X11)
#include "game/renderer/gl/x11_gl_context.hpp"
#endif
#include "game/renderer/gl/opengl.hpp"
#include "common/logger.hpp"
using namespace polygun::renderer;
@ -53,28 +45,3 @@ void GLContext::query_extensions() {
m_supported_extensions.insert(reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)));
}
#endif
GLContext* GLContext::create_context(window::Window* window) {
switch(window->get_window_type()) {
case window::WindowType::WINDOW_TYPE_WIN32:
#if defined(WINDOW_WIN32)
return new Win32GLContext(window);
#else
LOG_FATAL("Failed to create GLContext for Win32 window: not compiled in");
break;
#endif
case window::WindowType::WINDOW_TYPE_X11:
#if defined(WINDOW_X11)
// FIXME: Decide if X11GLContext should be legacy depending on used renderer
return new X11GLContext(window, false);
#else
LOG_FATAL("Failed to create GLContext for X11 window: not compiled in");
break;
#endif
case window::WindowType::WINDOW_TYPE_WAYLAND:
case window::WindowType::WINDOW_TYPE_SERENITYOS:
case window::WindowType::WINDOW_TYPE_HAIKU:
return nullptr;
}
return nullptr;
}

View File

@ -29,15 +29,11 @@ SOFTWARE.
#include <set>
#include <config.hpp>
namespace polygun::window {
class Window;
}
namespace polygun::renderer {
class GLContext {
public:
GLContext() = default;
virtual ~GLContext() {}
virtual ~GLContext() = default;
#if defined(RENDERER_GL)
bool is_extension_supported(const std::string& name);
@ -46,8 +42,6 @@ namespace polygun::renderer {
virtual void* get_proc_address(const std::string& name) = 0;
#endif
static GLContext* create_context(window::Window* window);
#if defined(RENDERER_GL)
protected:
std::set<std::string> m_supported_extensions;

View File

@ -37,29 +37,19 @@ SOFTWARE.
using namespace polygun::renderer;
GLMasterRenderer::GLMasterRenderer(window::Window* window) :
MasterRenderer(),
m_context(nullptr),
m_window_manages_gl_context(window->window_manages_gl_context())
MasterRenderer()
{
if(window->window_creates_gl_context())
m_context = window->get_window_gl_context();
else
m_context = GLContext::create_context(window);
GLContext* const context = window->get_window_gl_context();
LOG_INFO("OpenGL version string: %s", glGetString(GL_VERSION));
LOG_INFO("OpenGL vendor: %s", glGetString(GL_VENDOR));
LOG_INFO("OpenGL renderer: %s", glGetString(GL_RENDERER));
LOG_INFO("GLSL version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
m_context->query_extensions();
opengl::init(m_context);
context->query_extensions();
opengl::init(context);
m_mesh_renderer.reset(new GLMeshRenderer);
m_gui_renderer.reset(new GLGUIRenderer(this));
}
GLMasterRenderer::~GLMasterRenderer() {
if(!m_window_manages_gl_context)
delete m_context;
}
void GLMasterRenderer::clear_screen(float r, float g, float b) {
glClearColor(r, g, b, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

View File

@ -28,11 +28,9 @@ SOFTWARE.
#include "game/renderer/master_renderer.hpp"
namespace polygun::renderer {
class GLContext;
class GLMasterRenderer final : public MasterRenderer {
public:
GLMasterRenderer(window::Window* window);
virtual ~GLMasterRenderer() override;
virtual void clear_screen(float r, float g, float b) override;
virtual Shader* create_shader() const override;
@ -40,7 +38,6 @@ namespace polygun::renderer {
virtual Texture* create_texture() const override;
private:
GLContext* m_context;
bool m_window_manages_gl_context;
};
}

View File

@ -24,24 +24,55 @@ SOFTWARE.
#include "game/renderer/gl/x11_gl_context.hpp"
#include "game/window/x11/dynamic_glx.hpp"
#include "game/window/x11/x11_window.hpp"
#include "common/logger.hpp"
#include "game/window/x11/dynamic_glx.hpp"
#include "game/window/x11/dynamic_x11.hpp"
#include "game/window/x11/x11_window.hpp"
using namespace polygun::renderer;
typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
X11GLContext::X11GLContext(window::Window* window, bool legacy) :
m_window(static_cast<window::X11Window*>(window)),
m_legacy(legacy),
X11GLContext::X11GLContext(window::X11Window* window) :
m_window(window),
m_legacy(false),
m_visual_info(nullptr),
m_fb_config(),
m_has_doublebuffer(true),
m_context()
{
initialize(legacy);
window::glx::init();
#if defined(RENDERER_GL)
initialize();
#else
initialize_legacy();
#endif
}
X11GLContext::~X11GLContext() {
window::glx::glXDestroyContext(m_window->get_display(), m_context);
window::x11::XFree(m_visual_info);
}
void X11GLContext::use() {
if(m_legacy) {
m_context = window::glx::glXCreateContext(m_window->get_display(), m_visual_info, None, true);
if(!m_context)
throw std::runtime_error("Failed to create X11GLContext");
}
else {
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = reinterpret_cast<glXCreateContextAttribsARBProc>(window::glx::glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB")));
const int context_attribs[] = {
None
};
m_context = glXCreateContextAttribsARB(m_window->get_display(), m_fb_config, 0, true, context_attribs);
}
window::glx::glXMakeCurrent(m_window->get_display(), m_window->get_window_id(), m_context);
}
void X11GLContext::finish_frame() {
if(m_has_doublebuffer)
window::glx::glXSwapBuffers(m_window->get_display(), m_window->get_window_id());
}
#if defined(RENDERER_GL)
@ -50,27 +81,72 @@ void* X11GLContext::get_proc_address(const std::string& name) {
}
#endif
void X11GLContext::initialize(bool legacy) {
if(legacy) {
m_context = window::glx::glXCreateContext(m_window->get_display(), m_window->get_visual_info(), None, true);
if(!m_context)
LOG_FATAL("Failed to create X11GLContext");
window::glx::glXMakeCurrent(m_window->get_display(), m_window->get_window_id(), m_context);
}
else {
#if defined(RENDERER_GL)
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = reinterpret_cast<glXCreateContextAttribsARBProc>(window::glx::glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB")));
if(!glXCreateContextAttribsARB) {
initialize(true);
void X11GLContext::initialize() {
// check if GLX is supported
int dummy;
if(!window::glx::glXQueryExtension(m_window->get_display(), &dummy, &dummy))
throw std::runtime_error("X display doesn't support GLX");
if(!window::glx::glXGetProcAddressARB) {
initialize_legacy();
return;
}
const int context_attribs[] = {
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = reinterpret_cast<glXCreateContextAttribsARBProc>(window::glx::glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB")));
if(!glXCreateContextAttribsARB) {
initialize_legacy();
return;
}
const int attribs[] = {
GLX_X_RENDERABLE, True,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_DOUBLEBUFFER, True,
None
};
m_context = glXCreateContextAttribsARB(m_window->get_display(), m_window->get_glx_fb_config(), 0, true, context_attribs);
window::glx::glXMakeCurrent(m_window->get_display(), m_window->get_window_id(), m_context);
#else
initialize(true);
int fb_count;
GLXFBConfig* const fb_configs = window::glx::glXChooseFBConfig(m_window->get_display(), m_window->get_screen(), attribs, &fb_count);
if(fb_count==0) {
initialize_legacy();
return;
}
m_fb_config = fb_configs[0];
window::x11::XFree(fb_configs);
m_visual_info = window::glx::glXGetVisualFromFBConfig(m_window->get_display(), m_fb_config);
}
#endif
void X11GLContext::initialize_legacy() {
m_legacy = true;
int doublebuffer[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 12,
GLX_DOUBLEBUFFER,
None
};
int singlebuffer[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_DEPTH_SIZE, 12,
None
};
if(!(m_visual_info = window::glx::glXChooseVisual(m_window->get_display(), m_window->get_screen(), doublebuffer))) {
LOG_WARNING("Doublebuffer is not supported, trying singlebuffer");
if(!(m_visual_info = window::glx::glXChooseVisual(m_window->get_display(), m_window->get_screen(), singlebuffer)))
throw std::runtime_error("Failed to choose GLX visual");
m_has_doublebuffer = false;
}
}

View File

@ -36,9 +36,14 @@ namespace polygun::window {
namespace polygun::renderer {
class X11GLContext final : public GLContext {
public:
X11GLContext(window::Window* window, bool legacy);
X11GLContext(window::X11Window* window);
~X11GLContext() override;
void use();
void finish_frame();
XVisualInfo* get_visual_info() { return m_visual_info; }
#if defined(RENDERER_GL)
virtual void* get_proc_address(const std::string& name) override;
#endif
@ -46,10 +51,16 @@ namespace polygun::renderer {
private:
window::X11Window* m_window;
bool m_legacy;
XVisualInfo* m_visual_info;
GLXFBConfig m_fb_config;
bool m_has_doublebuffer;
GLXContext m_context;
private:
void initialize(bool legacy);
#if defined(RENDERER_GL)
void initialize();
#endif
void initialize_legacy();
};
}

View File

@ -37,14 +37,8 @@ SOFTWARE.
using namespace polygun::renderer;
LegacyGLMasterRenderer::LegacyGLMasterRenderer(window::Window* window) :
MasterRenderer(),
m_context(nullptr),
m_should_delete_gl_context(!window->window_creates_gl_context())
MasterRenderer()
{
if(window->window_creates_gl_context())
m_context = window->get_window_gl_context();
else
m_context = GLContext::create_context(window);
LOG_INFO("OpenGL version string: %s", glGetString(GL_VERSION));
LOG_INFO("OpenGL vendor: %s", glGetString(GL_VENDOR));
LOG_INFO("OpenGL renderer: %s", glGetString(GL_RENDERER));
@ -52,11 +46,6 @@ LegacyGLMasterRenderer::LegacyGLMasterRenderer(window::Window* window) :
m_gui_renderer.reset(new LegacyGLGUIRenderer(this));
}
LegacyGLMasterRenderer::~LegacyGLMasterRenderer() {
if(m_should_delete_gl_context)
delete m_context;
}
void LegacyGLMasterRenderer::clear_screen(float r, float g, float b) {
glClearColor(r, g, b, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

View File

@ -28,11 +28,9 @@ SOFTWARE.
#include "game/renderer/master_renderer.hpp"
namespace polygun::renderer {
class GLContext;
class LegacyGLMasterRenderer final : public MasterRenderer {
public:
LegacyGLMasterRenderer(window::Window* window);
virtual ~LegacyGLMasterRenderer() override;
virtual bool supports_greedy_meshing() const override { return false; }
virtual void clear_screen(float r, float g, float b) override;
@ -41,10 +39,6 @@ namespace polygun::renderer {
virtual Shader* create_shader() const override;
virtual Mesh* create_mesh(MeshUsageHint hint = MeshUsageHint::MESH_USAGE_HINT_STATIC) const override;
virtual Texture* create_texture() const override;
private:
GLContext* m_context;
bool m_should_delete_gl_context;
};
}

View File

@ -70,8 +70,6 @@ namespace polygun::window {
virtual void finish_frame() {}
virtual void grab_mouse(bool grab) = 0;
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
virtual bool window_creates_gl_context() const { return false; }
virtual bool window_manages_gl_context() const { return false; }
virtual renderer::GLContext* get_window_gl_context() { return nullptr; }
#endif

View File

@ -149,14 +149,10 @@ static const std::map<KeySym, polygun::window::KeyCode> g_x11_latin_keysym_to_ke
X11Window::X11Window(const std::string& title, unsigned width, unsigned height, renderer::RendererType renderer_type) :
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
m_glx_has_doublebuffer(true),
#endif
#if defined(RENDERER_GL)
m_glx_fb_config(),
m_gl_context(nullptr),
#endif
m_display(nullptr),
m_screen(0),
m_visual_info(nullptr),
m_window_id(),
m_wm_delete(0),
m_renderer_type(renderer_type),
@ -177,27 +173,38 @@ X11Window::X11Window(const std::string& title, unsigned width, unsigned height,
m_screen = DefaultScreen(m_display);
m_wm_delete = x11::XInternAtom(m_display, "WM_DELETE_WINDOW", false);
XVisualInfo* visual_info;
switch(renderer_type) {
case renderer::RendererType::RENDERER_TYPE_GL:
case renderer::RendererType::RENDERER_TYPE_LEGACY_GL:
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
m_visual_info = setup_glx();
m_gl_context = new renderer::X11GLContext(this);
visual_info = m_gl_context->get_visual_info();
#else
LOG_FATAL("Request to setup GLX while OpenGL renderer is not compiled in");
throw std::runtime_error("Request to setup GLX while OpenGL renderer is not compiled in");
#endif
break;
}
::Window root_window = RootWindow(m_display, m_visual_info->screen);
Colormap colormap = x11::XCreateColormap(m_display, root_window, m_visual_info->visual, AllocNone);
::Window root_window = RootWindow(m_display, visual_info->screen);
Colormap colormap = x11::XCreateColormap(m_display, root_window, visual_info->visual, AllocNone);
XSetWindowAttributes window_attribs;
window_attribs.colormap = colormap;
window_attribs.border_pixel = 0;
window_attribs.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask;
m_window_id = x11::XCreateWindow(m_display, root_window, 0, 0, width, height, 0, m_visual_info->depth, InputOutput, m_visual_info->visual, CWBorderPixel | CWColormap | CWEventMask, &window_attribs);
m_window_id = x11::XCreateWindow(m_display, root_window, 0, 0, width, height, 0, visual_info->depth, InputOutput, visual_info->visual, CWBorderPixel | CWColormap | CWEventMask, &window_attribs);
x11::XSetStandardProperties(m_display, m_window_id, title.c_str(), "polygun", None, nullptr, 0, nullptr);
x11::XSetWMProtocols(m_display, m_window_id, &m_wm_delete, 1);
switch(renderer_type) {
case renderer::RendererType::RENDERER_TYPE_GL:
case renderer::RendererType::RENDERER_TYPE_LEGACY_GL:
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
m_gl_context->use();
#endif
break;
}
// setup input context
x11::XSetLocaleModifiers("");
XIM im = x11::XOpenIM(m_display, nullptr, nullptr, nullptr);
@ -212,8 +219,11 @@ X11Window::X11Window(const std::string& title, unsigned width, unsigned height,
}
X11Window::~X11Window() {
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
if(m_gl_context)
delete m_gl_context;
#endif
x11::XDestroyWindow(m_display, m_window_id);
x11::XFree(m_visual_info);
if(m_display)
x11::XCloseDisplay(m_display);
}
@ -351,8 +361,7 @@ void X11Window::finish_frame() {
case renderer::RendererType::RENDERER_TYPE_GL:
case renderer::RendererType::RENDERER_TYPE_LEGACY_GL:
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
if(m_glx_has_doublebuffer)
glx::glXSwapBuffers(m_display, m_window_id);
m_gl_context->finish_frame();
break;
#endif
}
@ -375,67 +384,3 @@ void X11Window::grab_mouse(bool grab) {
x11::XFreeCursor(m_display, cursor);
m_mouse_grabbed = grab;
}
#if defined(RENDERER_GL)
XVisualInfo* X11Window::setup_glx() {
glx::init();
// check if GLX is supported
int dummy;
if(!glx::glXQueryExtension(m_display, &dummy, &dummy))
LOG_FATAL("X display doesn't support GLX");
const int attribs[] = {
GLX_X_RENDERABLE, True,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_DOUBLEBUFFER, True,
None
};
int fb_count;
GLXFBConfig* const fb_configs = glx::glXChooseFBConfig(m_display, m_screen, attribs, &fb_count);
if(fb_count==0)
return setup_glx_legacy();
m_glx_fb_config = fb_configs[0];
x11::XFree(fb_configs);
return glx::glXGetVisualFromFBConfig(m_display, m_glx_fb_config);
}
#endif
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
XVisualInfo* X11Window::setup_glx_legacy() {
XVisualInfo* visual_info;
int doublebuffer[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 12,
GLX_DOUBLEBUFFER,
None
};
int singlebuffer[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_DEPTH_SIZE, 12,
None
};
if(!(visual_info = glx::glXChooseVisual(m_display, m_screen, doublebuffer))) {
LOG_VERBOSE("Doublebuffer is not supported, trying singlebuffer");
if(!(visual_info = glx::glXChooseVisual(m_display, m_screen, singlebuffer)))
LOG_FATAL("Failed to choose GLX visual");
m_glx_has_doublebuffer = false;
}
return visual_info;
}
#endif

View File

@ -31,7 +31,7 @@ SOFTWARE.
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#if defined(RENDERER_GL)
#include <GL/glx.h>
#include "game/renderer/gl/x11_gl_context.hpp"
#endif
namespace polygun::window {
@ -42,26 +42,21 @@ namespace polygun::window {
Display* get_display() { return m_display; }
int get_screen() const { return m_screen; }
XVisualInfo* get_visual_info() { return m_visual_info; }
::Window get_window_id() const { return m_window_id; }
#if defined(RENDERER_GL)
GLXFBConfig get_glx_fb_config() { return m_glx_fb_config; }
#endif
virtual size_t poll_events(Event& event) override;
virtual void finish_frame() override;
virtual void grab_mouse(bool grab) override;
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
virtual renderer::GLContext* get_window_gl_context() { return m_gl_context; }
#endif
private:
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
bool m_glx_has_doublebuffer;
#endif
#if defined(RENDERER_GL)
GLXFBConfig m_glx_fb_config;
renderer::X11GLContext* m_gl_context;
#endif
Display* m_display;
int m_screen;
XVisualInfo* m_visual_info;
::Window m_window_id;
Atom m_wm_delete;
renderer::RendererType m_renderer_type;
@ -71,14 +66,6 @@ namespace polygun::window {
bool m_was_mouse_grabbed;
bool m_skip_motion_event;
bool m_first_focus_out_event;
private:
#if defined(RENDERER_GL)
XVisualInfo* setup_glx();
#endif
#if defined(RENDERER_GL) || defined(RENDERER_LEGACY_GL)
XVisualInfo* setup_glx_legacy();
#endif
};
}