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 | |
| parent | 5e6d5493165d1214f513b91eaeb4e162d21fdd3e (diff) | |
| parent | 357c55442f3dbdf6f23d16af5362d1a615cb84c1 (diff) | |
Merge pull request #5832 from stenzek/ubershader-prereq
Ubershader prerequisites
Diffstat (limited to 'Source/Core/Common/GL/GLInterface')
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/AGL.h | 8 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/AGL.mm | 33 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGL.cpp | 26 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGL.h | 2 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/GLX.cpp | 174 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/GLX.h | 13 |
6 files changed, 189 insertions, 67 deletions
diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h index 5f9a138282..8d62086954 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ b/Source/Core/Common/GL/GLInterface/AGL.h @@ -8,6 +8,7 @@ #import <AppKit/AppKit.h> #else struct NSOpenGLContext; +struct NSOpenGLPixelFormat; struct NSView; #endif @@ -18,13 +19,16 @@ class cInterfaceAGL : public cInterfaceBase public: void Swap() override; bool Create(void* window_handle, bool stereo, bool core) override; + bool Create(cInterfaceBase* main_context) override; bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; void Update() override; void SwapInterval(int interval) override; + std::unique_ptr<cInterfaceBase> CreateSharedContext() override; private: - NSView* m_view; - NSOpenGLContext* m_context; + NSView* m_view = nullptr; + NSOpenGLContext* m_context = nullptr; + NSOpenGLPixelFormat* m_pixel_format = nullptr; }; diff --git a/Source/Core/Common/GL/GLInterface/AGL.mm b/Source/Core/Common/GL/GLInterface/AGL.mm index bdae829cbc..07502475f7 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ b/Source/Core/Common/GL/GLInterface/AGL.mm @@ -60,15 +60,14 @@ bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core) NSOpenGLPFAAccelerated, stereo ? NSOpenGLPFAStereo : static_cast<NSOpenGLPixelFormatAttribute>(0), 0}; - NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; - if (fmt == nil) + m_pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; + if (m_pixel_format == nil) { ERROR_LOG(VIDEO, "failed to create pixel format"); return false; } - m_context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil]; - [fmt release]; + m_context = [[NSOpenGLContext alloc] initWithFormat:m_pixel_format shareContext:nil]; if (m_context == nil) { ERROR_LOG(VIDEO, "failed to create context"); @@ -82,6 +81,30 @@ bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core) return AttachContextToView(m_context, m_view, &s_backbuffer_width, &s_backbuffer_height); } +bool cInterfaceAGL::Create(cInterfaceBase* main_context) +{ + cInterfaceAGL* agl_context = static_cast<cInterfaceAGL*>(main_context); + NSOpenGLPixelFormat* pixel_format = agl_context->m_pixel_format; + NSOpenGLContext* share_context = agl_context->m_context; + + m_context = [[NSOpenGLContext alloc] initWithFormat:pixel_format shareContext:share_context]; + if (m_context == nil) + { + ERROR_LOG(VIDEO, "failed to create shared context"); + return false; + } + + return true; +} + +std::unique_ptr<cInterfaceBase> cInterfaceAGL::CreateSharedContext() +{ + std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceAGL>(); + if (!context->Create(this)) + return nullptr; + return context; +} + bool cInterfaceAGL::MakeCurrent() { [m_context makeCurrentContext]; @@ -100,6 +123,8 @@ void cInterfaceAGL::Shutdown() [m_context clearDrawable]; [m_context release]; m_context = nil; + [m_pixel_format release]; + m_pixel_format = nil; } void cInterfaceAGL::Update() diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index 32cd705d73..8e85511fc7 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -212,7 +212,10 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &core_attribs[0]); if (egl_ctx) + { + m_attribs = std::move(core_attribs); break; + } } } @@ -220,6 +223,7 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) { m_core = false; egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]); + m_attribs = std::move(ctx_attribs); } if (!egl_ctx) @@ -255,31 +259,13 @@ bool cInterfaceEGL::Create(cInterfaceBase* main_context) m_is_shared = true; m_has_handle = false; - EGLint ctx_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; - - switch (egl_context->GetMode()) - { - case GLInterfaceMode::MODE_OPENGL: - ctx_attribs[0] = EGL_NONE; - break; - case GLInterfaceMode::MODE_OPENGLES2: - ctx_attribs[1] = 2; - break; - case GLInterfaceMode::MODE_OPENGLES3: - ctx_attribs[1] = 3; - break; - default: - INFO_LOG(VIDEO, "Unknown opengl mode set"); - return false; - break; - } - if (egl_context->GetMode() == GLInterfaceMode::MODE_OPENGL) eglBindAPI(EGL_OPENGL_API); else eglBindAPI(EGL_OPENGL_ES_API); - egl_ctx = eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, ctx_attribs); + egl_ctx = + eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, egl_context->m_attribs.data()); if (!egl_ctx) { INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x", eglGetError()); diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index 69a351851f..16a716e3c2 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -7,6 +7,7 @@ #include <EGL/egl.h> #include <EGL/eglext.h> #include <string> +#include <vector> #include "Common/GL/GLInterfaceBase.h" @@ -17,6 +18,7 @@ private: bool m_has_handle; EGLNativeWindowType m_host_window; bool m_supports_surfaceless = false; + std::vector<int> m_attribs; bool CreateWindowSurface(); void DestroyWindowSurface(); 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; + } } } diff --git a/Source/Core/Common/GL/GLInterface/GLX.h b/Source/Core/Common/GL/GLInterface/GLX.h index ae019ccbf9..724dca5141 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.h +++ b/Source/Core/Common/GL/GLInterface/GLX.h @@ -5,7 +5,10 @@ #pragma once #include <GL/glx.h> +#include <GL/glxext.h> +#include <memory> #include <string> +#include <vector> #include "Common/GL/GLInterface/X11_Util.h" #include "Common/GL/GLInterfaceBase.h" @@ -13,11 +16,19 @@ class cInterfaceGLX : public cInterfaceBase { private: + Window m_host_window; cX11Window XWindow; Display* dpy; Window win; GLXContext ctx; GLXFBConfig fbconfig; + bool m_has_handle; + bool m_supports_pbuffer = false; + GLXPbufferSGIX m_pbuffer = 0; + std::vector<int> m_attribs; + + bool CreateWindowSurface(); + void DestroyWindowSurface(); public: friend class cX11Window; @@ -25,7 +36,9 @@ public: void Swap() override; void* GetFuncAddress(const std::string& name) override; bool Create(void* window_handle, bool stereo, bool core) override; + bool Create(cInterfaceBase* main_context) override; bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; + std::unique_ptr<cInterfaceBase> CreateSharedContext() override; }; |
