1
0
Fork 0

source/Platform/Unix/GLXContext: Initial implementation

This commit is contained in:
Henrik Hautakoski 2019-12-24 21:32:38 +01:00
parent b65cb9c2d2
commit 7dedabba57
2 changed files with 181 additions and 9 deletions

View file

@ -1,51 +1,211 @@
#include <stdio.h>
#include <Platform/PlatformDisplay.h>
#include <Spectre/System/Log.h>
#include "glad_glx.h"
#include "X11SharedDisplay.h"
#include "GLXContext.h" #include "GLXContext.h"
namespace sp { namespace sp {
GLXContext::GLXContext() static bool loadGL() {
{
static bool init = false;
if (!init) {
int ver;
init = true;
ver = gladLoaderLoadGL();
if (!ver) {
return false;
}
Log::info("GLX: Opengl Version %d.%d loaded.",
GLAD_VERSION_MAJOR(ver), GLAD_VERSION_MINOR(ver));
}
return true;
}
// Ensure that OpenGL extensions are loaded.
static bool ensureExtensionsLoaded(::Display* disp, int screen)
{
char msg[1024];
static bool init = false;
if (!init) {
int ver;
init = true;
ver = gladLoaderLoadGLX(disp, screen);
if (!ver) {
Log::warn("GLX: Could not load GLX extensions");
return false;
}
snprintf(msg, 1024, "GLX: GLX Version %d.%d loaded",
GLAD_VERSION_MAJOR(ver), GLAD_VERSION_MINOR(ver));
// Check for atleast version 1.4
if (ver < 10004) {
Log::error("%s but atleast version 1.4 is needed.", msg);
return false;
}
Log::info("%s.", msg);
}
return true;
}
GLXContext::GLXContext() :
m_disp (NULL),
m_win (0),
m_ctx (NULL)
{
} }
GLXContext::~GLXContext() GLXContext::~GLXContext()
{ {
destroy();
} }
bool GLXContext::create(const PlatformDisplay* display) bool GLXContext::create(const PlatformDisplay* display)
{ {
// Destroy any previous context first.
destroy();
m_disp = XGetDisplay();
if (m_disp == NULL) {
destroy();
Log::warn("X11: Could not open display");
return false;
}
m_win = (::Window) display->getHandle();
if (!createGLContext()) {
destroy();
return false;
}
return true;
}
bool GLXContext::createGLContext()
{
::GLXFBConfig *fbc;
::XVisualInfo *info;
int fbcount;
GLint vi_attr[] = {
GLX_RGBA,
GLX_DEPTH_SIZE, 24,
GLX_DOUBLEBUFFER, 1,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
None
};
GLint ctx_attr[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 2,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
None
};
// Ensure glx extensions are loaded.
if (!ensureExtensionsLoaded(m_disp, DefaultScreen(m_disp))) {
return false;
}
info = ::glXChooseVisual(m_disp, DefaultScreen(m_disp), vi_attr);
if (info == NULL) {
Log::warn("GLX: Could not find a valid VisualInfo.");
return false;
}
// Setup GL settings.
fbc = glXChooseFBConfig(m_disp, DefaultScreen(m_disp), (const int*) info->visual, &fbcount);
if (fbc == NULL) {
Log::warn("GLX: Could not find FB Config.");
return false;
}
// Create context.
m_ctx = glXCreateContextAttribsARB(m_disp, fbc[0], NULL, GL_TRUE, ctx_attr);
if (m_ctx == NULL) {
Log::warn("GLX: Failed to create context.");
return false;
}
glXMakeCurrent(m_disp, m_win, m_ctx);
// Load OpenGL
if (!loadGL()) {
Log::warn("GLX: Could not load OpenGL");
return false;
}
return true; return true;
} }
void GLXContext::destroy() void GLXContext::destroy()
{ {
if (m_ctx) {
::glXDestroyContext(m_disp, m_ctx);
m_ctx = NULL;
}
if (m_disp) {
XReleaseDisplay();
m_disp = NULL;
}
m_win = None;
} }
bool GLXContext::activate() bool GLXContext::activate()
{ {
return true; if (m_win && m_ctx) {
return ::glXMakeCurrent(m_disp, m_win, m_ctx);
}
return false;
} }
bool GLXContext::deactivate() bool GLXContext::deactivate()
{ {
return true; return ::glXMakeCurrent(m_disp, None, NULL);
} }
bool GLXContext::isActive() const bool GLXContext::isActive() const
{ {
return true; return ::glXGetCurrentContext() == m_ctx;
} }
bool GLXContext::setSwapInterval(int interval) bool GLXContext::setSwapInterval(int interval)
{ {
return true; ensureExtensionsLoaded(m_disp, DefaultScreen(m_disp));
if (GLAD_GLX_MESA_swap_control) {
return glXSwapIntervalMESA(interval);
}
if (GLAD_GLX_SGI_swap_control) {
return glXSwapIntervalSGI(interval);
}
return false;
} }
void GLXContext::setSize(unsigned int width, unsigned int height) void GLXContext::setSize(unsigned int width, unsigned int height)
{ {
// TODO: Not GLX specific! move to generic GLContext class.
if (activate()) {
glViewport(0, 0, width, height);
}
} }
void GLXContext::setSize(const Vector2u size) void GLXContext::setSize(const Vector2u size)
@ -55,7 +215,7 @@ void GLXContext::setSize(const Vector2u size)
void GLXContext::swapBuffers() void GLXContext::swapBuffers()
{ {
glXSwapBuffers(m_disp, m_win);
} }
} // namespace sp } // namespace sp

View file

@ -4,6 +4,7 @@
// X11 OpenGL Context (glx) // X11 OpenGL Context (glx)
#include "glad_glx.h"
#include <Spectre/Display/GLContext.h> #include <Spectre/Display/GLContext.h>
namespace sp { namespace sp {
@ -32,6 +33,17 @@ public :
void setSize(const Vector2u size); void setSize(const Vector2u size);
void swapBuffers(); void swapBuffers();
private :
bool createGLContext();
private :
::Display* m_disp;
::Window m_win;
::GLXContext m_ctx;
}; };
} // namespace sp } // namespace sp