summaryrefslogtreecommitdiff
path: root/Source/Core/Common/GL/GLInterface/GLX.cpp
diff options
context:
space:
mode:
authorAnthony <Helios747@users.noreply.github.com>2017-07-30 00:42:36 -0700
committerGitHub <noreply@github.com>2017-07-30 00:42:36 -0700
commit5bad2ee4a4129e734ff4f4d861cedc4cd573df55 (patch)
treecd3c3ccc6e35417858499449d774670c3983cb13 /Source/Core/Common/GL/GLInterface/GLX.cpp
parent5e6d5493165d1214f513b91eaeb4e162d21fdd3e (diff)
parent357c55442f3dbdf6f23d16af5362d1a615cb84c1 (diff)
Merge pull request #5832 from stenzek/ubershader-prereq
Ubershader prerequisites
Diffstat (limited to 'Source/Core/Common/GL/GLInterface/GLX.cpp')
-rw-r--r--Source/Core/Common/GL/GLInterface/GLX.cpp174
1 files changed, 133 insertions, 41 deletions
diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp
index f6fea067ef..e6a018e1d3 100644
--- a/Source/Core/Common/GL/GLInterface/GLX.cpp
+++ b/Source/Core/Common/GL/GLInterface/GLX.cpp
@@ -2,7 +2,8 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include <string>
+#include <array>
+#include <sstream>
#include "Common/GL/GLInterface/GLX.h"
#include "Common/Logging/Log.h"
@@ -17,6 +18,9 @@ typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int interval);
static PFNGLXCREATECONTEXTATTRIBSPROC glXCreateContextAttribs = nullptr;
static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
+static PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX = nullptr;
+static PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX = nullptr;
+
static bool s_glxError;
static int ctxErrorHandler(Display* dpy, XErrorEvent* ev)
{
@@ -26,7 +30,7 @@ static int ctxErrorHandler(Display* dpy, XErrorEvent* ev)
void cInterfaceGLX::SwapInterval(int Interval)
{
- if (glXSwapIntervalSGI)
+ if (glXSwapIntervalSGI && m_has_handle)
glXSwapIntervalSGI(Interval);
else
ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate).");
@@ -45,6 +49,9 @@ void cInterfaceGLX::Swap()
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core)
{
+ m_has_handle = !!window_handle;
+ m_host_window = (Window)window_handle;
+
dpy = XOpenDisplay(nullptr);
int screen = DefaultScreen(dpy);
@@ -100,51 +107,43 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core)
fbconfig = *fbc;
XFree(fbc);
- // Get an appropriate visual
- XVisualInfo* vi = glXGetVisualFromFBConfig(dpy, fbconfig);
-
s_glxError = false;
XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler);
// Create a GLX context.
// We try to get a 4.0 core profile, else we try 3.3, else try it with anything we get.
- int context_attribs[] = {GLX_CONTEXT_MAJOR_VERSION_ARB,
- 4,
- GLX_CONTEXT_MINOR_VERSION_ARB,
- 0,
- GLX_CONTEXT_PROFILE_MASK_ARB,
- GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
- GLX_CONTEXT_FLAGS_ARB,
- GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
- None};
+ std::array<int, 9> context_attribs = {
+ {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 0,
+ GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB,
+ GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}};
ctx = nullptr;
if (core)
{
- ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs);
+ ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs[0]);
XSync(dpy, False);
+ m_attribs.insert(m_attribs.end(), context_attribs.begin(), context_attribs.end());
}
if (core && (!ctx || s_glxError))
{
- int context_attribs_33[] = {GLX_CONTEXT_MAJOR_VERSION_ARB,
- 3,
- GLX_CONTEXT_MINOR_VERSION_ARB,
- 3,
- GLX_CONTEXT_PROFILE_MASK_ARB,
- GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
- GLX_CONTEXT_FLAGS_ARB,
- GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
- None};
+ std::array<int, 9> context_attribs_33 = {
+ {GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 3,
+ GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB,
+ GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}};
s_glxError = false;
- ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs_33);
+ ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs_33[0]);
XSync(dpy, False);
+ m_attribs.clear();
+ m_attribs.insert(m_attribs.end(), context_attribs_33.begin(), context_attribs_33.end());
}
if (!ctx || s_glxError)
{
- int context_attribs_legacy[] = {GLX_CONTEXT_MAJOR_VERSION_ARB, 1, GLX_CONTEXT_MINOR_VERSION_ARB,
- 0, None};
+ std::array<int, 5> context_attribs_legacy = {
+ {GLX_CONTEXT_MAJOR_VERSION_ARB, 1, GLX_CONTEXT_MINOR_VERSION_ARB, 0, None}};
s_glxError = false;
- ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs_legacy);
+ ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs_legacy[0]);
XSync(dpy, False);
+ m_attribs.clear();
+ m_attribs.insert(m_attribs.end(), context_attribs_legacy.begin(), context_attribs_legacy.end());
}
if (!ctx || s_glxError)
{
@@ -153,30 +152,116 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core)
}
XSetErrorHandler(oldHandler);
- XWindow.Initialize(dpy);
+ std::string tmp;
+ std::istringstream buffer(glXQueryExtensionsString(dpy, screen));
+ while (buffer >> tmp)
+ {
+ if (tmp == "GLX_SGIX_pbuffer")
+ m_supports_pbuffer = true;
+ }
- Window parent = (Window)window_handle;
+ if (m_supports_pbuffer)
+ {
+ // Get the function pointers we require
+ glXCreateGLXPbufferSGIX =
+ (PFNGLXCREATEGLXPBUFFERSGIXPROC)GetFuncAddress("glXCreateGLXPbufferSGIX");
+ glXDestroyGLXPbufferSGIX =
+ (PFNGLXDESTROYGLXPBUFFERSGIXPROC)GetFuncAddress("glXDestroyGLXPbufferSGIX");
+ }
- XWindowAttributes attribs;
- if (!XGetWindowAttributes(dpy, parent, &attribs))
+ if (!CreateWindowSurface())
{
- ERROR_LOG(VIDEO, "Window attribute retrieval failed");
+ ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n");
return false;
}
+ return true;
+}
+
+bool cInterfaceGLX::Create(cInterfaceBase* main_context)
+{
+ cInterfaceGLX* glx_context = static_cast<cInterfaceGLX*>(main_context);
- s_backbuffer_width = attribs.width;
- s_backbuffer_height = attribs.height;
+ m_has_handle = false;
+ dpy = glx_context->dpy;
+ fbconfig = glx_context->fbconfig;
+ s_glxError = false;
+ XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler);
- win = XWindow.CreateXWindow(parent, vi);
- XFree(vi);
+ ctx = glXCreateContextAttribs(dpy, fbconfig, glx_context->ctx, True, &glx_context->m_attribs[0]);
+ XSync(dpy, False);
+ if (!ctx || s_glxError)
+ {
+ ERROR_LOG(VIDEO, "Unable to create GL context.");
+ return false;
+ }
+ XSetErrorHandler(oldHandler);
+
+ if (!CreateWindowSurface())
+ {
+ ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n");
+ return false;
+ }
return true;
}
+std::unique_ptr<cInterfaceBase> cInterfaceGLX::CreateSharedContext()
+{
+ std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceGLX>();
+ if (!context->Create(this))
+ return nullptr;
+ return context;
+}
+
+bool cInterfaceGLX::CreateWindowSurface()
+{
+ if (m_has_handle)
+ {
+ // Get an appropriate visual
+ XVisualInfo* vi = glXGetVisualFromFBConfig(dpy, fbconfig);
+
+ XWindow.Initialize(dpy);
+
+ XWindowAttributes attribs;
+ if (!XGetWindowAttributes(dpy, m_host_window, &attribs))
+ {
+ ERROR_LOG(VIDEO, "Window attribute retrieval failed");
+ return false;
+ }
+
+ s_backbuffer_width = attribs.width;
+ s_backbuffer_height = attribs.height;
+
+ win = XWindow.CreateXWindow(m_host_window, vi);
+ XFree(vi);
+ }
+ else
+ {
+ win = m_pbuffer = glXCreateGLXPbufferSGIX(dpy, fbconfig, 1, 1, nullptr);
+ if (!m_pbuffer)
+ return false;
+ }
+
+ return true;
+}
+
+void cInterfaceGLX::DestroyWindowSurface()
+{
+ if (!m_pbuffer)
+ {
+ XWindow.DestroyXWindow();
+ }
+ else
+ {
+ glXDestroyGLXPbufferSGIX(dpy, m_pbuffer);
+ m_pbuffer = 0;
+ }
+}
+
bool cInterfaceGLX::MakeCurrent()
{
bool success = glXMakeCurrent(dpy, win, ctx);
- if (success)
+ if (success && !glXSwapIntervalSGI)
{
// load this function based on the current bound context
glXSwapIntervalSGI =
@@ -193,11 +278,18 @@ bool cInterfaceGLX::ClearCurrent()
// Close backend
void cInterfaceGLX::Shutdown()
{
- XWindow.DestroyXWindow();
+ DestroyWindowSurface();
if (ctx)
{
glXDestroyContext(dpy, ctx);
- XCloseDisplay(dpy);
- ctx = nullptr;
+
+ // Don't close the display connection if we are a shared context.
+ // Saves doing reference counting on this object, and the main context will always
+ // be shut down last anyway.
+ if (m_has_handle)
+ {
+ XCloseDisplay(dpy);
+ ctx = nullptr;
+ }
}
}