diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 4d230fca60..34a19f6426 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -22,7 +22,6 @@ #include "Common/CommonTypes.h" #include "Common/Event.h" #include "Common/FileUtil.h" -#include "Common/GL/GLInterfaceBase.h" #include "Common/Logging/LogManager.h" #include "Common/MsgHandler.h" #include "Common/Version.h" diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index d0ac4a48cd..f6430c04f3 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -110,7 +110,7 @@ endif() target_sources(common PRIVATE GL/GLUtil.cpp GL/GLExtensions/GLExtensions.cpp - GL/GLInterface/GLInterface.cpp + GL/GLContext.cpp ) if(USE_EGL) @@ -137,7 +137,7 @@ elseif(USE_X11) # Make sure to link to it if using GLX. target_link_libraries(common PUBLIC ${OPENGL_LIBRARIES}) endif() - target_sources(common PRIVATE GL/GLInterface/X11_Util.cpp) + target_sources(common PRIVATE GL/GLX11Window.cpp) target_link_libraries(common PUBLIC ${XRANDR_LIBRARIES}) endif() diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index d0751f8c3f..23752002cf 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -121,7 +121,7 @@ - + @@ -189,7 +189,7 @@ - + @@ -255,4 +255,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index 3737a5a1ff..63a131a8dc 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -243,9 +243,6 @@ GL\GLInterface - - GL\GLInterface - @@ -275,6 +272,9 @@ Debug + + GL\GLInterface + @@ -339,9 +339,6 @@ GL\GLInterface - - GL\GLInterface - @@ -355,6 +352,9 @@ Debug + + GL\GLInterface + @@ -362,4 +362,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp new file mode 100644 index 0000000000..da22f45c3b --- /dev/null +++ b/Source/Core/Common/GL/GLContext.cpp @@ -0,0 +1,115 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +#include "Common/GL/GLContext.h" + +#if defined(__APPLE__) +#include "Common/GL/GLInterface/AGL.h" +#elif defined(_WIN32) +#include "Common/GL/GLInterface/WGL.h" +#elif HAVE_X11 +#if defined(USE_EGL) && USE_EGL +#include "Common/GL/GLInterface/EGLX11.h" +#else +#include "Common/GL/GLInterface/GLX.h" +#endif +#elif defined(USE_EGL) && USE_EGL && defined(USE_HEADLESS) +#include "Common/GL/GLInterface/EGL.h" +#elif ANDROID +#include "Common/GL/GLInterface/EGLAndroid.h" +#error Platform doesnt have a GLInterface +#endif + +std::unique_ptr g_main_gl_context; + +GLContext::~GLContext() = default; + +bool GLContext::Initialize(void* window_handle, bool stereo, bool core) +{ + return false; +} + +bool GLContext::Initialize(GLContext* main_context) +{ + return false; +} + +void GLContext::SetBackBufferDimensions(u32 w, u32 h) +{ + m_backbuffer_width = w; + m_backbuffer_height = h; +} + +bool GLContext::IsHeadless() const +{ + return true; +} + +std::unique_ptr GLContext::CreateSharedContext() +{ + return nullptr; +} + +bool GLContext::MakeCurrent() +{ + return false; +} + +bool GLContext::ClearCurrent() +{ + return false; +} + +void GLContext::Shutdown() +{ +} + +void GLContext::Update() +{ +} + +void GLContext::UpdateSurface(void* window_handle) +{ +} + +void GLContext::Swap() +{ +} + +void GLContext::SwapInterval(int interval) +{ +} + +void* GLContext::GetFuncAddress(const std::string& name) +{ + return nullptr; +} + +std::unique_ptr GLContext::Create(void* window_handle, bool stereo, bool core) +{ + std::unique_ptr context; +#if defined(__APPLE__) + context = std::make_unique(); +#elif defined(_WIN32) + context = std::make_unique(); +#elif defined(USE_EGL) && defined(USE_HEADLESS) + context = std::make_unique(); +#elif defined(HAVE_X11) && HAVE_X11 +#if defined(USE_EGL) && USE_EGL + context = std::make_unique(); +#else + context = std::make_unique(); +#endif +#elif ANDROID + context = std::make_unique(); +#else + return nullptr; +#endif + if (!context->Initialize(window_handle, stereo, core)) + return nullptr; + + return context; +} diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h new file mode 100644 index 0000000000..990883ca90 --- /dev/null +++ b/Source/Core/Common/GL/GLContext.h @@ -0,0 +1,64 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "Common/CommonTypes.h" + +class GLContext +{ +public: + enum class Mode + { + Detect, + OpenGL, + OpenGLES + }; + + virtual ~GLContext(); + + Mode GetMode() { return m_opengl_mode; } + bool IsGLES() const { return m_opengl_mode == Mode::OpenGLES; } + + u32 GetBackBufferWidth() { return m_backbuffer_width; } + u32 GetBackBufferHeight() { return m_backbuffer_height; } + void SetBackBufferDimensions(u32 w, u32 h); + + virtual bool IsHeadless() const; + + virtual std::unique_ptr CreateSharedContext(); + virtual void Shutdown(); + + virtual bool MakeCurrent(); + virtual bool ClearCurrent(); + + virtual void Update(); + virtual void UpdateSurface(void* window_handle); + + virtual void Swap(); + virtual void SwapInterval(int interval); + + virtual void* GetFuncAddress(const std::string& name); + + // Creates an instance of GLInterface specific to the platform we are running on. + static std::unique_ptr Create(void* window_handle, bool stereo = false, + bool core = true); + +protected: + virtual bool Initialize(void* window_handle, bool stereo, bool core); + virtual bool Initialize(GLContext* main_context); + + Mode m_opengl_mode = Mode::Detect; + + // Window dimensions. + u32 m_backbuffer_width = 0; + u32 m_backbuffer_height = 0; + bool m_is_core_context = false; + bool m_is_shared = false; +}; + +extern std::unique_ptr g_main_gl_context; diff --git a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp index 9252a7bed3..18c4dc2f39 100644 --- a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp +++ b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp @@ -5,8 +5,8 @@ #include #include +#include "Common/GL/GLContext.h" #include "Common/GL/GLExtensions/GLExtensions.h" -#include "Common/GL/GLInterfaceBase.h" #include "Common/Logging/Log.h" #if defined(__linux__) || defined(__APPLE__) @@ -2432,7 +2432,7 @@ static void InitVersion() static void* GetFuncAddress(const std::string& name, void** func) { - *func = GLInterface->GetFuncAddress(name); + *func = g_main_gl_context->GetFuncAddress(name); if (*func == nullptr) { #if defined(__linux__) || defined(__APPLE__) @@ -2457,7 +2457,7 @@ bool Supports(const std::string& name) bool Init() { - _isES = GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL; + _isES = g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES; // Grab a few functions for initial checking // We need them to grab the extension list @@ -2507,4 +2507,4 @@ bool InitFunctionPointers() result &= !!GetFuncAddress(it.function_name, it.function_ptr); return result; } -} +} // namespace GLExtensions diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h index 8d62086954..3032fe573d 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ b/Source/Core/Common/GL/GLInterface/AGL.h @@ -12,22 +12,28 @@ struct NSOpenGLPixelFormat; struct NSView; #endif -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" -class cInterfaceAGL : public cInterfaceBase +class GLContextAGL : public GLContext { public: - void Swap() override; - bool Create(void* window_handle, bool stereo, bool core) override; - bool Create(cInterfaceBase* main_context) override; + bool IsHeadless() const override; + + std::unique_ptr CreateSharedContext() override; + void Shutdown() override; + bool MakeCurrent() override; bool ClearCurrent() override; - void Shutdown() override; - void Update() override; - void SwapInterval(int interval) override; - std::unique_ptr CreateSharedContext() override; -private: + void Update() override; + + void Swap() override; + void SwapInterval(int interval) override; + +protected: + bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(GLContext* main_context) override; + 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 07502475f7..80b82f917e 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ b/Source/Core/Common/GL/GLInterface/AGL.mm @@ -10,16 +10,15 @@ static bool UpdateCachedDimensions(NSView* view, u32* width, u32* height) NSWindow* window = [view window]; NSSize size = [view frame].size; - float scale = [window backingScaleFactor]; - size.width *= scale; - size.height *= scale; + const CGFloat scale = [window backingScaleFactor]; + u32 new_width = static_cast(size.width * scale); + u32 new_height = static_cast(size.height * scale); - if (*width == size.width && *height == size.height) + if (*width == new_width && *height == new_height) return false; - *width = size.width; - *height = size.height; - + *width = new_width; + *height = new_height; return true; } @@ -44,14 +43,19 @@ static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* wid return true; } -void cInterfaceAGL::Swap() +bool GLContextAGL::IsHeadless() const +{ + return !m_view; +} + +void GLContextAGL::Swap() { [m_context flushBuffer]; } // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core) +bool GLContextAGL::Initialize(void* window_handle, bool stereo, bool core) { NSOpenGLPixelFormatAttribute attr[] = { NSOpenGLPFADoubleBuffer, @@ -78,12 +82,13 @@ bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core) return true; m_view = static_cast(window_handle); - return AttachContextToView(m_context, m_view, &s_backbuffer_width, &s_backbuffer_height); + m_opengl_mode = Mode::OpenGL; + return AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height); } -bool cInterfaceAGL::Create(cInterfaceBase* main_context) +bool GLContextAGL::Initialize(GLContext* main_context) { - cInterfaceAGL* agl_context = static_cast(main_context); + GLContextAGL* agl_context = static_cast(main_context); NSOpenGLPixelFormat* pixel_format = agl_context->m_pixel_format; NSOpenGLContext* share_context = agl_context->m_context; @@ -97,28 +102,28 @@ bool cInterfaceAGL::Create(cInterfaceBase* main_context) return true; } -std::unique_ptr cInterfaceAGL::CreateSharedContext() +std::unique_ptr GLContextAGL::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 cInterfaceAGL::MakeCurrent() +bool GLContextAGL::MakeCurrent() { [m_context makeCurrentContext]; return true; } -bool cInterfaceAGL::ClearCurrent() +bool GLContextAGL::ClearCurrent() { [NSOpenGLContext clearCurrentContext]; return true; } // Close backend -void cInterfaceAGL::Shutdown() +void GLContextAGL::Shutdown() { [m_context clearDrawable]; [m_context release]; @@ -127,16 +132,16 @@ void cInterfaceAGL::Shutdown() m_pixel_format = nil; } -void cInterfaceAGL::Update() +void GLContextAGL::Update() { if (!m_view) return; - if (UpdateCachedDimensions(m_view, &s_backbuffer_width, &s_backbuffer_height)) + if (UpdateCachedDimensions(m_view, &m_backbuffer_width, &m_backbuffer_height)) [m_context update]; } -void cInterfaceAGL::SwapInterval(int interval) +void GLContextAGL::SwapInterval(int interval) { [m_context setValues:static_cast(&interval) forParameter:NSOpenGLCPSwapInterval]; } diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index e71b365928..46073fe074 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -28,35 +28,35 @@ #define EGL_OPENGL_ES3_BIT_KHR 0x00000040 #endif /* EGL_KHR_create_context */ -// Show the current FPS -void cInterfaceEGL::Swap() +GLContextEGL::~GLContextEGL() = default; + +bool GLContextEGL::IsHeadless() const { - if (egl_surf != EGL_NO_SURFACE) - eglSwapBuffers(egl_dpy, egl_surf); -} -void cInterfaceEGL::SwapInterval(int Interval) -{ - eglSwapInterval(egl_dpy, Interval); + return m_host_window == nullptr; } -void* cInterfaceEGL::GetFuncAddress(const std::string& name) +void GLContextEGL::Swap() +{ + if (m_egl_surface != EGL_NO_SURFACE) + eglSwapBuffers(m_egl_display, m_egl_surface); +} +void GLContextEGL::SwapInterval(int interval) +{ + eglSwapInterval(m_egl_display, interval); +} + +void* GLContextEGL::GetFuncAddress(const std::string& name) { return (void*)eglGetProcAddress(name.c_str()); } -void cInterfaceEGL::DetectMode() +void GLContextEGL::DetectMode(bool has_handle) { - if (s_opengl_mode != GLInterfaceMode::MODE_DETECT) - return; bool preferGLES = Config::Get(Config::GFX_PREFER_GLES); EGLint num_configs; - bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false; - std::array renderable_types{{ - EGL_OPENGL_BIT, - (1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */ - EGL_OPENGL_ES2_BIT, - }}; + bool supportsGL = false, supportsGLES3 = false; + std::array renderable_types{{EGL_OPENGL_BIT, EGL_OPENGL_ES3_BIT_KHR}}; for (auto renderable_type : renderable_types) { @@ -71,11 +71,11 @@ void cInterfaceEGL::DetectMode() EGL_RENDERABLE_TYPE, renderable_type, EGL_SURFACE_TYPE, - m_has_handle ? EGL_WINDOW_BIT : 0, + has_handle ? EGL_WINDOW_BIT : 0, EGL_NONE}; // Get how many configs there are - if (!eglChooseConfig(egl_dpy, attribs, nullptr, 0, &num_configs)) + if (!eglChooseConfig(m_egl_display, attribs, nullptr, 0, &num_configs)) { INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config"); continue; @@ -84,7 +84,7 @@ void cInterfaceEGL::DetectMode() EGLConfig* config = new EGLConfig[num_configs]; // Get all the configurations - if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs)) + if (!eglChooseConfig(m_egl_display, attribs, config, num_configs, &num_configs)) { INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config"); delete[] config; @@ -95,15 +95,13 @@ void cInterfaceEGL::DetectMode() { EGLint attribVal; bool ret; - ret = eglGetConfigAttrib(egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal); + ret = eglGetConfigAttrib(m_egl_display, config[i], EGL_RENDERABLE_TYPE, &attribVal); if (ret) { if (attribVal & EGL_OPENGL_BIT) supportsGL = true; - if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */ + if (attribVal & EGL_OPENGL_ES3_BIT_KHR) supportsGLES3 = true; - if (attribVal & EGL_OPENGL_ES2_BIT) - supportsGLES2 = true; } } delete[] config; @@ -112,63 +110,66 @@ void cInterfaceEGL::DetectMode() if (preferGLES) { if (supportsGLES3) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3; - else if (supportsGLES2) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2; + m_opengl_mode = Mode::OpenGLES; else if (supportsGL) - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + m_opengl_mode = Mode::OpenGL; } else { if (supportsGL) - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + m_opengl_mode = Mode::OpenGL; else if (supportsGLES3) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3; - else if (supportsGLES2) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2; + m_opengl_mode = Mode::OpenGLES; } - if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL) + if (m_opengl_mode == Mode::OpenGL) { INFO_LOG(VIDEO, "Using OpenGL"); } - else if (s_opengl_mode == GLInterfaceMode::MODE_OPENGLES3) + else if (m_opengl_mode == Mode::OpenGLES) { - INFO_LOG(VIDEO, "Using OpenGL|ES 3"); + INFO_LOG(VIDEO, "Using OpenGL|ES"); } - else if (s_opengl_mode == GLInterfaceMode::MODE_OPENGLES2) - { - INFO_LOG(VIDEO, "Using OpenGL|ES 2"); - } - else if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) + else if (m_opengl_mode == Mode::Detect) { // Errored before we found a mode ERROR_LOG(VIDEO, "Error: Failed to detect OpenGL flavour, falling back to OpenGL"); // This will fail to create a context, as it'll try to use the same attribs we just failed to // find a matching config with - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + m_opengl_mode = Mode::OpenGL; } } +EGLDisplay GLContextEGL::OpenEGLDisplay() +{ + return eglGetDisplay(EGL_DEFAULT_DISPLAY); +} + +EGLNativeWindowType GLContextEGL::GetEGLNativeWindow(EGLConfig config) +{ + return reinterpret_cast(EGL_DEFAULT_DISPLAY); +} + // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) +bool GLContextEGL::Initialize(void* window_handle, bool stereo, bool core) { + const bool has_handle = !!window_handle; + EGLint egl_major, egl_minor; bool supports_core_profile = false; - egl_dpy = OpenDisplay(); - m_host_window = (EGLNativeWindowType)window_handle; - m_has_handle = !!window_handle; - m_core = core; + m_egl_display = OpenEGLDisplay(); + m_host_window = window_handle; + m_is_core_context = core; - if (!egl_dpy) + if (!m_egl_display) { INFO_LOG(VIDEO, "Error: eglGetDisplay() failed"); return false; } - if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) + if (!eglInitialize(m_egl_display, &egl_major, &egl_minor)) { INFO_LOG(VIDEO, "Error: eglInitialize() failed"); return false; @@ -177,12 +178,13 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) /* Detection code */ EGLint num_configs; - DetectMode(); + if (m_opengl_mode == Mode::Detect) + DetectMode(has_handle); // attributes for a visual in RGBA format with at least // 8 bits per color int attribs[] = {EGL_RENDERABLE_TYPE, - EGL_OPENGL_ES2_BIT, + 0, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, @@ -190,43 +192,38 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) EGL_BLUE_SIZE, 8, EGL_SURFACE_TYPE, - m_has_handle ? EGL_WINDOW_BIT : 0, + has_handle ? EGL_WINDOW_BIT : 0, EGL_NONE}; std::vector ctx_attribs; - switch (s_opengl_mode) + switch (m_opengl_mode) { - case GLInterfaceMode::MODE_OPENGL: + case Mode::OpenGL: attribs[1] = EGL_OPENGL_BIT; ctx_attribs = {EGL_NONE}; break; - case GLInterfaceMode::MODE_OPENGLES2: - attribs[1] = EGL_OPENGL_ES2_BIT; - ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; - break; - case GLInterfaceMode::MODE_OPENGLES3: - attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */ + case Mode::OpenGLES: + attribs[1] = EGL_OPENGL_ES3_BIT_KHR; ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; break; default: ERROR_LOG(VIDEO, "Unknown opengl mode set"); return false; - break; } - if (!eglChooseConfig(egl_dpy, attribs, &m_config, 1, &num_configs)) + if (!eglChooseConfig(m_egl_display, attribs, &m_config, 1, &num_configs)) { INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config"); return false; } - if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL) + if (m_opengl_mode == Mode::OpenGL) eglBindAPI(EGL_OPENGL_API); else eglBindAPI(EGL_OPENGL_ES_API); std::string tmp; - std::istringstream buffer(eglQueryString(egl_dpy, EGL_EXTENSIONS)); + std::istringstream buffer(eglQueryString(m_egl_display, EGL_EXTENSIONS)); while (buffer >> tmp) { if (tmp == "EGL_KHR_surfaceless_context") @@ -235,7 +232,7 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) supports_core_profile = true; } - if (supports_core_profile && core && s_opengl_mode == GLInterfaceMode::MODE_OPENGL) + if (supports_core_profile && core && m_opengl_mode == Mode::OpenGL) { std::array, 7> versions_to_try = {{ {4, 5}, @@ -259,8 +256,8 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, EGL_NONE}; - egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &core_attribs[0]); - if (egl_ctx) + m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &core_attribs[0]); + if (m_egl_context) { m_attribs = std::move(core_attribs); break; @@ -268,14 +265,14 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) } } - if (!egl_ctx) + if (!m_egl_context) { - m_core = false; - egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]); + m_is_core_context = false; + m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]); m_attribs = std::move(ctx_attribs); } - if (!egl_ctx) + if (!m_egl_context) { INFO_LOG(VIDEO, "Error: eglCreateContext failed"); return false; @@ -289,33 +286,33 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) return true; } -std::unique_ptr cInterfaceEGL::CreateSharedContext() +std::unique_ptr GLContextEGL::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 cInterfaceEGL::Create(cInterfaceBase* main_context) +bool GLContextEGL::Initialize(GLContext* main_context) { - cInterfaceEGL* egl_context = static_cast(main_context); + GLContextEGL* egl_context = static_cast(main_context); - egl_dpy = egl_context->egl_dpy; - m_core = egl_context->m_core; + m_opengl_mode = egl_context->m_opengl_mode; + m_egl_display = egl_context->m_egl_display; + m_is_core_context = egl_context->m_is_core_context; m_config = egl_context->m_config; m_supports_surfaceless = egl_context->m_supports_surfaceless; m_is_shared = true; - m_has_handle = false; - if (egl_context->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (egl_context->GetMode() == Mode::OpenGL) eglBindAPI(EGL_OPENGL_API); else eglBindAPI(EGL_OPENGL_ES_API); - egl_ctx = - eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, egl_context->m_attribs.data()); - if (!egl_ctx) + m_egl_context = eglCreateContext(m_egl_display, m_config, egl_context->m_egl_context, + egl_context->m_attribs.data()); + if (!m_egl_context) { INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x", eglGetError()); return false; @@ -329,13 +326,13 @@ bool cInterfaceEGL::Create(cInterfaceBase* main_context) return true; } -bool cInterfaceEGL::CreateWindowSurface() +bool GLContextEGL::CreateWindowSurface() { - if (m_has_handle) + if (m_host_window) { - EGLNativeWindowType native_window = InitializePlatform(m_host_window, m_config); - egl_surf = eglCreateWindowSurface(egl_dpy, m_config, native_window, nullptr); - if (!egl_surf) + EGLNativeWindowType native_window = GetEGLNativeWindow(m_config); + m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, native_window, nullptr); + if (!m_egl_surface) { INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed"); return false; @@ -346,8 +343,8 @@ bool cInterfaceEGL::CreateWindowSurface() EGLint attrib_list[] = { EGL_NONE, }; - egl_surf = eglCreatePbufferSurface(egl_dpy, m_config, attrib_list); - if (!egl_surf) + m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_config, attrib_list); + if (!m_egl_surface) { INFO_LOG(VIDEO, "Error: eglCreatePbufferSurface failed"); return false; @@ -355,56 +352,50 @@ bool cInterfaceEGL::CreateWindowSurface() } else { - egl_surf = EGL_NO_SURFACE; + m_egl_surface = EGL_NO_SURFACE; } return true; } -void cInterfaceEGL::DestroyWindowSurface() +void GLContextEGL::DestroyWindowSurface() { - if (egl_surf != EGL_NO_SURFACE && !eglDestroySurface(egl_dpy, egl_surf)) + if (m_egl_surface != EGL_NO_SURFACE && !eglDestroySurface(m_egl_display, m_egl_surface)) NOTICE_LOG(VIDEO, "Could not destroy window surface."); - egl_surf = EGL_NO_SURFACE; + m_egl_surface = EGL_NO_SURFACE; } -bool cInterfaceEGL::MakeCurrent() +bool GLContextEGL::MakeCurrent() { - return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx); + return eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context); } -void cInterfaceEGL::UpdateHandle(void* window_handle) -{ - m_host_window = (EGLNativeWindowType)window_handle; - m_has_handle = !!window_handle; -} - -void cInterfaceEGL::UpdateSurface() +void GLContextEGL::UpdateSurface(void* window_handle) { + m_host_window = window_handle; ClearCurrent(); DestroyWindowSurface(); CreateWindowSurface(); MakeCurrent(); } -bool cInterfaceEGL::ClearCurrent() +bool GLContextEGL::ClearCurrent() { - return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + return eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } // Close backend -void cInterfaceEGL::Shutdown() +void GLContextEGL::Shutdown() { - ShutdownPlatform(); - if (egl_ctx) + if (m_egl_context) { - if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) + if (!eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context)) NOTICE_LOG(VIDEO, "Could not release drawing context."); - eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!eglDestroyContext(egl_dpy, egl_ctx)) + eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!eglDestroyContext(m_egl_display, m_egl_context)) NOTICE_LOG(VIDEO, "Could not destroy drawing context."); DestroyWindowSurface(); - if (!m_is_shared && !eglTerminate(egl_dpy)) + if (!m_is_shared && !eglTerminate(m_egl_display)) NOTICE_LOG(VIDEO, "Could not destroy display connection."); - egl_ctx = nullptr; + m_egl_context = nullptr; } } diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index 79c623c942..49abd63cc1 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -9,44 +9,46 @@ #include #include -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" -class cInterfaceEGL : public cInterfaceBase +class GLContextEGL : public GLContext { -private: - EGLConfig m_config; - bool m_has_handle; - EGLNativeWindowType m_host_window; - bool m_supports_surfaceless = false; - std::vector m_attribs; +public: + virtual ~GLContextEGL(); + + bool IsHeadless() const override; + + std::unique_ptr CreateSharedContext() override; + virtual void Shutdown() override; + + bool MakeCurrent() override; + bool ClearCurrent() override; + + void UpdateSurface(void* window_handle) override; + + void Swap() override; + void SwapInterval(int interval) override; + + void* GetFuncAddress(const std::string& name) override; + +protected: + virtual EGLDisplay OpenEGLDisplay(); + virtual EGLNativeWindowType GetEGLNativeWindow(EGLConfig config); + + bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(GLContext* main_context) override; bool CreateWindowSurface(); void DestroyWindowSurface(); + void DetectMode(bool has_handle); -protected: - void DetectMode(); - EGLSurface egl_surf; - EGLContext egl_ctx; - EGLDisplay egl_dpy; + void* m_host_window = nullptr; - virtual EGLDisplay OpenDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); } - virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) - { - return (EGLNativeWindowType)EGL_DEFAULT_DISPLAY; - } - virtual void ShutdownPlatform() {} + EGLConfig m_config; + bool m_supports_surfaceless = false; + std::vector m_attribs; -public: - void Swap() override; - void SwapInterval(int interval) override; - void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; } - 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; - void UpdateHandle(void* window_handle) override; - void UpdateSurface() override; - std::unique_ptr CreateSharedContext() override; + EGLSurface m_egl_surface; + EGLContext m_egl_context; + EGLDisplay m_egl_display; }; diff --git a/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp b/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp index 44fb41f1d2..2a5123b21f 100644 --- a/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp +++ b/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp @@ -3,26 +3,19 @@ // Refer to the license.txt file included. #include "Common/GL/GLInterface/EGLAndroid.h" +#include -EGLDisplay cInterfaceEGLAndroid::OpenDisplay() +EGLDisplay GLContextEGLAndroid::OpenEGLDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); } -EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) +EGLNativeWindowType GLContextEGLAndroid::GetEGLNativeWindow(EGLConfig config) { EGLint format; - eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format); - ANativeWindow_setBuffersGeometry(host_window, 0, 0, format); - - const int width = ANativeWindow_getWidth(host_window); - const int height = ANativeWindow_getHeight(host_window); - GLInterface->SetBackBufferDimensions(width, height); - - return host_window; -} - -void cInterfaceEGLAndroid::ShutdownPlatform() -{ + eglGetConfigAttrib(m_egl_display, config, EGL_NATIVE_VISUAL_ID, &format); + ANativeWindow_setBuffersGeometry(static_cast(m_host_window), 0, 0, format); + m_backbuffer_width = ANativeWindow_getWidth(static_cast(m_host_window)); + m_backbuffer_height = ANativeWindow_getHeight(static_cast(m_host_window)); + return static_cast(m_host_window); } diff --git a/Source/Core/Common/GL/GLInterface/EGLAndroid.h b/Source/Core/Common/GL/GLInterface/EGLAndroid.h index 8a43f261c9..0139bae91c 100644 --- a/Source/Core/Common/GL/GLInterface/EGLAndroid.h +++ b/Source/Core/Common/GL/GLInterface/EGLAndroid.h @@ -4,14 +4,11 @@ #pragma once -#include #include "Common/GL/GLInterface/EGL.h" -class cInterfaceEGLAndroid : public cInterfaceEGL +class GLContextEGLAndroid : public GLContextEGL { protected: - EGLDisplay OpenDisplay() override; - EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) override; - void ShutdownPlatform() override; + EGLDisplay OpenEGLDisplay() override; + EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override; }; diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.cpp b/Source/Core/Common/GL/GLInterface/EGLX11.cpp index 432f0aa601..58bf3133a8 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.cpp +++ b/Source/Core/Common/GL/GLInterface/EGLX11.cpp @@ -5,41 +5,39 @@ #include "Common/GL/GLInterface/EGLX11.h" #include "Common/Logging/Log.h" -EGLDisplay cInterfaceEGLX11::OpenDisplay() +GLContextEGLX11::~GLContextEGLX11() { - dpy = XOpenDisplay(nullptr); - XWindow.Initialize(dpy); - return eglGetDisplay(dpy); + if (m_display) + XCloseDisplay(m_display); } -EGLNativeWindowType cInterfaceEGLX11::InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) +EGLDisplay GLContextEGLX11::OpenEGLDisplay() +{ + if (!m_display) + m_display = XOpenDisplay(nullptr); + + return eglGetDisplay(m_display); +} + +EGLNativeWindowType GLContextEGLX11::GetEGLNativeWindow(EGLConfig config) { EGLint vid; - eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid); + eglGetConfigAttrib(m_egl_display, config, EGL_NATIVE_VISUAL_ID, &vid); - XVisualInfo visTemplate; + XVisualInfo visTemplate = {}; visTemplate.visualid = vid; - XVisualInfo* vi; int nVisuals; - vi = XGetVisualInfo(dpy, VisualIDMask, &visTemplate, &nVisuals); + XVisualInfo* vi = XGetVisualInfo(m_display, VisualIDMask, &visTemplate, &nVisuals); - XWindowAttributes attribs; - if (!XGetWindowAttributes(dpy, (Window)host_window, &attribs)) - { - ERROR_LOG(VIDEO, "Window attribute retrieval failed"); - return 0; - } + if (m_x_window) + m_x_window.reset(); - s_backbuffer_width = attribs.width; - s_backbuffer_height = attribs.height; + m_x_window = GLX11Window::Create(m_display, reinterpret_cast(m_host_window), vi); + m_backbuffer_width = m_x_window->GetWidth(); + m_backbuffer_height = m_x_window->GetHeight(); - return (EGLNativeWindowType)XWindow.CreateXWindow((Window)host_window, vi); -} - -void cInterfaceEGLX11::ShutdownPlatform() -{ - XWindow.DestroyXWindow(); - XCloseDisplay(dpy); + XFree(vi); + + return reinterpret_cast(m_x_window->GetWindow()); } diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.h b/Source/Core/Common/GL/GLInterface/EGLX11.h index dab5a38d8e..ec0e933ef7 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.h +++ b/Source/Core/Common/GL/GLInterface/EGLX11.h @@ -7,17 +7,17 @@ #include #include "Common/GL/GLInterface/EGL.h" -#include "Common/GL/GLInterface/X11_Util.h" +#include "Common/GL/GLX11Window.h" -class cInterfaceEGLX11 : public cInterfaceEGL +class GLContextEGLX11 : public GLContextEGL { -private: - cX11Window XWindow; - Display* dpy; +public: + ~GLContextEGLX11() override; protected: - EGLDisplay OpenDisplay() override; - EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) override; - void ShutdownPlatform() override; + EGLDisplay OpenEGLDisplay() override; + EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override; + + Display* m_display = nullptr; + std::unique_ptr m_x_window; }; diff --git a/Source/Core/Common/GL/GLInterface/GLInterface.cpp b/Source/Core/Common/GL/GLInterface/GLInterface.cpp deleted file mode 100644 index a6ae0c0991..0000000000 --- a/Source/Core/Common/GL/GLInterface/GLInterface.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include - -#include "Common/GL/GLInterfaceBase.h" - -#if defined(__APPLE__) -#include "Common/GL/GLInterface/AGL.h" -#elif defined(_WIN32) -#include "Common/GL/GLInterface/WGL.h" -#elif HAVE_X11 -#if defined(USE_EGL) && USE_EGL -#include "Common/GL/GLInterface/EGLX11.h" -#else -#include "Common/GL/GLInterface/GLX.h" -#endif -#elif defined(USE_EGL) && USE_EGL && defined(USE_HEADLESS) -#include "Common/GL/GLInterface/EGL.h" -#elif ANDROID -#include "Common/GL/GLInterface/EGLAndroid.h" -#error Platform doesnt have a GLInterface -#endif - -std::unique_ptr HostGL_CreateGLInterface() -{ -#if defined(__APPLE__) - return std::make_unique(); -#elif defined(_WIN32) - return std::make_unique(); -#elif defined(USE_EGL) && defined(USE_HEADLESS) - return std::make_unique(); -#elif defined(HAVE_X11) && HAVE_X11 -#if defined(USE_EGL) && USE_EGL - return std::make_unique(); -#else - return std::make_unique(); -#endif -#elif ANDROID - return std::make_unique(); -#else - return nullptr; -#endif -} 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 { - std::unique_ptr context = std::make_unique(); - if (!context->Create(this)) + 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; } -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) + m_render_window.reset(); + if (m_supports_pbuffer && m_pbuffer) { - XWindow.DestroyXWindow(); - } - else 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; } } } diff --git a/Source/Core/Common/GL/GLInterface/GLX.h b/Source/Core/Common/GL/GLInterface/GLX.h index 724dca5141..42e36f863f 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.h +++ b/Source/Core/Common/GL/GLInterface/GLX.h @@ -10,35 +10,39 @@ #include #include -#include "Common/GL/GLInterface/X11_Util.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" +#include "Common/GL/GLX11Window.h" -class cInterfaceGLX : public cInterfaceBase +class GLContextGLX : public GLContext { -private: - Window m_host_window; - cX11Window XWindow; - Display* dpy; - Window win; - GLXContext ctx; - GLXFBConfig fbconfig; - bool m_has_handle; +public: + bool IsHeadless() const override; + + std::unique_ptr CreateSharedContext() override; + void Shutdown() override; + + bool MakeCurrent() override; + bool ClearCurrent() override; + + void SwapInterval(int Interval) override; + void Swap() override; + + void* GetFuncAddress(const std::string& name) override; + +protected: + bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(GLContext* main_context) override; + + Display* m_display = nullptr; + std::unique_ptr m_render_window; + + GLXDrawable m_drawable = {}; + GLXContext m_context = {}; + GLXFBConfig m_fbconfig = {}; bool m_supports_pbuffer = false; GLXPbufferSGIX m_pbuffer = 0; std::vector m_attribs; - bool CreateWindowSurface(); + bool CreateWindowSurface(Window window_handle); void DestroyWindowSurface(); - -public: - friend class cX11Window; - void SwapInterval(int Interval) override; - 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 CreateSharedContext() override; }; diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp index 48f4b8c96c..d7c8c87c4f 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ b/Source/Core/Common/GL/GLInterface/WGL.cpp @@ -130,8 +130,8 @@ static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = nullptr; static void LoadWGLExtensions() { - wglSwapIntervalEXT = reinterpret_cast( - GLInterface->GetFuncAddress("wglSwapIntervalEXT")); + wglSwapIntervalEXT = + reinterpret_cast(wglGetProcAddress("wglSwapIntervalEXT")); wglCreateContextAttribsARB = reinterpret_cast( wglGetProcAddress("wglCreateContextAttribsARB")); wglChoosePixelFormatARB = reinterpret_cast( @@ -157,19 +157,24 @@ static void ClearWGLExtensionPointers() wglDestroyPbufferARB = nullptr; } -void cInterfaceWGL::SwapInterval(int Interval) +bool GLContextWGL::IsHeadless() const +{ + return !m_window_handle; +} + +void GLContextWGL::SwapInterval(int interval) { if (wglSwapIntervalEXT) - wglSwapIntervalEXT(Interval); + wglSwapIntervalEXT(interval); else ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); } -void cInterfaceWGL::Swap() +void GLContextWGL::Swap() { SwapBuffers(m_dc); } -void* cInterfaceWGL::GetFuncAddress(const std::string& name) +void* GLContextWGL::GetFuncAddress(const std::string& name) { FARPROC func = wglGetProcAddress(name.c_str()); if (func == nullptr) @@ -183,24 +188,9 @@ void* cInterfaceWGL::GetFuncAddress(const std::string& name) return func; } -// Draw messages on top of the screen -bool cInterfaceWGL::PeekMessages() -{ - // TODO: peekmessage - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - return FALSE; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return TRUE; -} - // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) +bool GLContextWGL::Initialize(void* window_handle, bool stereo, bool core) { if (!window_handle) return false; @@ -216,8 +206,8 @@ bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) // Control window size and picture scaling int twidth = window_rect.right - window_rect.left; int theight = window_rect.bottom - window_rect.top; - s_backbuffer_width = twidth; - s_backbuffer_height = theight; + m_backbuffer_width = twidth; + m_backbuffer_height = theight; const DWORD stereo_flag = stereo ? PFD_STEREO : 0; @@ -274,8 +264,7 @@ bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) } // WGL only supports desktop GL, for now. - if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + m_opengl_mode = Mode::OpenGL; if (core) { @@ -306,7 +295,7 @@ bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) { wglDeleteContext(m_rc); m_rc = core_context; - m_core = true; + m_is_core_context = true; } else { @@ -317,9 +306,11 @@ bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) return true; } -bool cInterfaceWGL::Create(cInterfaceBase* main_context) +bool GLContextWGL::Initialize(GLContext* main_context) { - cInterfaceWGL* wgl_main_context = static_cast(main_context); + GLContextWGL* wgl_main_context = static_cast(main_context); + + m_opengl_mode = wgl_main_context->m_opengl_mode; // WGL does not support surfaceless contexts, so we use a 1x1 pbuffer instead. if (!CreatePBuffer(wgl_main_context->m_dc, 1, 1, &m_pbuffer_handle, &m_dc)) @@ -329,14 +320,14 @@ bool cInterfaceWGL::Create(cInterfaceBase* main_context) if (!m_rc) return false; - m_core = true; + m_is_core_context = true; return true; } -std::unique_ptr cInterfaceWGL::CreateSharedContext() +std::unique_ptr GLContextWGL::CreateSharedContext() { - std::unique_ptr context = std::make_unique(); - if (!context->Create(this)) + std::unique_ptr context = std::make_unique(); + if (!context->Initialize(this)) { context->Shutdown(); return nullptr; @@ -345,7 +336,7 @@ std::unique_ptr cInterfaceWGL::CreateSharedContext() return std::move(context); } -HGLRC cInterfaceWGL::CreateCoreContext(HDC dc, HGLRC share_context) +HGLRC GLContextWGL::CreateCoreContext(HDC dc, HGLRC share_context) { if (!wglCreateContextAttribsARB) { @@ -402,8 +393,8 @@ HGLRC cInterfaceWGL::CreateCoreContext(HDC dc, HGLRC share_context) return nullptr; } -bool cInterfaceWGL::CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, - HDC* pbuffer_dc) +bool GLContextWGL::CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, + HDC* pbuffer_dc) { if (!wglChoosePixelFormatARB || !wglCreatePbufferARB || !wglGetPbufferDCARB || !wglReleasePbufferDCARB || !wglDestroyPbufferARB) @@ -462,29 +453,29 @@ bool cInterfaceWGL::CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE return true; } -bool cInterfaceWGL::MakeCurrent() +bool GLContextWGL::MakeCurrent() { return wglMakeCurrent(m_dc, m_rc) == TRUE; } -bool cInterfaceWGL::ClearCurrent() +bool GLContextWGL::ClearCurrent() { return wglMakeCurrent(m_dc, nullptr) == TRUE; } // Update window width, size and etc. Called from Render.cpp -void cInterfaceWGL::Update() +void GLContextWGL::Update() { RECT rcWindow; GetClientRect(m_window_handle, &rcWindow); // Get the new window width and height - s_backbuffer_width = rcWindow.right - rcWindow.left; - s_backbuffer_height = rcWindow.bottom - rcWindow.top; + m_backbuffer_width = rcWindow.right - rcWindow.left; + m_backbuffer_height = rcWindow.bottom - rcWindow.top; } // Close backend -void cInterfaceWGL::Shutdown() +void GLContextWGL::Shutdown() { if (m_rc) { diff --git a/Source/Core/Common/GL/GLInterface/WGL.h b/Source/Core/Common/GL/GLInterface/WGL.h index efa9655713..7e74470866 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.h +++ b/Source/Core/Common/GL/GLInterface/WGL.h @@ -6,26 +6,30 @@ #include #include -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" -class cInterfaceWGL : public cInterfaceBase +class GLContextWGL : public GLContext { public: - void SwapInterval(int interval) override; - 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 IsHeadless() const; + + std::unique_ptr CreateSharedContext() override; + bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; void Update() override; - bool PeekMessages() override; - std::unique_ptr CreateSharedContext() override; + void Swap() override; + void SwapInterval(int interval) override; + + void* GetFuncAddress(const std::string& name) override; + +protected: + bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(GLContext* main_context) override; -private: static HGLRC CreateCoreContext(HDC dc, HGLRC share_context); static bool CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, HDC* pbuffer_dc); diff --git a/Source/Core/Common/GL/GLInterface/X11_Util.cpp b/Source/Core/Common/GL/GLInterface/X11_Util.cpp deleted file mode 100644 index ed884a9ffd..0000000000 --- a/Source/Core/Common/GL/GLInterface/X11_Util.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "Common/GL/GLInterface/X11_Util.h" -#include "Common/GL/GLInterfaceBase.h" -#include "Common/Logging/Log.h" -#include "Common/Thread.h" - -void cX11Window::Initialize(Display* _dpy) -{ - dpy = _dpy; -} - -Window cX11Window::CreateXWindow(Window parent, XVisualInfo* vi) -{ - XSetWindowAttributes attr; - - colormap = XCreateColormap(dpy, parent, vi->visual, AllocNone); - - // Setup window attributes - attr.colormap = colormap; - - XWindowAttributes attribs; - if (!XGetWindowAttributes(dpy, parent, &attribs)) - { - ERROR_LOG(VIDEO, "Window attribute retrieval failed"); - return 0; - } - - // Create the window - win = XCreateWindow(dpy, parent, 0, 0, attribs.width, attribs.height, 0, vi->depth, InputOutput, - vi->visual, CWColormap, &attr); - XSelectInput(dpy, parent, StructureNotifyMask); - XMapWindow(dpy, win); - XSync(dpy, True); - - xEventThread = std::thread(&cX11Window::XEventThread, this); - - return win; -} - -void cX11Window::DestroyXWindow(void) -{ - XUnmapWindow(dpy, win); - win = 0; - if (xEventThread.joinable()) - xEventThread.join(); - XFreeColormap(dpy, colormap); -} - -void cX11Window::XEventThread() -{ - while (win) - { - XEvent event; - for (int num_events = XPending(dpy); num_events > 0; num_events--) - { - XNextEvent(dpy, &event); - switch (event.type) - { - case ConfigureNotify: - XResizeWindow(dpy, win, event.xconfigure.width, event.xconfigure.height); - GLInterface->SetBackBufferDimensions(event.xconfigure.width, event.xconfigure.height); - break; - default: - break; - } - } - Common::SleepCurrentThread(20); - } -} diff --git a/Source/Core/Common/GL/GLInterface/X11_Util.h b/Source/Core/Common/GL/GLInterface/X11_Util.h deleted file mode 100644 index e79a6fe1df..0000000000 --- a/Source/Core/Common/GL/GLInterface/X11_Util.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include - -class cX11Window -{ -private: - void XEventThread(); - std::thread xEventThread; - Colormap colormap; - -public: - void Initialize(Display* dpy); - Window CreateXWindow(Window parent, XVisualInfo* vi); - void DestroyXWindow(); - - Display* dpy; - Window win; -}; diff --git a/Source/Core/Common/GL/GLInterfaceBase.h b/Source/Core/Common/GL/GLInterfaceBase.h deleted file mode 100644 index 4ffb7f5f53..0000000000 --- a/Source/Core/Common/GL/GLInterfaceBase.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include -#include - -#include "Common/CommonTypes.h" - -enum class GLInterfaceMode -{ - MODE_DETECT, - MODE_OPENGL, - MODE_OPENGLES2, - MODE_OPENGLES3, -}; - -class cInterfaceBase -{ -protected: - // Window dimensions. - u32 s_backbuffer_width = 0; - u32 s_backbuffer_height = 0; - bool m_core = false; - bool m_is_shared = false; - - GLInterfaceMode s_opengl_mode = GLInterfaceMode::MODE_DETECT; - -public: - virtual ~cInterfaceBase() {} - virtual void Swap() {} - virtual void SetMode(GLInterfaceMode mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; } - virtual GLInterfaceMode GetMode() { return s_opengl_mode; } - virtual void* GetFuncAddress(const std::string& name) { return nullptr; } - virtual bool Create(void* window_handle, bool stereo = false, bool core = true) { return true; } - virtual bool Create(cInterfaceBase* main_context) { return true; } - virtual bool MakeCurrent() { return true; } - virtual bool ClearCurrent() { return true; } - virtual void Shutdown() {} - virtual void SwapInterval(int Interval) {} - virtual u32 GetBackBufferWidth() { return s_backbuffer_width; } - virtual u32 GetBackBufferHeight() { return s_backbuffer_height; } - virtual void SetBackBufferDimensions(u32 W, u32 H) - { - s_backbuffer_width = W; - s_backbuffer_height = H; - } - virtual void Update() {} - virtual bool PeekMessages() { return false; } - virtual void UpdateHandle(void* window_handle) {} - virtual void UpdateSurface() {} - virtual std::unique_ptr CreateSharedContext() { return nullptr; } -}; - -extern std::unique_ptr GLInterface; - -// This function has to be defined along the Host_ functions from Core/Host.h. -// Current canonical implementation: DolphinWX/GLInterface/GLInterface.cpp. -std::unique_ptr HostGL_CreateGLInterface(); diff --git a/Source/Core/Common/GL/GLUtil.cpp b/Source/Core/Common/GL/GLUtil.cpp index 02a38d8654..729cc2c25d 100644 --- a/Source/Core/Common/GL/GLUtil.cpp +++ b/Source/Core/Common/GL/GLUtil.cpp @@ -5,19 +5,12 @@ #include #include "Common/Assert.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/Logging/Log.h" -std::unique_ptr GLInterface; - namespace GLUtil { -void InitInterface() -{ - GLInterface = HostGL_CreateGLInterface(); -} - GLuint CompileProgram(const std::string& vertexShader, const std::string& fragmentShader) { // generate objects @@ -107,7 +100,7 @@ void EnablePrimitiveRestart() { constexpr GLuint PRIMITIVE_RESTART_INDEX = 65535; - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES) { glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); } @@ -125,4 +118,4 @@ void EnablePrimitiveRestart() } } } -} +} // namespace GLUtil diff --git a/Source/Core/Common/GL/GLUtil.h b/Source/Core/Common/GL/GLUtil.h index d4714026f0..62605585f3 100644 --- a/Source/Core/Common/GL/GLUtil.h +++ b/Source/Core/Common/GL/GLUtil.h @@ -10,7 +10,6 @@ namespace GLUtil { -void InitInterface(); GLuint CompileProgram(const std::string& vertexShader, const std::string& fragmentShader); void EnablePrimitiveRestart(); -} +} // namespace GLUtil diff --git a/Source/Core/Common/GL/GLX11Window.cpp b/Source/Core/Common/GL/GLX11Window.cpp new file mode 100644 index 0000000000..793939377d --- /dev/null +++ b/Source/Core/Common/GL/GLX11Window.cpp @@ -0,0 +1,77 @@ +// Copyright 2012 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Common/GL/GLX11Window.h" +#include "Common/GL/GLContext.h" +#include "Common/Thread.h" + +GLX11Window::GLX11Window(Display* display, Window parent_window, Colormap color_map, Window window, + int width, int height) + : m_display(display), m_parent_window(parent_window), m_color_map(color_map), m_window(window), + m_width(width), m_height(height), + m_event_thread(std::thread(&GLX11Window::XEventThread, this)) +{ +} + +GLX11Window::~GLX11Window() +{ + Window window = m_window; + m_window = None; + if (m_event_thread.joinable()) + m_event_thread.join(); + XUnmapWindow(m_display, window); + XDestroyWindow(m_display, window); + XFreeColormap(m_display, m_color_map); +} + +std::unique_ptr GLX11Window::Create(Display* display, Window parent_window, + XVisualInfo* vi) +{ + // Set color map for the new window based on the visual. + Colormap color_map = XCreateColormap(display, parent_window, vi->visual, AllocNone); + XSetWindowAttributes attribs = {}; + attribs.colormap = color_map; + + // Get the dimensions from the parent window. + XWindowAttributes parent_attribs = {}; + XGetWindowAttributes(display, parent_window, &parent_attribs); + + // Create the window + Window window = + XCreateWindow(display, parent_window, 0, 0, parent_attribs.width, parent_attribs.height, 0, + vi->depth, InputOutput, vi->visual, CWColormap, &attribs); + XSelectInput(display, parent_window, StructureNotifyMask); + XMapWindow(display, window); + XSync(display, True); + + return std::make_unique(display, parent_window, color_map, window, + parent_attribs.width, parent_attribs.height); +} + +void GLX11Window::XEventThread() +{ + // There's a potential race here on m_window. But this thread will disappear soon. + while (m_window) + { + XEvent event; + for (int num_events = XPending(m_display); num_events > 0; num_events--) + { + XNextEvent(m_display, &event); + switch (event.type) + { + case ConfigureNotify: + { + m_width = event.xconfigure.width; + m_height = event.xconfigure.height; + XResizeWindow(m_display, m_window, m_width, m_height); + g_main_gl_context->SetBackBufferDimensions(m_width, m_height); + } + break; + default: + break; + } + } + Common::SleepCurrentThread(20); + } +} diff --git a/Source/Core/Common/GL/GLX11Window.h b/Source/Core/Common/GL/GLX11Window.h new file mode 100644 index 0000000000..15c183c7cf --- /dev/null +++ b/Source/Core/Common/GL/GLX11Window.h @@ -0,0 +1,41 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include + +class GLX11Window +{ +public: + GLX11Window(Display* display, Window parent_window, Colormap color_map, Window window, int width, + int height); + ~GLX11Window(); + + Display* GetDisplay() const { return m_display; } + Window GetParentWindow() const { return m_parent_window; } + Window GetWindow() const { return m_window; } + int GetWidth() const { return m_width; } + int GetHeight() const { return m_height; } + + static std::unique_ptr Create(Display* display, Window parent_window, + XVisualInfo* vi); + +private: + void XEventThread(); + + Display* m_display; + Window m_parent_window; + Colormap m_color_map; + Window m_window; + + int m_width; + int m_height; + + std::thread m_event_thread; +}; diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index a6cccdaaa2..1c1c976f70 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -9,7 +9,7 @@ #include "Common/Common.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" @@ -414,7 +414,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glBindBuffer(GL_ARRAY_BUFFER, static_cast(g_vertex_manager.get())->GetVertexBufferHandle()); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (!g_main_gl_context->IsGLES()) glEnable(GL_PROGRAM_POINT_SIZE); } diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index 1efb650eeb..fbe7f576c7 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -4,7 +4,6 @@ #include "Common/Assert.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" #include "Common/MsgHandler.h" #include "VideoBackends/OGL/FramebufferManager.h" diff --git a/Source/Core/VideoBackends/OGL/PerfQuery.cpp b/Source/Core/VideoBackends/OGL/PerfQuery.cpp index b3b5df2265..30a6e1781b 100644 --- a/Source/Core/VideoBackends/OGL/PerfQuery.cpp +++ b/Source/Core/VideoBackends/OGL/PerfQuery.cpp @@ -6,7 +6,7 @@ #include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "VideoBackends/OGL/PerfQuery.h" @@ -17,11 +17,10 @@ namespace OGL { std::unique_ptr GetPerfQuery() { - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3 && - GLExtensions::Supports("GL_NV_occlusion_query_samples")) + if (g_main_gl_context->IsGLES() && GLExtensions::Supports("GL_NV_occlusion_query_samples")) return std::make_unique(); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context->IsGLES()) return std::make_unique(GL_ANY_SAMPLES_PASSED); return std::make_unique(GL_SAMPLES_PASSED); @@ -266,4 +265,4 @@ void PerfQueryGLESNV::FlushResults() FlushOne(); } -} // namespace +} // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 2d284ae4ef..ae930dddab 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -12,7 +12,7 @@ #include "Common/Assert.h" #include "Common/CommonTypes.h" #include "Common/FileUtil.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" @@ -805,7 +805,7 @@ void ProgramShaderCache::CreateHeader() bool SharedContextAsyncShaderCompiler::WorkerThreadInitMainThread(void** param) { - std::unique_ptr context = GLInterface->CreateSharedContext(); + std::unique_ptr context = g_main_gl_context->CreateSharedContext(); if (!context) { PanicAlert("Failed to create shared context for shader compiling."); @@ -818,7 +818,7 @@ bool SharedContextAsyncShaderCompiler::WorkerThreadInitMainThread(void** param) bool SharedContextAsyncShaderCompiler::WorkerThreadInitWorkerThread(void* param) { - cInterfaceBase* context = static_cast(param); + GLContext* context = static_cast(param); if (!context->MakeCurrent()) return false; @@ -831,7 +831,7 @@ bool SharedContextAsyncShaderCompiler::WorkerThreadInitWorkerThread(void* param) void SharedContextAsyncShaderCompiler::WorkerThreadExit(void* param) { - cInterfaceBase* context = static_cast(param); + GLContext* context = static_cast(param); context->ClearCurrent(); delete context; } diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 27113a6b8b..18f9fbf322 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -16,7 +16,7 @@ #include "Common/Assert.h" #include "Common/Atomic.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/Logging/LogManager.h" #include "Common/MathUtil.h" @@ -354,8 +354,8 @@ static void InitDriverInfo() // Init functions Renderer::Renderer() - : ::Renderer(static_cast(std::max(GLInterface->GetBackBufferWidth(), 1u)), - static_cast(std::max(GLInterface->GetBackBufferHeight(), 1u))) + : ::Renderer(static_cast(std::max(g_main_gl_context->GetBackBufferWidth(), 1u)), + static_cast(std::max(g_main_gl_context->GetBackBufferHeight(), 1u))) { bool bSuccess = true; @@ -365,7 +365,7 @@ Renderer::Renderer() InitDriverInfo(); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (!g_main_gl_context->IsGLES()) { if (!GLExtensions::Supports("GL_ARB_framebuffer_object")) { @@ -500,7 +500,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsBPTCTextures = GLExtensions::Supports("GL_ARB_texture_compression_bptc"); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context->IsGLES()) { g_ogl_config.SupportedESPointSize = GLExtensions::Supports("GL_OES_geometry_point_size") ? @@ -730,10 +730,9 @@ Renderer::Renderer() if (!g_ogl_config.bSupportsGLBufferStorage && !g_ogl_config.bSupportsGLPinnedMemory) { - OSD::AddMessage( - StringFromFormat("Your OpenGL driver does not support %s_buffer_storage.", - GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3 ? "EXT" : "ARB"), - 60000); + OSD::AddMessage(StringFromFormat("Your OpenGL driver does not support %s_buffer_storage.", + g_main_gl_context->IsGLES() ? "EXT" : "ARB"), + 60000); OSD::AddMessage("This device's performance will be terrible.", 60000); OSD::AddMessage("Please ask your device vendor for an updated OpenGL driver.", 60000); } @@ -761,7 +760,7 @@ Renderer::Renderer() // Handle VSync on/off s_vsync = g_ActiveConfig.IsVSync(); if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_VSYNC)) - GLInterface->SwapInterval(s_vsync); + g_main_gl_context->SwapInterval(s_vsync); // Because of the fixed framebuffer size we need to disable the resolution // options while running @@ -1044,7 +1043,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) std::unique_ptr colorMap(new u32[targetPixelRcWidth * targetPixelRcHeight]); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context->IsGLES()) // XXX: Swap colours glReadPixels(targetPixelRc.left, targetPixelRc.bottom, targetPixelRcWidth, targetPixelRcHeight, GL_RGBA, GL_UNSIGNED_BYTE, colorMap.get()); @@ -1351,7 +1350,7 @@ void Renderer::ApplyBlendingState(const BlendingState state, bool force) GL_XOR, GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET}; - if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL) + if (g_main_gl_context->IsGLES()) { // Logic ops aren't available in GLES3 } @@ -1421,7 +1420,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region OSD::DrawMessages(); // Swap the back and front buffers, presenting the image. - GLInterface->Swap(); + g_main_gl_context->Swap(); } else { @@ -1466,7 +1465,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region { s_vsync = g_ActiveConfig.IsVSync(); if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_VSYNC)) - GLInterface->SwapInterval(s_vsync); + g_main_gl_context->SwapInterval(s_vsync); } // Clean out old stuff from caches. It's not worth it to clean out the shader caches. @@ -1502,12 +1501,11 @@ void Renderer::CheckForSurfaceChange() m_surface_handle = m_new_surface_handle; m_new_surface_handle = nullptr; - GLInterface->UpdateHandle(m_surface_handle); - GLInterface->UpdateSurface(); + g_main_gl_context->UpdateSurface(m_surface_handle); // With a surface change, the window likely has new dimensions. - m_backbuffer_width = GLInterface->GetBackBufferWidth(); - m_backbuffer_height = GLInterface->GetBackBufferHeight(); + m_backbuffer_width = g_main_gl_context->GetBackBufferWidth(); + m_backbuffer_height = g_main_gl_context->GetBackBufferHeight(); } void Renderer::CheckForSurfaceResize() @@ -1515,7 +1513,7 @@ void Renderer::CheckForSurfaceResize() if (!m_surface_resized.TestAndClear()) return; - GLInterface->Update(); + g_main_gl_context->Update(); m_backbuffer_width = m_new_backbuffer_width; m_backbuffer_height = m_new_backbuffer_height; } @@ -1538,7 +1536,7 @@ void Renderer::ResetAPIState() glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_BLEND); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (!g_main_gl_context->IsGLES()) glDisable(GL_COLOR_LOGIC_OP); if (g_ActiveConfig.backend_info.bSupportsDepthClamp) { @@ -1717,4 +1715,4 @@ std::unique_ptr Renderer::CreateAsyncShaderCom { return std::make_unique(); } -} +} // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/SamplerCache.cpp b/Source/Core/VideoBackends/OGL/SamplerCache.cpp index 32be0ac4d9..ae848e8d29 100644 --- a/Source/Core/VideoBackends/OGL/SamplerCache.cpp +++ b/Source/Core/VideoBackends/OGL/SamplerCache.cpp @@ -7,7 +7,7 @@ #include #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "VideoCommon/SamplerCommon.h" #include "VideoCommon/VideoConfig.h" @@ -99,7 +99,7 @@ void SamplerCache::SetParameters(GLuint sampler_id, const SamplerState& params) glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, params.min_lod / 16.f); glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, params.max_lod / 16.f); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (!g_main_gl_context->IsGLES()) glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, params.lod_bias / 256.f); if (params.anisotropic_filtering && g_ogl_config.bSupportsAniso) @@ -117,4 +117,4 @@ void SamplerCache::Clear() p.second = 0; m_cache.clear(); } -} +} // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 95a3d30e1a..10f191448e 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -10,7 +10,6 @@ #include #include "Common/Assert.h" -#include "Common/GL/GLInterfaceBase.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index d2e37f07a9..130669c28e 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -39,7 +39,7 @@ Make AA apply instantly during gameplay if possible #include #include "Common/Common.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/MsgHandler.h" @@ -66,7 +66,7 @@ std::string VideoBackend::GetName() const std::string VideoBackend::GetDisplayName() const { - if (GLInterface != nullptr && GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context && g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES) return _trans("OpenGL ES"); else return _trans("OpenGL"); @@ -161,12 +161,12 @@ bool VideoBackend::Initialize(void* window_handle) { InitializeShared(); - GLUtil::InitInterface(); - GLInterface->SetMode(GLInterfaceMode::MODE_DETECT); - if (!GLInterface->Create(window_handle, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer)) + g_main_gl_context = + GLContext::Create(window_handle, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); + if (!g_main_gl_context) return false; - GLInterface->MakeCurrent(); + g_main_gl_context->MakeCurrent(); if (!InitializeGLExtensions() || !FillBackendInfo()) return false; @@ -196,9 +196,9 @@ void VideoBackend::Shutdown() g_perf_query.reset(); g_vertex_manager.reset(); g_renderer.reset(); - GLInterface->ClearCurrent(); - GLInterface->Shutdown(); - GLInterface.reset(); + g_main_gl_context->ClearCurrent(); + g_main_gl_context->Shutdown(); + g_main_gl_context.reset(); ShutdownShared(); } -} +} // namespace OGL diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index 695f58cc1d..dd390bc6dc 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -4,7 +4,7 @@ #include -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/Logging/Log.h" @@ -15,9 +15,8 @@ std::unique_ptr SWOGLWindow::s_instance; void SWOGLWindow::Init(void* window_handle) { - GLUtil::InitInterface(); - GLInterface->SetMode(GLInterfaceMode::MODE_DETECT); - if (!GLInterface->Create(window_handle)) + g_main_gl_context = GLContext::Create(window_handle); + if (!g_main_gl_context) { ERROR_LOG(VIDEO, "GLInterface::Create failed."); } @@ -27,8 +26,8 @@ void SWOGLWindow::Init(void* window_handle) void SWOGLWindow::Shutdown() { - GLInterface->Shutdown(); - GLInterface.reset(); + g_main_gl_context->Shutdown(); + g_main_gl_context.reset(); s_instance.reset(); } @@ -66,10 +65,9 @@ void SWOGLWindow::Prepare() " TexCoord = vec2(rawpos.x, -rawpos.y);\n" "}\n"; - std::string header = GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL ? - "#version 140\n" : - "#version 300 es\n" - "precision highp float;\n"; + std::string header = g_main_gl_context->IsGLES() ? "#version 300 es\n" + "precision highp float;\n" : + "#version 140\n"; m_image_program = GLUtil::CompileProgram(header + vertex_shader, header + frag_shader); @@ -93,10 +91,10 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) void SWOGLWindow::ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region) { SW::SWTexture* sw_image = static_cast(image); - GLInterface->Update(); // just updates the render window position and the backbuffer size + g_main_gl_context->Update(); // just updates the render window position and the backbuffer size - GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); - GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight(); + GLsizei glWidth = (GLsizei)g_main_gl_context->GetBackBufferWidth(); + GLsizei glHeight = (GLsizei)g_main_gl_context->GetBackBufferHeight(); glViewport(0, 0, glWidth, glHeight); @@ -123,10 +121,5 @@ void SWOGLWindow::ShowImage(AbstractTexture* image, const EFBRectangle& xfb_regi // } m_text.clear(); - GLInterface->Swap(); -} - -int SWOGLWindow::PeekMessages() -{ - return GLInterface->PeekMessages(); + g_main_gl_context->Swap(); } diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index 64ee2414bc..eadf3171cb 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -26,8 +26,6 @@ public: // Image to show, will be swapped immediately void ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region); - int PeekMessages(); - static std::unique_ptr s_instance; private: diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 6ca183b57c..8781a2da9b 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -9,7 +9,7 @@ #include "Common/Common.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "VideoBackends/Software/Clipper.h" #include "VideoBackends/Software/DebugUtil.h" @@ -88,7 +88,7 @@ bool VideoSoftware::Initialize(void* window_handle) Rasterizer::Init(); DebugUtil::Init(); - GLInterface->MakeCurrent(); + g_main_gl_context->MakeCurrent(); SWOGLWindow::s_instance->Prepare(); g_renderer = std::make_unique(); @@ -116,4 +116,4 @@ void VideoSoftware::Shutdown() g_renderer.reset(); ShutdownShared(); } -} +} // namespace SW diff --git a/Source/UnitTests/StubHost.cpp b/Source/UnitTests/StubHost.cpp index a2ba02c20b..78c81c38f2 100644 --- a/Source/UnitTests/StubHost.cpp +++ b/Source/UnitTests/StubHost.cpp @@ -8,7 +8,6 @@ #include #include -#include "Common/GL/GLInterfaceBase.h" #include "Core/Host.h" void Host_NotifyMapLoaded() @@ -54,7 +53,3 @@ void Host_YieldToUI() void Host_UpdateProgressDialog(const char* caption, int position, int total) { } -std::unique_ptr HostGL_CreateGLInterface() -{ - return nullptr; -}