diff options
| author | Anthony <Helios747@users.noreply.github.com> | 2017-07-30 00:42:36 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-30 00:42:36 -0700 |
| commit | 5bad2ee4a4129e734ff4f4d861cedc4cd573df55 (patch) | |
| tree | cd3c3ccc6e35417858499449d774670c3983cb13 /Source/Core/Common/GL/GLInterface/GLX.cpp | |
| parent | 5e6d5493165d1214f513b91eaeb4e162d21fdd3e (diff) | |
| parent | 357c55442f3dbdf6f23d16af5362d1a615cb84c1 (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.cpp | 174 |
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; + } } } |
