summaryrefslogtreecommitdiff
path: root/Source/Core/Common/GL/GLInterface
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
parent5e6d5493165d1214f513b91eaeb4e162d21fdd3e (diff)
parent357c55442f3dbdf6f23d16af5362d1a615cb84c1 (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.h8
-rw-r--r--Source/Core/Common/GL/GLInterface/AGL.mm33
-rw-r--r--Source/Core/Common/GL/GLInterface/EGL.cpp26
-rw-r--r--Source/Core/Common/GL/GLInterface/EGL.h2
-rw-r--r--Source/Core/Common/GL/GLInterface/GLX.cpp174
-rw-r--r--Source/Core/Common/GL/GLInterface/GLX.h13
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;
};