From 134d967be2dd4ba9531abb8ba8494c3ac423ca72 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:02:45 +1000 Subject: Refactoring and cleanup of GLInterface (now GLContext) --- Source/Core/Common/GL/GLInterface/GLX.cpp | 142 +++++++++++++++--------------- 1 file changed, 69 insertions(+), 73 deletions(-) (limited to 'Source/Core/Common/GL/GLInterface/GLX.cpp') diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index 28714fd20c..173127fc5b 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -30,43 +30,40 @@ static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) return 0; } -void cInterfaceGLX::SwapInterval(int Interval) +void GLContextGLX::SwapInterval(int Interval) { - if (!m_has_handle) + if (!m_drawable) return; // Try EXT_swap_control, then MESA_swap_control. if (glXSwapIntervalEXTPtr) - glXSwapIntervalEXTPtr(dpy, win, Interval); + glXSwapIntervalEXTPtr(m_display, m_drawable, Interval); else if (glXSwapIntervalMESAPtr) glXSwapIntervalMESAPtr(static_cast(Interval)); else ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); } -void* cInterfaceGLX::GetFuncAddress(const std::string& name) +void* GLContextGLX::GetFuncAddress(const std::string& name) { - return (void*)glXGetProcAddress((const GLubyte*)name.c_str()); + return reinterpret_cast(glXGetProcAddress(reinterpret_cast(name.c_str()))); } -void cInterfaceGLX::Swap() +void GLContextGLX::Swap() { - glXSwapBuffers(dpy, win); + glXSwapBuffers(m_display, m_drawable); } // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) +bool GLContextGLX::Initialize(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); + m_display = XOpenDisplay(nullptr); + int screen = DefaultScreen(m_display); // checking glx version int glxMajorVersion, glxMinorVersion; - glXQueryVersion(dpy, &glxMajorVersion, &glxMinorVersion); + glXQueryVersion(m_display, &glxMajorVersion, &glxMinorVersion); if (glxMajorVersion < 1 || (glxMajorVersion == 1 && glxMinorVersion < 4)) { ERROR_LOG(VIDEO, "glX-Version %d.%d detected, but need at least 1.4", glxMajorVersion, @@ -107,13 +104,13 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) stereo ? True : False, None}; int fbcount = 0; - GLXFBConfig* fbc = glXChooseFBConfig(dpy, screen, visual_attribs, &fbcount); + GLXFBConfig* fbc = glXChooseFBConfig(m_display, screen, visual_attribs, &fbcount); if (!fbc || !fbcount) { ERROR_LOG(VIDEO, "Failed to retrieve a framebuffer config"); return false; } - fbconfig = *fbc; + m_fbconfig = *fbc; XFree(fbc); s_glxError = false; @@ -125,36 +122,36 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) {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; + m_context = nullptr; if (core) { - ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs[0]); - XSync(dpy, False); + m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs[0]); + XSync(m_display, False); m_attribs.insert(m_attribs.end(), context_attribs.begin(), context_attribs.end()); } - if (core && (!ctx || s_glxError)) + if (core && (!m_context || s_glxError)) { std::array 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[0]); - XSync(dpy, False); + m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs_33[0]); + XSync(m_display, False); m_attribs.clear(); m_attribs.insert(m_attribs.end(), context_attribs_33.begin(), context_attribs_33.end()); } - if (!ctx || s_glxError) + if (!m_context || s_glxError) { std::array 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[0]); - XSync(dpy, False); + m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs_legacy[0]); + XSync(m_display, False); m_attribs.clear(); m_attribs.insert(m_attribs.end(), context_attribs_legacy.begin(), context_attribs_legacy.end()); } - if (!ctx || s_glxError) + if (!m_context || s_glxError) { ERROR_LOG(VIDEO, "Unable to create GL context."); XSetErrorHandler(oldHandler); @@ -168,7 +165,7 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) m_supports_pbuffer = false; std::string tmp; - std::istringstream buffer(glXQueryExtensionsString(dpy, screen)); + std::istringstream buffer(glXQueryExtensionsString(m_display, screen)); while (buffer >> tmp) { if (tmp == "GLX_SGIX_pbuffer") @@ -191,7 +188,7 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) } } - if (!CreateWindowSurface()) + if (!CreateWindowSurface(reinterpret_cast(window_handle))) { ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n"); XSetErrorHandler(oldHandler); @@ -199,31 +196,33 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) } XSetErrorHandler(oldHandler); + m_opengl_mode = Mode::OpenGL; return true; } -bool cInterfaceGLX::Create(cInterfaceBase* main_context) +bool GLContextGLX::Initialize(GLContext* main_context) { - cInterfaceGLX* glx_context = static_cast(main_context); + GLContextGLX* glx_context = static_cast(main_context); - m_has_handle = false; + m_opengl_mode = glx_context->m_opengl_mode; m_supports_pbuffer = glx_context->m_supports_pbuffer; - dpy = glx_context->dpy; - fbconfig = glx_context->fbconfig; + m_display = glx_context->m_display; + m_fbconfig = glx_context->m_fbconfig; s_glxError = false; XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler); - ctx = glXCreateContextAttribs(dpy, fbconfig, glx_context->ctx, True, &glx_context->m_attribs[0]); - XSync(dpy, False); + m_context = glXCreateContextAttribs(m_display, m_fbconfig, glx_context->m_context, True, + &glx_context->m_attribs[0]); + XSync(m_display, False); - if (!ctx || s_glxError) + if (!m_context || s_glxError) { ERROR_LOG(VIDEO, "Unable to create GL context."); XSetErrorHandler(oldHandler); return false; } - if (m_supports_pbuffer && !CreateWindowSurface()) + if (m_supports_pbuffer && !CreateWindowSurface(None)) { ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n"); XSetErrorHandler(oldHandler); @@ -234,84 +233,81 @@ bool cInterfaceGLX::Create(cInterfaceBase* main_context) return true; } -std::unique_ptr cInterfaceGLX::CreateSharedContext() +bool GLContextGLX::IsHeadless() const +{ + return m_render_window == nullptr; +} + +std::unique_ptr GLContextGLX::CreateSharedContext() { - std::unique_ptr context = std::make_unique(); - if (!context->Create(this)) + std::unique_ptr context = std::make_unique(); + if (!context->Initialize(this)) return nullptr; return context; } -bool cInterfaceGLX::CreateWindowSurface() +bool GLContextGLX::CreateWindowSurface(Window window_handle) { - if (m_has_handle) + if (window_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"); + XVisualInfo* vi = glXGetVisualFromFBConfig(m_display, m_fbconfig); + m_render_window = GLX11Window::Create(m_display, window_handle, vi); + if (!m_render_window) return false; - } - - s_backbuffer_width = attribs.width; - s_backbuffer_height = attribs.height; - win = XWindow.CreateXWindow(m_host_window, vi); + m_backbuffer_width = m_render_window->GetWidth(); + m_backbuffer_height = m_render_window->GetHeight(); + m_drawable = static_cast(m_render_window->GetWindow()); XFree(vi); } else if (m_supports_pbuffer) { - win = m_pbuffer = glXCreateGLXPbufferSGIX(dpy, fbconfig, 1, 1, nullptr); + m_pbuffer = glXCreateGLXPbufferSGIX(m_display, m_fbconfig, 1, 1, nullptr); if (!m_pbuffer) return false; + + m_drawable = static_cast(m_pbuffer); } return true; } -void cInterfaceGLX::DestroyWindowSurface() +void GLContextGLX::DestroyWindowSurface() { - if (m_has_handle) - { - XWindow.DestroyXWindow(); - } - else if (m_supports_pbuffer && m_pbuffer) + m_render_window.reset(); + if (m_supports_pbuffer && m_pbuffer) { - glXDestroyGLXPbufferSGIX(dpy, m_pbuffer); + glXDestroyGLXPbufferSGIX(m_display, m_pbuffer); m_pbuffer = 0; } } -bool cInterfaceGLX::MakeCurrent() +bool GLContextGLX::MakeCurrent() { - return glXMakeCurrent(dpy, win, ctx); + return glXMakeCurrent(m_display, m_drawable, m_context); } -bool cInterfaceGLX::ClearCurrent() +bool GLContextGLX::ClearCurrent() { - return glXMakeCurrent(dpy, None, nullptr); + return glXMakeCurrent(m_display, None, nullptr); } // Close backend -void cInterfaceGLX::Shutdown() +void GLContextGLX::Shutdown() { DestroyWindowSurface(); - if (ctx) + if (m_context) { - glXDestroyContext(dpy, ctx); + glXDestroyContext(m_display, m_context); // 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) + if (m_render_window) { - XCloseDisplay(dpy); - ctx = nullptr; + XCloseDisplay(m_display); + m_context = nullptr; } } } -- cgit v1.2.3 From 9c57a98723997736adea94383668fbdf8a993fd8 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:19 +1000 Subject: GLContext: Use host connection This also removes the need for a sleeping event thread. --- Source/Core/Common/GL/GLInterface/GLX.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'Source/Core/Common/GL/GLInterface/GLX.cpp') diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index 173127fc5b..c2569bd153 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -56,9 +56,9 @@ void GLContextGLX::Swap() // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool GLContextGLX::Initialize(void* window_handle, bool stereo, bool core) +bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool stereo, bool core) { - m_display = XOpenDisplay(nullptr); + m_display = static_cast(display_handle); int screen = DefaultScreen(m_display); // checking glx version @@ -298,16 +298,12 @@ void GLContextGLX::Shutdown() { DestroyWindowSurface(); if (m_context) - { glXDestroyContext(m_display, m_context); +} - // 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_render_window) - { - XCloseDisplay(m_display); - m_context = nullptr; - } - } +void GLContextGLX::Update() +{ + m_render_window->UpdateDimensions(); + m_backbuffer_width = m_render_window->GetWidth(); + m_backbuffer_height = m_render_window->GetHeight(); } -- cgit v1.2.3 From 4b8d1c2b429485d54d7dad2fdc142ed43b34b992 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:30 +1000 Subject: GLContext: Combine shared context initialization and creation --- Source/Core/Common/GL/GLInterface/GLX.cpp | 49 +++++++++++++------------------ 1 file changed, 21 insertions(+), 28 deletions(-) (limited to 'Source/Core/Common/GL/GLInterface/GLX.cpp') diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index c2569bd153..7a8e67f109 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -30,6 +30,11 @@ static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) return 0; } +bool GLContextGLX::IsHeadless() const +{ + return m_render_window == nullptr; +} + void GLContextGLX::SwapInterval(int Interval) { if (!m_drawable) @@ -200,50 +205,38 @@ bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool st return true; } -bool GLContextGLX::Initialize(GLContext* main_context) +std::unique_ptr GLContextGLX::CreateSharedContext() { - GLContextGLX* glx_context = static_cast(main_context); - - m_opengl_mode = glx_context->m_opengl_mode; - m_supports_pbuffer = glx_context->m_supports_pbuffer; - m_display = glx_context->m_display; - m_fbconfig = glx_context->m_fbconfig; s_glxError = false; XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler); - m_context = glXCreateContextAttribs(m_display, m_fbconfig, glx_context->m_context, True, - &glx_context->m_attribs[0]); + GLXContext new_glx_context = + glXCreateContextAttribs(m_display, m_fbconfig, m_context, True, &m_attribs[0]); XSync(m_display, False); - if (!m_context || s_glxError) + if (!new_glx_context || s_glxError) { ERROR_LOG(VIDEO, "Unable to create GL context."); XSetErrorHandler(oldHandler); - return false; + return nullptr; } - if (m_supports_pbuffer && !CreateWindowSurface(None)) + std::unique_ptr new_context = std::make_unique(); + new_context->m_context = new_glx_context; + new_context->m_opengl_mode = m_opengl_mode; + new_context->m_supports_pbuffer = m_supports_pbuffer; + new_context->m_display = m_display; + new_context->m_fbconfig = m_fbconfig; + + if (m_supports_pbuffer && !new_context->CreateWindowSurface(None)) { - ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n"); + ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed"); XSetErrorHandler(oldHandler); - return false; + return nullptr; } XSetErrorHandler(oldHandler); - return true; -} - -bool GLContextGLX::IsHeadless() const -{ - return m_render_window == nullptr; -} - -std::unique_ptr GLContextGLX::CreateSharedContext() -{ - std::unique_ptr context = std::make_unique(); - if (!context->Initialize(this)) - return nullptr; - return context; + return new_context; } bool GLContextGLX::CreateWindowSurface(Window window_handle) -- cgit v1.2.3 From 025e909773a2761cad8a3954498fe800f6f94963 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:33 +1000 Subject: GLContext: Use destructor instead of Shutdown() to cleanup Also uses the Initialize() method to make the context current. --- Source/Core/Common/GL/GLInterface/GLX.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'Source/Core/Common/GL/GLInterface/GLX.cpp') diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index 7a8e67f109..d74bccf8a4 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -30,9 +30,21 @@ static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) return 0; } +GLContextGLX::~GLContextGLX() +{ + DestroyWindowSurface(); + if (m_context) + { + if (glXGetCurrentContext() == m_context) + glXMakeCurrent(m_display, None, nullptr); + + glXDestroyContext(m_display, m_context); + } +} + bool GLContextGLX::IsHeadless() const { - return m_render_window == nullptr; + return !m_render_window; } void GLContextGLX::SwapInterval(int Interval) @@ -202,7 +214,7 @@ bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool st XSetErrorHandler(oldHandler); m_opengl_mode = Mode::OpenGL; - return true; + return MakeCurrent(); } std::unique_ptr GLContextGLX::CreateSharedContext() @@ -227,6 +239,7 @@ std::unique_ptr GLContextGLX::CreateSharedContext() new_context->m_supports_pbuffer = m_supports_pbuffer; new_context->m_display = m_display; new_context->m_fbconfig = m_fbconfig; + new_context->m_is_shared = true; if (m_supports_pbuffer && !new_context->CreateWindowSurface(None)) { @@ -286,14 +299,6 @@ bool GLContextGLX::ClearCurrent() return glXMakeCurrent(m_display, None, nullptr); } -// Close backend -void GLContextGLX::Shutdown() -{ - DestroyWindowSurface(); - if (m_context) - glXDestroyContext(m_display, m_context); -} - void GLContextGLX::Update() { m_render_window->UpdateDimensions(); -- cgit v1.2.3 From 2c6d96433c322b50470705d43005fd6308506d49 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 14 Oct 2018 23:32:50 +1000 Subject: GLContext: Try GL versions 3.2-4.6 when getting a context GLX previously was only creating a 4.0 context. --- Source/Core/Common/GL/GLInterface/GLX.cpp | 41 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'Source/Core/Common/GL/GLInterface/GLX.cpp') diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index d74bccf8a4..c2e4491ff5 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -134,30 +134,29 @@ bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool st 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. - std::array 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}}; - m_context = nullptr; if (core) { - m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs[0]); - XSync(m_display, False); - m_attribs.insert(m_attribs.end(), context_attribs.begin(), context_attribs.end()); - } - if (core && (!m_context || s_glxError)) - { - std::array 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; - m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs_33[0]); - XSync(m_display, False); - m_attribs.clear(); - m_attribs.insert(m_attribs.end(), context_attribs_33.begin(), context_attribs_33.end()); + for (const auto& version : s_desktop_opengl_versions) + { + std::array context_attribs = { + {GLX_CONTEXT_MAJOR_VERSION_ARB, version.first, GLX_CONTEXT_MINOR_VERSION_ARB, + version.second, 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; + m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs[0]); + XSync(m_display, False); + m_attribs.insert(m_attribs.end(), context_attribs.begin(), context_attribs.end()); + if (!m_context || s_glxError) + continue; + + // Got a context. + INFO_LOG(VIDEO, "Created a GLX context with version %d.%d", version.first, version.second); + break; + } } + + // Failed to create any core contexts, try for anything. if (!m_context || s_glxError) { std::array context_attribs_legacy = { -- cgit v1.2.3