#include #include #include #include "glad_glx.h" #include "Xlib.h" #include "GLXContext.h" namespace sp { 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_win (0), m_ctx (NULL) { } GLXContext::~GLXContext() { destroy(); } bool GLXContext::create(const PlatformDisplay* display) { // Destroy any previous context first. destroy(); m_win = (::Window) display->getHandle(); if (!createGLContext()) { destroy(); return false; } return true; } bool GLXContext::createGLContext() { ::Display* disp = Xlib::getDisplay(); ::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(disp, DefaultScreen(disp))) { return false; } info = ::glXChooseVisual(disp, DefaultScreen(disp), vi_attr); if (info == NULL) { Log::warn("GLX: Could not find a valid VisualInfo."); return false; } // Setup GL settings. fbc = glXChooseFBConfig(disp, DefaultScreen(disp), (const int*) info->visual, &fbcount); if (fbc == NULL) { Log::warn("GLX: Could not find FB Config."); return false; } // Create context. m_ctx = glXCreateContextAttribsARB(disp, fbc[0], NULL, GL_TRUE, ctx_attr); if (m_ctx == NULL) { Log::warn("GLX: Failed to create context."); return false; } glXMakeCurrent(disp, m_win, m_ctx); // Load OpenGL if (!loadGL()) { Log::warn("GLX: Could not load OpenGL"); return false; } return true; } void GLXContext::destroy() { if (m_ctx) { ::glXDestroyContext(Xlib::getDisplay(), m_ctx); m_ctx = NULL; } m_win = None; } bool GLXContext::activate() { if (m_win && m_ctx) { return ::glXMakeCurrent(Xlib::getDisplay(), m_win, m_ctx); } return false; } bool GLXContext::deactivate() { return ::glXMakeCurrent(Xlib::getDisplay(), None, NULL); } bool GLXContext::isActive() const { return ::glXGetCurrentContext() == m_ctx; } bool GLXContext::setSwapInterval(int interval) { ::Display *disp = Xlib::getDisplay(); ensureExtensionsLoaded(disp, DefaultScreen(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) { // TODO: Not GLX specific! move to generic GLContext class. if (activate()) { glViewport(0, 0, width, height); } } void GLXContext::setSize(const Vector2u size) { setSize(size.x, size.y); } void GLXContext::swapBuffers() { glXSwapBuffers(Xlib::getDisplay(), m_win); } } // namespace sp