diff options
| author | Stenzek <stenzek@gmail.com> | 2018-10-03 23:02:45 +1000 |
|---|---|---|
| committer | Stenzek <stenzek@gmail.com> | 2018-10-20 21:11:34 +1000 |
| commit | 134d967be2dd4ba9531abb8ba8494c3ac423ca72 (patch) | |
| tree | 3486a0d8a8f5c1a141bccc1e9cc56306cde327b4 /Source/Core/Common/GL/GLInterface | |
| parent | 74b82bab3b6e4e8a1799bbcbdc5244f20f4d2826 (diff) | |
Refactoring and cleanup of GLInterface (now GLContext)
Diffstat (limited to 'Source/Core/Common/GL/GLInterface')
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/AGL.h | 22 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/AGL.mm | 47 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGL.cpp | 213 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGL.h | 66 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGLAndroid.cpp | 23 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGLAndroid.h | 9 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGLX11.cpp | 46 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGLX11.h | 18 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/GLInterface.cpp | 45 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/GLX.cpp | 142 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/GLX.h | 52 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/WGL.cpp | 75 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/WGL.h | 24 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/X11_Util.cpp | 72 | ||||
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/X11_Util.h | 27 |
15 files changed, 362 insertions, 519 deletions
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<GLContext> CreateSharedContext() override; + void Shutdown() override; + bool MakeCurrent() override; bool ClearCurrent() override; - void Shutdown() override; + void Update() override; + + void Swap() override; void SwapInterval(int interval) override; - std::unique_ptr<cInterfaceBase> CreateSharedContext() override; -private: +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<u32>(size.width * scale); + u32 new_height = static_cast<u32>(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<NSView*>(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<cInterfaceAGL*>(main_context); + GLContextAGL* agl_context = static_cast<GLContextAGL*>(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<cInterfaceBase> cInterfaceAGL::CreateSharedContext() +std::unique_ptr<GLContext> GLContextAGL::CreateSharedContext() { - std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceAGL>(); - if (!context->Create(this)) + std::unique_ptr<GLContextAGL> context = std::make_unique<GLContextAGL>(); + 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<GLint*>(&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); + return m_host_window == nullptr; } -void cInterfaceEGL::SwapInterval(int Interval) + +void GLContextEGL::Swap() { - eglSwapInterval(egl_dpy, Interval); + 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* cInterfaceEGL::GetFuncAddress(const std::string& name) +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<int, 3> renderable_types{{ - EGL_OPENGL_BIT, - (1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */ - EGL_OPENGL_ES2_BIT, - }}; + bool supportsGL = false, supportsGLES3 = false; + std::array<int, 3> 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<EGLNativeWindowType>(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<EGLint> 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<std::pair<int, int>, 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<cInterfaceBase> cInterfaceEGL::CreateSharedContext() +std::unique_ptr<GLContext> GLContextEGL::CreateSharedContext() { - std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceEGL>(); - if (!context->Create(this)) + std::unique_ptr<GLContextEGL> context = std::make_unique<GLContextEGL>(); + 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<cInterfaceEGL*>(main_context); + GLContextEGL* egl_context = static_cast<GLContextEGL*>(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; -} - -bool cInterfaceEGL::MakeCurrent() -{ - return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx); + m_egl_surface = EGL_NO_SURFACE; } -void cInterfaceEGL::UpdateHandle(void* window_handle) +bool GLContextEGL::MakeCurrent() { - m_host_window = (EGLNativeWindowType)window_handle; - m_has_handle = !!window_handle; + return eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context); } -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 <string> #include <vector> -#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<int> m_attribs; +public: + virtual ~GLContextEGL(); - bool CreateWindowSurface(); - void DestroyWindowSurface(); + bool IsHeadless() const override; -protected: - void DetectMode(); - EGLSurface egl_surf; - EGLContext egl_ctx; - EGLDisplay egl_dpy; - - virtual EGLDisplay OpenDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); } - virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) - { - return (EGLNativeWindowType)EGL_DEFAULT_DISPLAY; - } - virtual void ShutdownPlatform() {} + std::unique_ptr<GLContext> CreateSharedContext() override; + virtual void Shutdown() override; + + bool MakeCurrent() override; + bool ClearCurrent() override; + + void UpdateSurface(void* window_handle) override; -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<cInterfaceBase> CreateSharedContext() 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); + + void* m_host_window = nullptr; + + EGLConfig m_config; + bool m_supports_surfaceless = false; + std::vector<int> m_attribs; + + 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 <android/native_window.h> -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<ANativeWindow*>(m_host_window), 0, 0, format); + m_backbuffer_width = ANativeWindow_getWidth(static_cast<ANativeWindow*>(m_host_window)); + m_backbuffer_height = ANativeWindow_getHeight(static_cast<ANativeWindow*>(m_host_window)); + return static_cast<EGLNativeWindowType>(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 <android/native_window.h> #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<Window>(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); -} + XFree(vi); -void cInterfaceEGLX11::ShutdownPlatform() -{ - XWindow.DestroyXWindow(); - XCloseDisplay(dpy); + return reinterpret_cast<EGLNativeWindowType>(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 <X11/Xlib.h> #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<GLX11Window> 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 <memory> - -#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<cInterfaceBase> HostGL_CreateGLInterface() -{ -#if defined(__APPLE__) - return std::make_unique<cInterfaceAGL>(); -#elif defined(_WIN32) - return std::make_unique<cInterfaceWGL>(); -#elif defined(USE_EGL) && defined(USE_HEADLESS) - return std::make_unique<cInterfaceEGL>(); -#elif defined(HAVE_X11) && HAVE_X11 -#if defined(USE_EGL) && USE_EGL - return std::make_unique<cInterfaceEGLX11>(); -#else - return std::make_unique<cInterfaceGLX>(); -#endif -#elif ANDROID - return std::make_unique<cInterfaceEGLAndroid>(); -#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<unsigned int>(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<void*>(glXGetProcAddress(reinterpret_cast<const GLubyte*>(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<int, 9> context_attribs_33 = { {GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 3, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}}; s_glxError = false; - ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs_33[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<int, 5> context_attribs_legacy = { {GLX_CONTEXT_MAJOR_VERSION_ARB, 1, GLX_CONTEXT_MINOR_VERSION_ARB, 0, None}}; s_glxError = false; - ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs_legacy[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>(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<cInterfaceGLX*>(main_context); + GLContextGLX* glx_context = static_cast<GLContextGLX*>(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<cInterfaceBase> cInterfaceGLX::CreateSharedContext() +bool GLContextGLX::IsHeadless() const +{ + return m_render_window == nullptr; +} + +std::unique_ptr<GLContext> GLContextGLX::CreateSharedContext() { - std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceGLX>(); - if (!context->Create(this)) + std::unique_ptr<GLContextGLX> context = std::make_unique<GLContextGLX>(); + 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<GLXDrawable>(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<GLXDrawable>(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; } } } 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 <string> #include <vector> -#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; - bool m_supports_pbuffer = false; - GLXPbufferSGIX m_pbuffer = 0; - std::vector<int> m_attribs; +public: + bool IsHeadless() const override; - bool CreateWindowSurface(); - void DestroyWindowSurface(); + std::unique_ptr<GLContext> CreateSharedContext() override; + void Shutdown() override; + + bool MakeCurrent() override; + bool ClearCurrent() override; -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<cInterfaceBase> CreateSharedContext() 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<GLX11Window> m_render_window; + + GLXDrawable m_drawable = {}; + GLXContext m_context = {}; + GLXFBConfig m_fbconfig = {}; + bool m_supports_pbuffer = false; + GLXPbufferSGIX m_pbuffer = 0; + std::vector<int> m_attribs; + + bool CreateWindowSurface(Window window_handle); + void DestroyWindowSurface(); }; 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<PFNWGLSWAPINTERVALEXTPROC>( - GLInterface->GetFuncAddress("wglSwapIntervalEXT")); + wglSwapIntervalEXT = + reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(wglGetProcAddress("wglSwapIntervalEXT")); wglCreateContextAttribsARB = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>( wglGetProcAddress("wglCreateContextAttribsARB")); wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>( @@ -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<cInterfaceWGL*>(main_context); + GLContextWGL* wgl_main_context = static_cast<GLContextWGL*>(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<cInterfaceBase> cInterfaceWGL::CreateSharedContext() +std::unique_ptr<GLContext> GLContextWGL::CreateSharedContext() { - std::unique_ptr<cInterfaceWGL> context = std::make_unique<cInterfaceWGL>(); - if (!context->Create(this)) + std::unique_ptr<GLContextWGL> context = std::make_unique<GLContextWGL>(); + if (!context->Initialize(this)) { context->Shutdown(); return nullptr; @@ -345,7 +336,7 @@ std::unique_ptr<cInterfaceBase> 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 <windows.h> #include <string> -#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<GLContext> CreateSharedContext() override; + bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; void Update() override; - bool PeekMessages() override; - std::unique_ptr<cInterfaceBase> 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 <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <string> -#include <thread> - -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; -}; |
