diff --git a/Makefile b/Makefile index ffd905cd60..85339fa110 100644 --- a/Makefile +++ b/Makefile @@ -179,10 +179,10 @@ else ifneq (,$(filter android-arm64 android-x86_64,$(platform))) CC = $(ANDROID_NDK_LLVM)/bin/clang --target=$(ANDROID_TRIPLE) CXX = $(ANDROID_NDK_LLVM)/bin/clang++ --target=$(ANDROID_TRIPLE) AR = $(ANDROID_NDK_LLVM)/bin/llvm-ar - FLAGS += -DANDROID -DHAVE_EGL=1 -I$(CORE_DIR)/Source/Android -funwind-tables + FLAGS += -DANDROID -I$(CORE_DIR)/Source/Android -funwind-tables LDFLAGS += -static-libstdc++ HAVE_BUNDLED_ICONV := 1 - LIBS += -lEGL -landroid -llog -latomic -lm -ldl + LIBS += -landroid -llog -latomic -lm -ldl # Windows (MinGW-w64, native MSYS2 or cross) else diff --git a/Makefile.common b/Makefile.common index 9520abaec9..f76338797a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1733,7 +1733,6 @@ ifeq ($(OS_ANDROID),1) $(CORE_DIR)/Source/Android/jni/AndroidCommon/IDCache.cpp \ $(CORE_DIR)/Source/Core/Common/Logging/ConsoleListenerDroid.cpp \ $(CORE_DIR)/Source/Core/Common/MemArenaAndroid.cpp \ - $(CORE_DIR)/Source/Core/Common/GL/GLInterface/EGL.cpp \ $(CORE_DIR)/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp endif ifeq ($(OS_APPLE),1) diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index 816fe4f8a4..7977475bd2 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -5,27 +5,7 @@ #include "Common/GL/GLContext.h" -#if defined(__APPLE__) && !defined(__LIBRETRO__) -#include "Common/GL/GLInterface/AGL.h" -#endif -#if defined(_WIN32) -#include "Common/GL/GLInterface/WGL.h" -#endif -#if defined(__HAIKU__) -#include "Common/GL/GLInterface/BGL.h" -#endif -#if HAVE_EGL -#include "Common/GL/GLInterface/EGL.h" -#if HAVE_X11 -#include "Common/GL/GLInterface/EGLX11.h" -#endif -#if defined(ANDROID) && !defined(__LIBRETRO__) -#include "Common/GL/GLInterface/EGLAndroid.h" -#endif -#endif -#if defined(__LIBRETRO__) #include "DolphinLibretro/VideoContexts/GLContextLR.h" -#endif const std::array, 9> GLContext::s_desktop_opengl_versions = { {{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2}}}; @@ -42,11 +22,6 @@ bool GLContext::IsHeadless() const return true; } -std::unique_ptr GLContext::CreateSharedContext() -{ - return nullptr; -} - bool GLContext::MakeCurrent() { return false; @@ -82,34 +57,8 @@ std::unique_ptr GLContext::Create(const WindowSystemInfo& wsi, bool s bool prefer_gles) { std::unique_ptr context; -#if defined(__APPLE__) && !defined(__LIBRETRO__) - if (wsi.type == WindowSystemType::MacOS || wsi.type == WindowSystemType::Headless) - context = std::make_unique(); -#endif -#if defined(_WIN32) && !defined(__LIBRETRO__) - if (wsi.type == WindowSystemType::Windows) - context = std::make_unique(); -#endif -#if defined(ANDROID) && !defined(__LIBRETRO__) - if (wsi.type == WindowSystemType::Android) - context = std::make_unique(); -#endif -#if defined(__HAIKU__) - if (wsi.type == WindowSystemType::Haiku) - context = std::make_unique(); -#endif -#if HAVE_EGL -#if HAVE_X11 - if (wsi.type == WindowSystemType::X11) - context = std::make_unique(); -#endif - if (wsi.type == WindowSystemType::Headless || wsi.type == WindowSystemType::FBDev) - context = std::make_unique(); -#endif -#if defined(__LIBRETRO__) if (wsi.type == WindowSystemType::Libretro) context = std::make_unique(); -#endif if (!context) return nullptr; diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index b1619a647f..ff17ebced7 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -31,8 +31,6 @@ public: virtual bool IsHeadless() const; - virtual std::unique_ptr CreateSharedContext(); - virtual bool MakeCurrent(); virtual bool ClearCurrent(); @@ -57,7 +55,6 @@ protected: // Window dimensions. u32 m_backbuffer_width = 0; u32 m_backbuffer_height = 0; - bool m_is_shared = false; // A list of desktop OpenGL versions to attempt to create a context for. // (4.6-3.2, geometry shaders is a minimum requirement since we're using core profile). diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h deleted file mode 100644 index dda9fee0e3..0000000000 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -// This define will silence all "OpenGL is deprecated, use Metal" warnings. -#define GL_SILENCE_DEPRECATION 1 - -#if defined(__APPLE__) && defined(__OBJC__) -#import -#else -struct NSOpenGLContext; -struct NSOpenGLPixelFormat; -struct NSView; -#endif - -#include "Common/GL/GLContext.h" - -class GLContextAGL final : public GLContext -{ -public: - ~GLContextAGL() override; - - bool IsHeadless() const override; - - std::unique_ptr CreateSharedContext() override; - - bool MakeCurrent() override; - bool ClearCurrent() override; - - void Update() override; - - void Swap() override; - void SwapInterval(int interval) override; - -protected: - bool Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) 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 deleted file mode 100644 index 1b8ff224d1..0000000000 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2012 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "Common/GL/GLInterface/AGL.h" - -#include "Common/Logging/Log.h" - -// UpdateCachedDimensions and AttachContextToView contain calls to UI APIs, so they must only be -// called from the main thread or they risk crashing! - -static bool UpdateCachedDimensions(NSView* view, u32* width, u32* height) -{ - NSWindow* window = [view window]; - NSSize size = [view frame].size; - - const CGFloat scale = [window backingScaleFactor]; - u32 new_width = static_cast(size.width * scale); - u32 new_height = static_cast(size.height * scale); - - if (*width == new_width && *height == new_height) - return false; - - *width = new_width; - *height = new_height; - return true; -} - -static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* width, u32* height) -{ - // Enable high-resolution display support. - [view setWantsBestResolutionOpenGLSurface:YES]; - - NSWindow* window = [view window]; - if (window == nil) - { - ERROR_LOG_FMT(VIDEO, "failed to get NSWindow"); - return false; - } - - (void)UpdateCachedDimensions(view, width, height); - - [context setView:view]; - - return true; -} - -GLContextAGL::~GLContextAGL() -{ - if ([NSOpenGLContext currentContext] == m_context) - [NSOpenGLContext clearCurrentContext]; - - if (m_context) - { - [m_context clearDrawable]; - [m_context release]; - } - if (m_pixel_format) - [m_pixel_format release]; -} - -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 GLContextAGL::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) -{ - NSOpenGLPixelFormatAttribute attr[] = { - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAOpenGLProfile, - core ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy, - NSOpenGLPFAAccelerated, - stereo ? NSOpenGLPFAStereo : static_cast(0), - 0}; - m_pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; - if (m_pixel_format == nil) - { - ERROR_LOG_FMT(VIDEO, "failed to create pixel format"); - return false; - } - - m_context = [[NSOpenGLContext alloc] initWithFormat:m_pixel_format shareContext:nil]; - if (m_context == nil) - { - ERROR_LOG_FMT(VIDEO, "failed to create context"); - return false; - } - - if (!wsi.render_surface) - return true; - - m_view = static_cast(wsi.render_surface); - m_opengl_mode = Mode::OpenGL; - - __block bool success; - if ([NSThread isMainThread]) - { - success = AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height); - } - else - { - dispatch_sync(dispatch_get_main_queue(), ^{ - success = AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height); - }); - } - - if (!success) - { - return false; - } - - [m_context makeCurrentContext]; - return true; -} - -std::unique_ptr GLContextAGL::CreateSharedContext() -{ - NSOpenGLContext* new_agl_context = [[NSOpenGLContext alloc] initWithFormat:m_pixel_format - shareContext:m_context]; - if (new_agl_context == nil) - { - ERROR_LOG_FMT(VIDEO, "failed to create shared context"); - return nullptr; - } - - std::unique_ptr new_context = std::make_unique(); - new_context->m_context = new_agl_context; - new_context->m_pixel_format = m_pixel_format; - [new_context->m_pixel_format retain]; - new_context->m_is_shared = true; - return new_context; -} - -bool GLContextAGL::MakeCurrent() -{ - [m_context makeCurrentContext]; - return true; -} - -bool GLContextAGL::ClearCurrent() -{ - [NSOpenGLContext clearCurrentContext]; - return true; -} - -void GLContextAGL::Update() -{ - if (!m_view) - return; - - dispatch_sync(dispatch_get_main_queue(), ^{ - if (UpdateCachedDimensions(m_view, &m_backbuffer_width, &m_backbuffer_height)) - { - [m_context update]; - } - }); -} - -void GLContextAGL::SwapInterval(int interval) -{ - [m_context setValues:static_cast(&interval) forParameter:NSOpenGLCPSwapInterval]; -} diff --git a/Source/Core/Common/GL/GLInterface/BGL.cpp b/Source/Core/Common/GL/GLInterface/BGL.cpp deleted file mode 100644 index ac03e698a4..0000000000 --- a/Source/Core/Common/GL/GLInterface/BGL.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "Common/GL/GLInterface/BGL.h" - -#include -#include -#include - -#include "Common/Assert.h" - -BGLView* GLContextBGL::s_current = nullptr; - -GLContextBGL::~GLContextBGL() -{ - if (!m_window) - delete m_gl; -} - -bool GLContextBGL::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) -{ - m_window = static_cast(wsi.render_window); - - m_gl = new BGLView(m_window ? m_window->Bounds() : BRect(), "GLContextBGL", B_FOLLOW_ALL_SIDES, 0, - BGL_RGB | BGL_DOUBLE | BGL_ALPHA); - if (m_window) - m_window->AddChild(m_gl); - - m_opengl_mode = Mode::OpenGL; - - m_gl->LockLooper(); - BRect size = m_gl->Frame(); - m_gl->UnlockLooper(); - - m_backbuffer_width = size.IntegerWidth(); - m_backbuffer_height = size.IntegerHeight(); - - MakeCurrent(); - - return true; -} - -bool GLContextBGL::IsHeadless() const -{ - return m_window == nullptr; -} - -bool GLContextBGL::MakeCurrent() -{ - if (s_current) - s_current->UnlockGL(); - m_gl->LockGL(); - s_current = m_gl; - return true; -} - -bool GLContextBGL::ClearCurrent() -{ - if (!s_current) - return true; - - ASSERT(m_gl == s_current); - s_current->UnlockGL(); - s_current = nullptr; - return true; -} - -void GLContextBGL::Swap() -{ - m_gl->SwapBuffers(); -} - -void GLContextBGL::Update() -{ - m_gl->LockLooper(); - BRect size = m_gl->Frame(); - if (m_backbuffer_width == size.IntegerWidth() && m_backbuffer_height == size.IntegerHeight()) - { - m_gl->UnlockLooper(); - return; - } - - ClearCurrent(); - m_gl->FrameResized(size.Width(), size.Height()); - MakeCurrent(); - m_gl->UnlockLooper(); - - m_backbuffer_width = size.IntegerWidth(); - m_backbuffer_height = size.IntegerHeight(); -} - -void* GLContextBGL::GetFuncAddress(const std::string& name) -{ - return m_gl->GetGLProcAddress(name.c_str()); -} diff --git a/Source/Core/Common/GL/GLInterface/BGL.h b/Source/Core/Common/GL/GLInterface/BGL.h deleted file mode 100644 index c36f2602dc..0000000000 --- a/Source/Core/Common/GL/GLInterface/BGL.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "Common/GL/GLContext.h" - -class BWindow; -class BGLView; - -class GLContextBGL final : public GLContext -{ -public: - ~GLContextBGL() override; - - bool IsHeadless() const override; - - bool MakeCurrent() override; - bool ClearCurrent() override; - - void Update() override; - - void Swap() override; - - void* GetFuncAddress(const std::string& name) override; - -protected: - bool Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) override; - -private: - static BGLView* s_current; - - BWindow* m_window; - BGLView* m_gl; -}; diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp deleted file mode 100644 index a0bf6dcbab..0000000000 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2012 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "Common/GL/GLInterface/EGL.h" - -#include -#include -#include - -#include "Common/Logging/Log.h" - -#ifndef EGL_KHR_create_context -#define EGL_KHR_create_context 1 -#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 -#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB -#define EGL_CONTEXT_FLAGS_KHR 0x30FC -#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD -#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD -#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE -#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF -#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 -#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 -#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 -#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 -#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 -#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 -#endif /* EGL_KHR_create_context */ - -GLContextEGL::~GLContextEGL() -{ - DestroyWindowSurface(); - DestroyContext(); -} - -bool GLContextEGL::IsHeadless() const -{ - return m_wsi.type == WindowSystemType::Headless; -} - -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 GLContextEGL::DetectMode() -{ - EGLint num_configs; - bool supportsGL = false, supportsGLES3 = false; - std::array renderable_types{{EGL_OPENGL_BIT, EGL_OPENGL_ES3_BIT_KHR}}; - - for (auto renderable_type : renderable_types) - { - // attributes for a visual in RGBA format with at least - // 8 bits per color - int attribs[] = {EGL_RED_SIZE, - 8, - EGL_GREEN_SIZE, - 8, - EGL_BLUE_SIZE, - 8, - EGL_RENDERABLE_TYPE, - renderable_type, - EGL_SURFACE_TYPE, - IsHeadless() ? 0 : EGL_WINDOW_BIT, - EGL_NONE}; - - // Get how many configs there are - if (!eglChooseConfig(m_egl_display, attribs, nullptr, 0, &num_configs)) - { - INFO_LOG_FMT(VIDEO, "Error: couldn't get an EGL visual config"); - continue; - } - - EGLConfig* config = new EGLConfig[num_configs]; - - // Get all the configurations - if (!eglChooseConfig(m_egl_display, attribs, config, num_configs, &num_configs)) - { - INFO_LOG_FMT(VIDEO, "Error: couldn't get an EGL visual config"); - delete[] config; - continue; - } - - for (int i = 0; i < num_configs; ++i) - { - EGLint attribVal; - bool ret; - ret = eglGetConfigAttrib(m_egl_display, config[i], EGL_RENDERABLE_TYPE, &attribVal); - if (ret) - { - if (attribVal & EGL_OPENGL_BIT) - supportsGL = true; - if (attribVal & EGL_OPENGL_ES3_BIT_KHR) - supportsGLES3 = true; - } - } - delete[] config; - } - - if (supportsGL) - { - INFO_LOG_FMT(VIDEO, "Using OpenGL"); - m_opengl_mode = Mode::OpenGL; - } - else if (supportsGLES3) - { - INFO_LOG_FMT(VIDEO, "Using OpenGL|ES"); - m_opengl_mode = Mode::OpenGLES; - } - else - { - // Errored before we found a mode - ERROR_LOG_FMT(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 - m_opengl_mode = Mode::OpenGL; - } -} - -EGLDisplay GLContextEGL::OpenEGLDisplay() -{ - return eglGetDisplay(static_cast(m_wsi.render_surface)); -} - -EGLNativeWindowType GLContextEGL::GetEGLNativeWindow(EGLConfig config) -{ - return reinterpret_cast(m_wsi.display_connection); -} - -// Create rendering window. -// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool GLContextEGL::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) -{ - EGLint egl_major, egl_minor; - bool supports_core_profile = false; - - m_wsi = wsi; - m_egl_display = OpenEGLDisplay(); - if (!m_egl_display) - { - INFO_LOG_FMT(VIDEO, "Error: eglGetDisplay() failed"); - return false; - } - - if (!eglInitialize(m_egl_display, &egl_major, &egl_minor)) - { - INFO_LOG_FMT(VIDEO, "Error: eglInitialize() failed"); - return false; - } - - /* Detection code */ - EGLint num_configs; - - if (m_opengl_mode == Mode::Detect) - DetectMode(); - - // attributes for a visual in RGBA format with at least - // 8 bits per color - int attribs[] = {EGL_RENDERABLE_TYPE, - 0, - EGL_RED_SIZE, - 8, - EGL_GREEN_SIZE, - 8, - EGL_BLUE_SIZE, - 8, - EGL_SURFACE_TYPE, - IsHeadless() ? 0 : EGL_WINDOW_BIT, - EGL_NONE}; - - std::vector ctx_attribs; - switch (m_opengl_mode) - { - case Mode::OpenGL: - attribs[1] = EGL_OPENGL_BIT; - ctx_attribs = {EGL_NONE}; - break; - case Mode::OpenGLES: - attribs[1] = EGL_OPENGL_ES3_BIT_KHR; - ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; - break; - default: - ERROR_LOG_FMT(VIDEO, "Unknown opengl mode set"); - return false; - } - - if (!eglChooseConfig(m_egl_display, attribs, &m_config, 1, &num_configs)) - { - INFO_LOG_FMT(VIDEO, "Error: couldn't get an EGL visual config"); - return false; - } - - if (m_opengl_mode == Mode::OpenGL) - eglBindAPI(EGL_OPENGL_API); - else - eglBindAPI(EGL_OPENGL_ES_API); - - std::string tmp; - std::istringstream buffer(eglQueryString(m_egl_display, EGL_EXTENSIONS)); - while (buffer >> tmp) - { - if (tmp == "EGL_KHR_surfaceless_context") - m_supports_surfaceless = true; - else if (tmp == "EGL_KHR_create_context") - supports_core_profile = true; - } - - if (supports_core_profile && core && m_opengl_mode == Mode::OpenGL) - { - for (const auto& version : s_desktop_opengl_versions) - { - std::vector core_attribs = {EGL_CONTEXT_MAJOR_VERSION_KHR, - version.first, - EGL_CONTEXT_MINOR_VERSION_KHR, - version.second, - EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, - EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, - EGL_CONTEXT_FLAGS_KHR, - EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, - EGL_NONE}; - - 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; - } - } - } - - if (!m_egl_context) - { - m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]); - m_attribs = std::move(ctx_attribs); - } - - if (!m_egl_context) - { - INFO_LOG_FMT(VIDEO, "Error: eglCreateContext failed"); - return false; - } - - if (!CreateWindowSurface()) - { - ERROR_LOG_FMT(VIDEO, "Error: CreateWindowSurface failed {:#06x}", eglGetError()); - return false; - } - - return MakeCurrent(); -} - -std::unique_ptr GLContextEGL::CreateSharedContext() -{ - eglBindAPI(m_opengl_mode == Mode::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API); - EGLContext new_egl_context = - eglCreateContext(m_egl_display, m_config, m_egl_context, m_attribs.data()); - if (!new_egl_context) - { - INFO_LOG_FMT(VIDEO, "Error: eglCreateContext failed {:#06x}", eglGetError()); - return nullptr; - } - - std::unique_ptr new_context = std::make_unique(); - new_context->m_opengl_mode = m_opengl_mode; - new_context->m_egl_context = new_egl_context; - new_context->m_wsi.display_connection = m_wsi.display_connection; - new_context->m_egl_display = m_egl_display; - new_context->m_config = m_config; - new_context->m_supports_surfaceless = m_supports_surfaceless; - new_context->m_is_shared = true; - if (!new_context->CreateWindowSurface()) - { - ERROR_LOG_FMT(VIDEO, "Error: CreateWindowSurface failed {:#06x}", eglGetError()); - return nullptr; - } - - return new_context; -} - -bool GLContextEGL::CreateWindowSurface() -{ - if (!IsHeadless()) - { - EGLNativeWindowType native_window = GetEGLNativeWindow(m_config); - m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, native_window, nullptr); - if (!m_egl_surface) - { - INFO_LOG_FMT(VIDEO, "Error: eglCreateWindowSurface failed"); - return false; - } - - // Get dimensions from the surface. - EGLint surface_width = 1, surface_height = 1; - if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_WIDTH, &surface_width) || - !eglQuerySurface(m_egl_display, m_egl_surface, EGL_HEIGHT, &surface_height)) - { - WARN_LOG_FMT(VIDEO, - "Failed to get surface dimensions via eglQuerySurface. Size may be incorrect."); - } - m_backbuffer_width = static_cast(surface_width); - m_backbuffer_height = static_cast(surface_height); - } - else if (!m_supports_surfaceless) - { - EGLint attrib_list[] = { - EGL_NONE, - }; - m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_config, attrib_list); - if (!m_egl_surface) - { - INFO_LOG_FMT(VIDEO, "Error: eglCreatePbufferSurface failed"); - return false; - } - } - else - { - m_egl_surface = EGL_NO_SURFACE; - } - return true; -} - -void GLContextEGL::DestroyWindowSurface() -{ - if (m_egl_surface == EGL_NO_SURFACE) - return; - - if (eglGetCurrentSurface(EGL_DRAW) == m_egl_surface) - eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!eglDestroySurface(m_egl_display, m_egl_surface)) - NOTICE_LOG_FMT(VIDEO, "Could not destroy window surface."); - m_egl_surface = EGL_NO_SURFACE; -} - -bool GLContextEGL::MakeCurrent() -{ - return eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context); -} - -void GLContextEGL::UpdateSurface(void* window_handle) -{ - m_wsi.render_surface = window_handle; - ClearCurrent(); - DestroyWindowSurface(); - CreateWindowSurface(); - MakeCurrent(); -} - -bool GLContextEGL::ClearCurrent() -{ - return eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -} - -// Close backend -void GLContextEGL::DestroyContext() -{ - if (!m_egl_context) - return; - - if (eglGetCurrentContext() == m_egl_context) - eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!eglDestroyContext(m_egl_display, m_egl_context)) - NOTICE_LOG_FMT(VIDEO, "Could not destroy drawing context."); - if (!m_is_shared && !eglTerminate(m_egl_display)) - NOTICE_LOG_FMT(VIDEO, "Could not destroy display connection."); - m_egl_context = EGL_NO_CONTEXT; - m_egl_display = EGL_NO_DISPLAY; -} diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h deleted file mode 100644 index bed1b31ecc..0000000000 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include - -#include "Common/GL/GLContext.h" - -class GLContextEGL : public GLContext -{ -public: - virtual ~GLContextEGL() override; - - bool IsHeadless() const override; - - std::unique_ptr CreateSharedContext() 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(const WindowSystemInfo& wsi, bool stereo, bool core) override; - - bool CreateWindowSurface(); - void DestroyWindowSurface(); - void DetectMode(); - void DestroyContext(); - - WindowSystemInfo m_wsi = {}; - - EGLConfig m_config; - bool m_supports_surfaceless = false; - std::vector m_attribs; - - EGLSurface m_egl_surface = EGL_NO_SURFACE; - EGLContext m_egl_context = EGL_NO_CONTEXT; - EGLDisplay m_egl_display = EGL_NO_DISPLAY; -}; diff --git a/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp b/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp deleted file mode 100644 index 873387f7e9..0000000000 --- a/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2014 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "Common/GL/GLInterface/EGLAndroid.h" - -#include - -EGLDisplay GLContextEGLAndroid::OpenEGLDisplay() -{ - return eglGetDisplay(EGL_DEFAULT_DISPLAY); -} - -EGLNativeWindowType GLContextEGLAndroid::GetEGLNativeWindow(EGLConfig config) -{ - EGLint format; - eglGetConfigAttrib(m_egl_display, config, EGL_NATIVE_VISUAL_ID, &format); - ANativeWindow_setBuffersGeometry(static_cast(m_wsi.render_surface), 0, 0, format); - m_backbuffer_width = ANativeWindow_getWidth(static_cast(m_wsi.render_surface)); - m_backbuffer_height = ANativeWindow_getHeight(static_cast(m_wsi.render_surface)); - return static_cast(m_wsi.render_surface); -} diff --git a/Source/Core/Common/GL/GLInterface/EGLAndroid.h b/Source/Core/Common/GL/GLInterface/EGLAndroid.h deleted file mode 100644 index 36bc5b9e21..0000000000 --- a/Source/Core/Common/GL/GLInterface/EGLAndroid.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "Common/GL/GLInterface/EGL.h" - -class GLContextEGLAndroid final : public GLContextEGL -{ -protected: - 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 deleted file mode 100644 index 1795ddd2dd..0000000000 --- a/Source/Core/Common/GL/GLInterface/EGLX11.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "Common/GL/GLInterface/EGLX11.h" - -#include - -#include "Common/StringUtil.h" - -GLContextEGLX11::GLContextEGLX11() -{ - // HACK: If EGL_PLATFORM is set to "wayland", Dolphin will still use GLContextEGLX11 due to our - // lack of proper Wayland support, and crash. - // Some distros have started aggressively setting that environment variable, bypassing the usual - // runtime detection. Thus, clear that environment variable if it forces wayland. - const char* current_egl_platform = getenv("EGL_PLATFORM"); - const bool replace_egl_platform = - current_egl_platform != nullptr && - Common::CaseInsensitiveContains(current_egl_platform, "wayland"); - setenv("EGL_PLATFORM", "", replace_egl_platform); -} - -GLContextEGLX11::~GLContextEGLX11() -{ - // The context must be destroyed before the window. - DestroyWindowSurface(); - DestroyContext(); - m_render_window.reset(); -} - -void GLContextEGLX11::Update() -{ - m_render_window->UpdateDimensions(); - m_backbuffer_width = m_render_window->GetWidth(); - m_backbuffer_height = m_render_window->GetHeight(); -} - -EGLDisplay GLContextEGLX11::OpenEGLDisplay() -{ - return eglGetDisplay(static_cast(m_wsi.display_connection)); -} - -EGLNativeWindowType GLContextEGLX11::GetEGLNativeWindow(EGLConfig config) -{ - EGLint vid; - eglGetConfigAttrib(m_egl_display, config, EGL_NATIVE_VISUAL_ID, &vid); - - XVisualInfo visTemplate = {}; - visTemplate.visualid = vid; - - int nVisuals; - XVisualInfo* vi = XGetVisualInfo(static_cast(m_wsi.display_connection), VisualIDMask, - &visTemplate, &nVisuals); - - if (m_render_window) - m_render_window.reset(); - - m_render_window = GLX11Window::Create(static_cast(m_wsi.display_connection), - reinterpret_cast(m_wsi.render_surface), vi); - m_backbuffer_width = m_render_window->GetWidth(); - m_backbuffer_height = m_render_window->GetHeight(); - - XFree(vi); - - return reinterpret_cast(m_render_window->GetWindow()); -} diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.h b/Source/Core/Common/GL/GLInterface/EGLX11.h deleted file mode 100644 index 03560d8581..0000000000 --- a/Source/Core/Common/GL/GLInterface/EGLX11.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include "Common/GL/GLInterface/EGL.h" -#include "Common/GL/GLX11Window.h" - -class GLContextEGLX11 final : public GLContextEGL -{ -public: - GLContextEGLX11(); - ~GLContextEGLX11() override; - - void Update() override; - -protected: - EGLDisplay OpenEGLDisplay() override; - EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override; - - std::unique_ptr m_render_window; -}; diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp deleted file mode 100644 index a85a27a79d..0000000000 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ /dev/null @@ -1,491 +0,0 @@ -// Copyright 2012 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "Common/GL/GLInterface/WGL.h" - -#include -#include -#include - -#include "Common/Logging/Log.h" -#include "Common/MsgHandler.h" - -// from wglext.h -#ifndef WGL_ARB_pbuffer -#define WGL_ARB_pbuffer 1 -DECLARE_HANDLE(HPBUFFERARB); -#define WGL_DRAW_TO_PBUFFER_ARB 0x202D -#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E -#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 -#define WGL_PBUFFER_LARGEST_ARB 0x2033 -#define WGL_PBUFFER_WIDTH_ARB 0x2034 -#define WGL_PBUFFER_HEIGHT_ARB 0x2035 -#define WGL_PBUFFER_LOST_ARB 0x2036 -typedef HPBUFFERARB(WINAPI* PFNWGLCREATEPBUFFERARBPROC)(HDC hDC, int iPixelFormat, int iWidth, - int iHeight, const int* piAttribList); -typedef HDC(WINAPI* PFNWGLGETPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer); -typedef int(WINAPI* PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer, HDC hDC); -typedef BOOL(WINAPI* PFNWGLDESTROYPBUFFERARBPROC)(HPBUFFERARB hPbuffer); -typedef BOOL(WINAPI* PFNWGLQUERYPBUFFERARBPROC)(HPBUFFERARB hPbuffer, int iAttribute, int* piValue); -#endif /* WGL_ARB_pbuffer */ - -#ifndef WGL_ARB_pixel_format -#define WGL_ARB_pixel_format 1 -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_DRAW_TO_BITMAP_ARB 0x2002 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NEED_PALETTE_ARB 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 -#define WGL_SWAP_METHOD_ARB 0x2007 -#define WGL_NUMBER_OVERLAYS_ARB 0x2008 -#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 -#define WGL_TRANSPARENT_ARB 0x200A -#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 -#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 -#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 -#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A -#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B -#define WGL_SHARE_DEPTH_ARB 0x200C -#define WGL_SHARE_STENCIL_ARB 0x200D -#define WGL_SHARE_ACCUM_ARB 0x200E -#define WGL_SUPPORT_GDI_ARB 0x200F -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_STEREO_ARB 0x2012 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201A -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_ALPHA_SHIFT_ARB 0x201C -#define WGL_ACCUM_BITS_ARB 0x201D -#define WGL_ACCUM_RED_BITS_ARB 0x201E -#define WGL_ACCUM_GREEN_BITS_ARB 0x201F -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_GENERIC_ACCELERATION_ARB 0x2026 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_SWAP_EXCHANGE_ARB 0x2028 -#define WGL_SWAP_COPY_ARB 0x2029 -#define WGL_SWAP_UNDEFINED_ARB 0x202A -#define WGL_TYPE_RGBA_ARB 0x202B -#define WGL_TYPE_COLORINDEX_ARB 0x202C -typedef BOOL(WINAPI* PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC hdc, int iPixelFormat, - int iLayerPlane, UINT nAttributes, - const int* piAttributes, int* piValues); -typedef BOOL(WINAPI* PFNWGLGETPIXELFORMATATTRIBFVARBPROC)(HDC hdc, int iPixelFormat, - int iLayerPlane, UINT nAttributes, - const int* piAttributes, FLOAT* pfValues); -typedef BOOL(WINAPI* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, - const FLOAT* pfAttribFList, UINT nMaxFormats, - int* piFormats, UINT* nNumFormats); -#endif /* WGL_ARB_pixel_format */ - -#ifndef WGL_ARB_create_context -#define WGL_ARB_create_context 1 -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define ERROR_INVALID_VERSION_ARB 0x2095 -typedef HGLRC(WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, - const int* attribList); -#endif /* WGL_ARB_create_context */ - -#ifndef WGL_ARB_create_context_profile -#define WGL_ARB_create_context_profile 1 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 -#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define ERROR_INVALID_PROFILE_ARB 0x2096 -#endif /* WGL_ARB_create_context_profile */ - -#ifndef WGL_EXT_swap_control -#define WGL_EXT_swap_control 1 -typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval); -typedef int(WINAPI* PFNWGLGETSWAPINTERVALEXTPROC)(void); -#endif /* WGL_EXT_swap_control */ - -// Persistent pointers -static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr; -static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr; -static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = nullptr; -static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = nullptr; -static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = nullptr; -static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = nullptr; -static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = nullptr; - -static void LoadWGLExtensions() -{ - wglSwapIntervalEXT = - reinterpret_cast(wglGetProcAddress("wglSwapIntervalEXT")); - wglCreateContextAttribsARB = reinterpret_cast( - wglGetProcAddress("wglCreateContextAttribsARB")); - wglChoosePixelFormatARB = reinterpret_cast( - wglGetProcAddress("wglChoosePixelFormatARB")); - wglCreatePbufferARB = - reinterpret_cast(wglGetProcAddress("wglCreatePbufferARB")); - wglGetPbufferDCARB = - reinterpret_cast(wglGetProcAddress("wglGetPbufferDCARB")); - wglReleasePbufferDCARB = - reinterpret_cast(wglGetProcAddress("wglReleasePbufferDCARB")); - wglDestroyPbufferARB = - reinterpret_cast(wglGetProcAddress("wglDestroyPbufferARB")); -} - -static void ClearWGLExtensionPointers() -{ - wglSwapIntervalEXT = nullptr; - wglCreateContextAttribsARB = nullptr; - wglChoosePixelFormatARB = nullptr; - wglCreatePbufferARB = nullptr; - wglGetPbufferDCARB = nullptr; - wglReleasePbufferDCARB = nullptr; - wglDestroyPbufferARB = nullptr; -} - -GLContextWGL::~GLContextWGL() -{ - if (m_rc) - { - if (wglGetCurrentContext() == m_rc && !wglMakeCurrent(m_dc, nullptr)) - NOTICE_LOG_FMT(VIDEO, "Could not release drawing context."); - - if (!wglDeleteContext(m_rc)) - ERROR_LOG_FMT(VIDEO, "Attempt to release rendering context failed."); - - m_rc = nullptr; - } - - if (m_dc) - { - if (m_pbuffer_handle) - { - wglReleasePbufferDCARB(static_cast(m_pbuffer_handle), m_dc); - m_dc = nullptr; - - wglDestroyPbufferARB(static_cast(m_pbuffer_handle)); - m_pbuffer_handle = nullptr; - } - else - { - if (!ReleaseDC(m_window_handle, m_dc)) - ERROR_LOG_FMT(VIDEO, "Attempt to release device context failed."); - - m_dc = nullptr; - } - } -} - -bool GLContextWGL::IsHeadless() const -{ - return !m_window_handle; -} - -void GLContextWGL::SwapInterval(int interval) -{ - if (wglSwapIntervalEXT) - { - wglSwapIntervalEXT(interval); - } - else - { - ERROR_LOG_FMT(VIDEO, - "No support for SwapInterval (framerate clamped to monitor refresh rate)."); - } -} -void GLContextWGL::Swap() -{ - SwapBuffers(m_dc); -} - -void* GLContextWGL::GetFuncAddress(const std::string& name) -{ - FARPROC func = wglGetProcAddress(name.c_str()); - if (func == nullptr) - { - // Using GetModuleHandle here is okay, since we import functions from opengl32.dll, it's - // guaranteed to be loaded. - HMODULE opengl_module = GetModuleHandle(TEXT("opengl32.dll")); - func = GetProcAddress(opengl_module, name.c_str()); - } - - return reinterpret_cast(func); -} - -// Create rendering window. -// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool GLContextWGL::Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) -{ - if (!wsi.render_surface) - return false; - - RECT window_rect = {}; - m_window_handle = static_cast(wsi.render_surface); - if (!GetClientRect(m_window_handle, &window_rect)) - return false; - - // Clear extension function pointers before creating the first context. - ClearWGLExtensionPointers(); - - // Control window size and picture scaling - int twidth = window_rect.right - window_rect.left; - int theight = window_rect.bottom - window_rect.top; - m_backbuffer_width = twidth; - m_backbuffer_height = theight; - - const DWORD stereo_flag = stereo ? PFD_STEREO : 0; - - // clang-format off - static const PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor - 1, // Version Number - PFD_DRAW_TO_WINDOW | // Format Must Support Window - PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER | // Must Support Double Buffering - stereo_flag, // Could Support Quad Buffering - PFD_TYPE_RGBA, // Request An RGBA Format - 32, // Select Our Color Depth - 0, - 0, 0, 0, 0, 0, // Color Bits Ignored - 0, // 8bit Alpha Buffer - 0, // Shift Bit Ignored - 0, // No Accumulation Buffer - 0, 0, 0, 0, // Accumulation Bits Ignored - 0, // 0Bit Z-Buffer (Depth Buffer) - 0, // 0bit Stencil Buffer - 0, // No Auxiliary Buffer - PFD_MAIN_PLANE, // Main Drawing Layer - 0, // Reserved - 0, 0, 0 // Layer Masks Ignored - }; - // clang-format on - - m_dc = GetDC(m_window_handle); - if (!m_dc) - { - PanicAlertFmt("(1) Can't create an OpenGL Device context. Fail."); - return false; - } - - const int pixel_format = ChoosePixelFormat(m_dc, &pfd); - if (pixel_format == 0) - { - PanicAlertFmt("(2) Can't find a suitable PixelFormat."); - return false; - } - - if (!SetPixelFormat(m_dc, pixel_format, &pfd)) - { - PanicAlertFmt("(3) Can't set the PixelFormat."); - return false; - } - - m_rc = wglCreateContext(m_dc); - if (!m_rc) - { - PanicAlertFmt("(4) Can't create an OpenGL rendering context."); - return false; - } - - // WGL only supports desktop GL, for now. - m_opengl_mode = Mode::OpenGL; - - if (core) - { - // Make the fallback context current, temporarily. - // This is because we need an active context to use wglCreateContextAttribsARB. - if (!wglMakeCurrent(m_dc, m_rc)) - { - PanicAlertFmt("(5) Can't make dummy WGL context current."); - return false; - } - - // Load WGL extension function pointers. - LoadWGLExtensions(); - - // Attempt creating a core context. - HGLRC core_context = CreateCoreContext(m_dc, nullptr); - - // Switch out the temporary context before continuing, regardless of whether we got a core - // context. If we didn't get a core context, the caller expects that the context is not current. - if (!wglMakeCurrent(m_dc, nullptr)) - { - PanicAlertFmt("(6) Failed to switch out temporary context"); - return false; - } - - // If we got a core context, destroy and replace the temporary context. - if (core_context) - { - wglDeleteContext(m_rc); - m_rc = core_context; - } - else - { - WARN_LOG_FMT(VIDEO, "Failed to create a core OpenGL context. Using fallback context."); - } - } - - return MakeCurrent(); -} - -std::unique_ptr GLContextWGL::CreateSharedContext() -{ - // WGL does not support surfaceless contexts, so we use a 1x1 pbuffer instead. - HANDLE pbuffer; - HDC dc; - if (!CreatePBuffer(m_dc, 1, 1, &pbuffer, &dc)) - return nullptr; - - HGLRC rc = CreateCoreContext(dc, m_rc); - if (!rc) - { - wglReleasePbufferDCARB(static_cast(pbuffer), dc); - wglDestroyPbufferARB(static_cast(pbuffer)); - return nullptr; - } - - std::unique_ptr context = std::make_unique(); - context->m_pbuffer_handle = pbuffer; - context->m_dc = dc; - context->m_rc = rc; - context->m_opengl_mode = m_opengl_mode; - context->m_is_shared = true; - return context; -} - -HGLRC GLContextWGL::CreateCoreContext(HDC dc, HGLRC share_context) -{ - if (!wglCreateContextAttribsARB) - { - WARN_LOG_FMT(VIDEO, "Missing WGL_ARB_create_context extension"); - return nullptr; - } - - for (const auto& version : s_desktop_opengl_versions) - { - // Construct list of attributes. Prefer a forward-compatible, core context. - std::array attribs = {WGL_CONTEXT_PROFILE_MASK_ARB, - WGL_CONTEXT_CORE_PROFILE_BIT_ARB, -#ifdef _DEBUG - WGL_CONTEXT_FLAGS_ARB, - WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | - WGL_CONTEXT_DEBUG_BIT_ARB, -#else - WGL_CONTEXT_FLAGS_ARB, - WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, -#endif - WGL_CONTEXT_MAJOR_VERSION_ARB, - version.first, - WGL_CONTEXT_MINOR_VERSION_ARB, - version.second, - 0, - 0}; - - // Attempt creating this context. - HGLRC core_context = wglCreateContextAttribsARB(dc, share_context, attribs.data()); - if (core_context) - { - INFO_LOG_FMT(VIDEO, "WGL: Created a GL {}.{} core context", version.first, version.second); - return core_context; - } - } - - WARN_LOG_FMT(VIDEO, "Unable to create a core OpenGL context of an acceptable version"); - return nullptr; -} - -bool GLContextWGL::CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, - HDC* pbuffer_dc) -{ - if (!wglChoosePixelFormatARB || !wglCreatePbufferARB || !wglGetPbufferDCARB || - !wglReleasePbufferDCARB || !wglDestroyPbufferARB) - { - ERROR_LOG_FMT(VIDEO, "Missing WGL_ARB_pbuffer extension"); - return false; - } - - static constexpr std::array pf_iattribs = { - WGL_DRAW_TO_PBUFFER_ARB, - 1, // Pixel format compatible with pbuffer rendering - WGL_RED_BITS_ARB, - 0, - WGL_GREEN_BITS_ARB, - 0, - WGL_BLUE_BITS_ARB, - 0, - WGL_DEPTH_BITS_ARB, - 0, - WGL_STENCIL_BITS_ARB, - 0, - 0, - 0}; - - static constexpr std::array pf_fattribs = {}; - - int pixel_format; - UINT num_pixel_formats; - if (!wglChoosePixelFormatARB(onscreen_dc, pf_iattribs.data(), pf_fattribs.data(), 1, - &pixel_format, &num_pixel_formats)) - { - ERROR_LOG_FMT(VIDEO, "Failed to obtain a compatible pbuffer pixel format"); - return false; - } - - static constexpr std::array pb_attribs = {}; - - HPBUFFERARB pbuffer = - wglCreatePbufferARB(onscreen_dc, pixel_format, width, height, pb_attribs.data()); - if (!pbuffer) - { - ERROR_LOG_FMT(VIDEO, "Failed to create pbuffer"); - return false; - } - - HDC dc = wglGetPbufferDCARB(pbuffer); - if (!dc) - { - ERROR_LOG_FMT(VIDEO, "Failed to get drawing context from pbuffer"); - wglDestroyPbufferARB(pbuffer); - return false; - } - - *pbuffer_handle = pbuffer; - *pbuffer_dc = dc; - return true; -} - -bool GLContextWGL::MakeCurrent() -{ - return wglMakeCurrent(m_dc, m_rc) == TRUE; -} - -bool GLContextWGL::ClearCurrent() -{ - return wglMakeCurrent(m_dc, nullptr) == TRUE; -} - -// Update window width, size and etc. Called from Render.cpp -void GLContextWGL::Update() -{ - RECT rcWindow; - GetClientRect(m_window_handle, &rcWindow); - - // Get the new window width and height - m_backbuffer_width = rcWindow.right - rcWindow.left; - m_backbuffer_height = rcWindow.bottom - rcWindow.top; -} diff --git a/Source/Core/Common/GL/GLInterface/WGL.h b/Source/Core/Common/GL/GLInterface/WGL.h deleted file mode 100644 index 2f5a81e075..0000000000 --- a/Source/Core/Common/GL/GLInterface/WGL.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include "Common/GL/GLContext.h" - -class GLContextWGL final : public GLContext -{ -public: - ~GLContextWGL() override; - - bool IsHeadless() const override; - - std::unique_ptr CreateSharedContext() override; - - bool MakeCurrent() override; - bool ClearCurrent() override; - - void Update() override; - - void Swap() override; - void SwapInterval(int interval) override; - - void* GetFuncAddress(const std::string& name) override; - -protected: - bool Initialize(const WindowSystemInfo& wsi, bool stereo, bool core) override; - - static HGLRC CreateCoreContext(HDC dc, HGLRC share_context); - static bool CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, - HDC* pbuffer_dc); - - HWND m_window_handle = nullptr; - HANDLE m_pbuffer_handle = nullptr; - HDC m_dc = nullptr; - HGLRC m_rc = nullptr; -}; diff --git a/Source/Core/Common/GL/GLX11Window.cpp b/Source/Core/Common/GL/GLX11Window.cpp deleted file mode 100644 index 1fb8c1935c..0000000000 --- a/Source/Core/Common/GL/GLX11Window.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "Common/GL/GLX11Window.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) -{ -} - -GLX11Window::~GLX11Window() -{ - XUnmapWindow(m_display, m_window); - XDestroyWindow(m_display, m_window); - XFreeColormap(m_display, m_color_map); -} - -void GLX11Window::UpdateDimensions() -{ - XWindowAttributes attribs; - XGetWindowAttributes(m_display, m_parent_window, &attribs); - XResizeWindow(m_display, m_window, attribs.width, attribs.height); - m_width = attribs.width; - m_height = attribs.height; -} - -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); -} diff --git a/Source/Core/Common/GL/GLX11Window.h b/Source/Core/Common/GL/GLX11Window.h deleted file mode 100644 index 53b9245bb4..0000000000 --- a/Source/Core/Common/GL/GLX11Window.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#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; } - - void UpdateDimensions(); - - static std::unique_ptr Create(Display* display, Window parent_window, - XVisualInfo* vi); - -private: - Display* m_display; - Window m_parent_window; - Colormap m_color_map; - Window m_window; - - int m_width; - int m_height; -}; diff --git a/Source/Core/DolphinLibretro/VideoContexts/GLContextLR.cpp b/Source/Core/DolphinLibretro/VideoContexts/GLContextLR.cpp index a1d3f9eb38..0dcbb2104f 100644 --- a/Source/Core/DolphinLibretro/VideoContexts/GLContextLR.cpp +++ b/Source/Core/DolphinLibretro/VideoContexts/GLContextLR.cpp @@ -7,555 +7,7 @@ #include "DolphinLibretro/VideoContexts/ContextStatus.h" #include "DolphinLibretro/Video.h" -#include #include -#include - -#include "Common/GL/GLExtensions/GLExtensions.h" - -/* Shared contexts for the shader compiler's threads, made from the - * frontend's: EGL, then GLX, on every Unix but Apple's, and WGL on - * Windows, all loaded at runtime from whichever libraries the frontend - * has, so the core links none of them. */ -#if (defined(__unix__) || defined(__ANDROID__)) && !defined(__APPLE__) -#define LR_SHARED_EGL 1 -#if !defined(__ANDROID__) -#define LR_SHARED_GLX 1 -#endif -#include "Common/DynamicLibrary.h" -#endif -#if defined(_WIN32) -#define LR_SHARED_WGL 1 -#include -#endif - -namespace -{ -// Version/profile of the frontend context, so worker contexts are created to match it. -struct CurrentGLVersion -{ - GLint major = 0; - GLint minor = 0; - bool core_profile = false; -}; - -CurrentGLVersion QueryCurrentGLVersion(bool gles) -{ - CurrentGLVersion v; - glGetIntegerv(GL_MAJOR_VERSION, &v.major); - glGetIntegerv(GL_MINOR_VERSION, &v.minor); - if (!gles && (v.major > 3 || (v.major == 3 && v.minor >= 2))) - { - GLint mask = 0; - glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); - v.core_profile = (mask & GL_CONTEXT_CORE_PROFILE_BIT) != 0; - } - return v; -} - -#if defined(LR_SHARED_EGL) -// EGL is loaded at runtime, from the library the frontend already has loaded. -namespace EGL -{ -using EGLDisplay = void*; -using EGLContext = void*; -using EGLSurface = void*; -using EGLConfig = void*; -using EGLint = int; -using EGLBoolean = unsigned int; -using EGLenum = unsigned int; - -constexpr EGLint EGL_TRUE = 1; -constexpr EGLint EGL_NONE = 0x3038; -constexpr EGLint EGL_CONFIG_ID = 0x3028; -constexpr EGLint EGL_EXTENSIONS = 0x3055; -constexpr EGLint EGL_HEIGHT = 0x3056; -constexpr EGLint EGL_WIDTH = 0x3057; -constexpr EGLint EGL_CONTEXT_CLIENT_VERSION = 0x3098; -constexpr EGLint EGL_CONTEXT_MAJOR_VERSION_KHR = 0x3098; -constexpr EGLint EGL_CONTEXT_MINOR_VERSION_KHR = 0x30FB; -constexpr EGLint EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR = 0x30FD; -constexpr EGLint EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR = 0x1; -constexpr EGLint EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR = 0x2; -constexpr EGLenum EGL_OPENGL_ES_API = 0x30A0; -constexpr EGLenum EGL_OPENGL_API = 0x30A2; - -EGLBoolean (*BindAPI)(EGLenum); -EGLContext (*GetCurrentContext)(); -EGLDisplay (*GetCurrentDisplay)(); -EGLBoolean (*QueryContext)(EGLDisplay, EGLContext, EGLint, EGLint*); -EGLBoolean (*ChooseConfig)(EGLDisplay, const EGLint*, EGLConfig*, EGLint, EGLint*); -EGLContext (*CreateContext)(EGLDisplay, EGLConfig, EGLContext, const EGLint*); -EGLint (*GetError)(); -const char* (*QueryString)(EGLDisplay, EGLint); -EGLSurface (*CreatePbufferSurface)(EGLDisplay, EGLConfig, const EGLint*); -EGLBoolean (*DestroyContext)(EGLDisplay, EGLContext); -EGLBoolean (*DestroySurface)(EGLDisplay, EGLSurface); -EGLBoolean (*MakeCurrent)(EGLDisplay, EGLSurface, EGLSurface, EGLContext); - -bool Load() -{ - static Common::DynamicLibrary libegl; - static const bool loaded = [] { - if (!libegl.Open("libEGL.so.1") && !libegl.Open("libEGL.so")) - return false; - return libegl.GetSymbol("eglBindAPI", &BindAPI) && - libegl.GetSymbol("eglGetCurrentContext", &GetCurrentContext) && - libegl.GetSymbol("eglGetCurrentDisplay", &GetCurrentDisplay) && - libegl.GetSymbol("eglQueryContext", &QueryContext) && - libegl.GetSymbol("eglChooseConfig", &ChooseConfig) && - libegl.GetSymbol("eglCreateContext", &CreateContext) && - libegl.GetSymbol("eglGetError", &GetError) && - libegl.GetSymbol("eglQueryString", &QueryString) && - libegl.GetSymbol("eglCreatePbufferSurface", &CreatePbufferSurface) && - libegl.GetSymbol("eglDestroyContext", &DestroyContext) && - libegl.GetSymbol("eglDestroySurface", &DestroySurface) && - libegl.GetSymbol("eglMakeCurrent", &MakeCurrent); - }(); - return loaded; -} -} // namespace EGL - -class GLContextLRSharedEGL final : public GLContext -{ -public: - GLContextLRSharedEGL(Mode mode, EGL::EGLDisplay display, EGL::EGLContext context, - EGL::EGLSurface surface) - : m_display(display), m_context(context), m_surface(surface) - { - m_opengl_mode = mode; - m_is_shared = true; - } - - ~GLContextLRSharedEGL() override - { - if (EGL::GetCurrentContext() == m_context) - ClearCurrent(); - if (m_surface) - EGL::DestroySurface(m_display, m_surface); - EGL::DestroyContext(m_display, m_context); - } - - bool IsHeadless() const override { return true; } - - bool MakeCurrent() override - { - EGL::BindAPI(m_opengl_mode == Mode::OpenGLES ? EGL::EGL_OPENGL_ES_API : EGL::EGL_OPENGL_API); - return EGL::MakeCurrent(m_display, m_surface, m_surface, m_context) == - static_cast(EGL::EGL_TRUE); - } - - bool ClearCurrent() override - { - return EGL::MakeCurrent(m_display, nullptr, nullptr, nullptr) == - static_cast(EGL::EGL_TRUE); - } - - void* GetFuncAddress(const std::string& name) override - { - return reinterpret_cast(Libretro::Video::hw_render.get_proc_address(name.c_str())); - } - -private: - EGL::EGLDisplay m_display; - EGL::EGLContext m_context; - EGL::EGLSurface m_surface; -}; - -std::unique_ptr CreateSharedEGL(GLContext::Mode mode) -{ - if (!EGL::Load()) - return nullptr; - - const EGL::EGLContext share = EGL::GetCurrentContext(); - const EGL::EGLDisplay display = EGL::GetCurrentDisplay(); - if (!share || !display) - return nullptr; - - const bool gles = mode == GLContext::Mode::OpenGLES; - EGL::BindAPI(gles ? EGL::EGL_OPENGL_ES_API : EGL::EGL_OPENGL_API); - - EGL::EGLint config_id = 0; - EGL::QueryContext(display, share, EGL::EGL_CONFIG_ID, &config_id); - const EGL::EGLint config_attribs[] = {EGL::EGL_CONFIG_ID, config_id, EGL::EGL_NONE}; - EGL::EGLConfig config = nullptr; - EGL::EGLint num_configs = 0; - if (!EGL::ChooseConfig(display, config_attribs, &config, 1, &num_configs) || num_configs < 1) - config = nullptr; // EGL_NO_CONFIG_KHR, frontend may have used EGL_KHR_no_config_context - - const CurrentGLVersion ver = QueryCurrentGLVersion(gles); - EGL::EGLint ctx_attribs[7]; - int n = 0; - ctx_attribs[n++] = EGL::EGL_CONTEXT_MAJOR_VERSION_KHR; - ctx_attribs[n++] = ver.major; - ctx_attribs[n++] = EGL::EGL_CONTEXT_MINOR_VERSION_KHR; - ctx_attribs[n++] = ver.minor; - if (!gles) - { - ctx_attribs[n++] = EGL::EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; - ctx_attribs[n++] = ver.core_profile ? EGL::EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : - EGL::EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; - } - ctx_attribs[n] = EGL::EGL_NONE; - - EGL::EGLContext context = EGL::CreateContext(display, config, share, ctx_attribs); - if (!context) - { - // No EGL_KHR_create_context, fall back to the basic attributes. - const EGL::EGLint es_attribs[] = {EGL::EGL_CONTEXT_CLIENT_VERSION, 3, EGL::EGL_NONE}; - const EGL::EGLint gl_attribs[] = {EGL::EGL_NONE}; - context = EGL::CreateContext(display, config, share, gles ? es_attribs : gl_attribs); - } - if (!context) - { - WARN_LOG_FMT(VIDEO, "Shared context: eglCreateContext failed {:#06x}", EGL::GetError()); - return nullptr; - } - - // Worker contexts never draw, so avoid a surface when possible. - EGL::EGLSurface surface = nullptr; - const char* exts = EGL::QueryString(display, EGL::EGL_EXTENSIONS); - if (!exts || !strstr(exts, "EGL_KHR_surfaceless_context")) - { - const EGL::EGLint pbuffer_attribs[] = {EGL::EGL_WIDTH, 1, EGL::EGL_HEIGHT, 1, EGL::EGL_NONE}; - surface = config ? EGL::CreatePbufferSurface(display, config, pbuffer_attribs) : nullptr; - if (!surface) - { - WARN_LOG_FMT(VIDEO, "Shared context: no surfaceless support and pbuffer creation failed"); - EGL::DestroyContext(display, context); - return nullptr; - } - } - - INFO_LOG_FMT(VIDEO, "Created EGL shared context for shader compiling"); - return std::make_unique(mode, display, context, surface); -} -#endif // LR_SHARED_EGL - -#if defined(LR_SHARED_GLX) -// GLX is loaded at runtime (rather than including GL/glx.h, which conflicts with Dolphin's GL -// loader, and linking libGL), using whichever libGL the frontend already has loaded. -namespace GLX -{ -using Display = void; -using GLXContext = void*; -using GLXFBConfig = void*; -using GLXDrawable = unsigned long; -using XErrorHandler = int (*)(Display*, void*); - -constexpr int GLX_SCREEN = 0x800C; -constexpr int GLX_FBCONFIG_ID = 0x8013; -constexpr int GLX_CONTEXT_MAJOR_VERSION_ARB = 0x2091; -constexpr int GLX_CONTEXT_MINOR_VERSION_ARB = 0x2092; -constexpr int GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126; -constexpr int GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x1; -constexpr int GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x2; -constexpr int GLX_CONTEXT_ES2_PROFILE_BIT_EXT = 0x4; - -GLXContext (*GetCurrentContext)(); -Display* (*GetCurrentDisplay)(); -int (*QueryContext)(Display*, GLXContext, int, int*); -GLXFBConfig* (*ChooseFBConfig)(Display*, int, const int*, int*); -GLXFBConfig* (*GetFBConfigs)(Display*, int, int*); -int (*GetFBConfigAttrib)(Display*, GLXFBConfig, int, int*); -void* (*GetProcAddressARB)(const unsigned char*); -int (*MakeContextCurrent)(Display*, GLXDrawable, GLXDrawable, GLXContext); -void (*DestroyContext)(Display*, GLXContext); -GLXContext (*CreateContextAttribsARB)(Display*, GLXFBConfig, GLXContext, int, const int*); -int (*XFree)(void*); -int (*XSync)(Display*, int); -XErrorHandler (*XSetErrorHandler)(XErrorHandler); - -bool Load() -{ - static Common::DynamicLibrary libgl; - static Common::DynamicLibrary libx11; - static const bool loaded = [] { - if (!libgl.Open("libGL.so.1") && !libgl.Open("libGL.so")) - return false; - if (!libx11.Open("libX11.so.6") && !libx11.Open("libX11.so")) - return false; - return libgl.GetSymbol("glXGetCurrentContext", &GetCurrentContext) && - libgl.GetSymbol("glXGetCurrentDisplay", &GetCurrentDisplay) && - libgl.GetSymbol("glXQueryContext", &QueryContext) && - libgl.GetSymbol("glXChooseFBConfig", &ChooseFBConfig) && - libgl.GetSymbol("glXGetFBConfigs", &GetFBConfigs) && - libgl.GetSymbol("glXGetFBConfigAttrib", &GetFBConfigAttrib) && - libgl.GetSymbol("glXGetProcAddressARB", &GetProcAddressARB) && - libgl.GetSymbol("glXMakeContextCurrent", &MakeContextCurrent) && - libgl.GetSymbol("glXDestroyContext", &DestroyContext) && - libx11.GetSymbol("XFree", &XFree) && libx11.GetSymbol("XSync", &XSync) && - libx11.GetSymbol("XSetErrorHandler", &XSetErrorHandler) && - (CreateContextAttribsARB = reinterpret_cast( - GetProcAddressARB(reinterpret_cast( - "glXCreateContextAttribsARB")))) != nullptr; - }(); - return loaded; -} - -int IgnoreXError(Display*, void*) -{ - return 0; -} -} // namespace GLX - -class GLContextLRSharedGLX final : public GLContext -{ -public: - GLContextLRSharedGLX(Mode mode, GLX::Display* display, GLX::GLXContext context) - : m_display(display), m_context(context) - { - m_opengl_mode = mode; - m_is_shared = true; - } - - ~GLContextLRSharedGLX() override - { - if (GLX::GetCurrentContext() == m_context) - ClearCurrent(); - GLX::DestroyContext(m_display, m_context); - } - - bool IsHeadless() const override { return true; } - - // GLX_ARB_create_context allows GL 3.0+ contexts to be made current without a drawable. - bool MakeCurrent() override { return GLX::MakeContextCurrent(m_display, 0, 0, m_context) != 0; } - bool ClearCurrent() override { return GLX::MakeContextCurrent(m_display, 0, 0, nullptr) != 0; } - - void* GetFuncAddress(const std::string& name) override - { - return reinterpret_cast(Libretro::Video::hw_render.get_proc_address(name.c_str())); - } - -private: - GLX::Display* m_display; - GLX::GLXContext m_context; -}; - -std::unique_ptr CreateSharedGLX(GLContext::Mode mode) -{ - if (!GLX::Load()) - return nullptr; - - GLX::GLXContext share = GLX::GetCurrentContext(); - GLX::Display* display = GLX::GetCurrentDisplay(); - if (!share || !display) - return nullptr; - - int screen = 0; - int fbconfig_id = 0; - GLX::QueryContext(display, share, GLX::GLX_SCREEN, &screen); - GLX::QueryContext(display, share, GLX::GLX_FBCONFIG_ID, &fbconfig_id); - const int fb_attribs[] = {GLX::GLX_FBCONFIG_ID, fbconfig_id, 0}; - int num_configs = 0; - GLX::GLXFBConfig config = nullptr; - GLX::GLXFBConfig* configs = GLX::ChooseFBConfig(display, screen, fb_attribs, &num_configs); - if (configs && num_configs > 0) - config = configs[0]; - else - { - /* Mesa keeps its default attributes beside the ID and may match none: - * the screen's configs, for the one with the ID */ - int i; - if (configs) - GLX::XFree(configs); - configs = GLX::GetFBConfigs(display, screen, &num_configs); - for (i = 0; configs && i < num_configs && !config; i++) - { - int id = 0; - if (GLX::GetFBConfigAttrib(display, configs[i], GLX::GLX_FBCONFIG_ID, &id) == 0 && - id == fbconfig_id) - { - config = configs[i]; - } - } - } - if (configs) - GLX::XFree(configs); - if (!config) - { - WARN_LOG_FMT(VIDEO, "Shared context: no GLXFBConfig matching frontend context"); - return nullptr; - } - - const bool gles = mode == GLContext::Mode::OpenGLES; - const CurrentGLVersion ver = QueryCurrentGLVersion(gles); - const int profile = gles ? GLX::GLX_CONTEXT_ES2_PROFILE_BIT_EXT : - ver.core_profile ? GLX::GLX_CONTEXT_CORE_PROFILE_BIT_ARB : - GLX::GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - const int ctx_attribs[] = {GLX::GLX_CONTEXT_MAJOR_VERSION_ARB, ver.major, - GLX::GLX_CONTEXT_MINOR_VERSION_ARB, ver.minor, - GLX::GLX_CONTEXT_PROFILE_MASK_ARB, profile, - 0}; - - // A failed glXCreateContextAttribsARB raises an X error, and the default handler would - // terminate the frontend, so swallow errors while creating. - GLX::XSync(display, 0); - const GLX::XErrorHandler old_handler = GLX::XSetErrorHandler(GLX::IgnoreXError); - GLX::GLXContext context = GLX::CreateContextAttribsARB(display, config, share, 1, ctx_attribs); - GLX::XSync(display, 0); - GLX::XSetErrorHandler(old_handler); - - if (!context) - { - WARN_LOG_FMT(VIDEO, "Shared context: glXCreateContextAttribsARB failed"); - return nullptr; - } - - INFO_LOG_FMT(VIDEO, "Created GLX shared context for shader compiling"); - return std::make_unique(mode, display, context); -} -#endif // LR_SHARED_GLX -#if defined(LR_SHARED_WGL) -namespace WGL -{ -constexpr int WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091; -constexpr int WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092; -constexpr int WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126; -constexpr int WGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x1; -constexpr int WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x2; -constexpr int WGL_CONTEXT_ES2_PROFILE_BIT_EXT = 0x4; - -HGLRC(WINAPI* GetCurrentContext)(); -HDC(WINAPI* GetCurrentDC)(); -BOOL(WINAPI* MakeCurrent)(HDC, HGLRC); -BOOL(WINAPI* DeleteContext)(HGLRC); -PROC(WINAPI* GetExtProc)(LPCSTR); -HGLRC(WINAPI* CreateContextAttribsARB)(HDC, HGLRC, const int*); -HANDLE(WINAPI* CreatePbufferARB)(HDC, int, int, int, const int*); -HDC(WINAPI* GetPbufferDCARB)(HANDLE); -int(WINAPI* ReleasePbufferDCARB)(HANDLE, HDC); -BOOL(WINAPI* DestroyPbufferARB)(HANDLE); - -/* opengl32 from the frontend, and the extensions with its context current */ -bool Load() -{ - HMODULE gl = GetModuleHandleA("opengl32.dll"); - if (!gl) - return false; - GetCurrentContext = reinterpret_cast( - reinterpret_cast(GetProcAddress(gl, "wglGetCurrentContext"))); - GetCurrentDC = reinterpret_cast( - reinterpret_cast(GetProcAddress(gl, "wglGetCurrentDC"))); - MakeCurrent = reinterpret_cast( - reinterpret_cast(GetProcAddress(gl, "wglMakeCurrent"))); - DeleteContext = reinterpret_cast( - reinterpret_cast(GetProcAddress(gl, "wglDeleteContext"))); - GetExtProc = reinterpret_cast( - reinterpret_cast(GetProcAddress(gl, "wglGetProcAddress"))); - if (!GetCurrentContext || !GetCurrentDC || !MakeCurrent || !DeleteContext || !GetExtProc) - return false; - CreateContextAttribsARB = reinterpret_cast( - reinterpret_cast(GetExtProc("wglCreateContextAttribsARB"))); - CreatePbufferARB = reinterpret_cast( - reinterpret_cast(GetExtProc("wglCreatePbufferARB"))); - GetPbufferDCARB = reinterpret_cast( - reinterpret_cast(GetExtProc("wglGetPbufferDCARB"))); - ReleasePbufferDCARB = reinterpret_cast( - reinterpret_cast(GetExtProc("wglReleasePbufferDCARB"))); - DestroyPbufferARB = reinterpret_cast( - reinterpret_cast(GetExtProc("wglDestroyPbufferARB"))); - return CreateContextAttribsARB != nullptr; -} -} // namespace WGL - -class GLContextLRSharedWGL final : public GLContext -{ -public: - GLContextLRSharedWGL(Mode mode, HDC dc, HGLRC context, HANDLE pbuffer) - : m_dc(dc), m_context(context), m_pbuffer(pbuffer) - { - m_opengl_mode = mode; - m_is_shared = true; - } - - ~GLContextLRSharedWGL() override - { - if (WGL::GetCurrentContext() == m_context) - ClearCurrent(); - WGL::DeleteContext(m_context); - if (m_pbuffer) - { - WGL::ReleasePbufferDCARB(m_pbuffer, m_dc); - WGL::DestroyPbufferARB(m_pbuffer); - } - } - - bool IsHeadless() const override { return true; } - bool MakeCurrent() override { return WGL::MakeCurrent(m_dc, m_context) != FALSE; } - bool ClearCurrent() override { return WGL::MakeCurrent(nullptr, nullptr) != FALSE; } - - void* GetFuncAddress(const std::string& name) override - { - return reinterpret_cast(Libretro::Video::hw_render.get_proc_address(name.c_str())); - } - -private: - HDC m_dc; - HGLRC m_context; - HANDLE m_pbuffer; -}; - -/* A context sharing the frontend's, current on a 1x1 pbuffer of the - * frontend's pixel format, or on the frontend's own DC without - * WGL_ARB_pbuffer. */ -std::unique_ptr CreateSharedWGL(GLContext::Mode mode) -{ - if (!WGL::Load()) - return nullptr; - - const HGLRC share = WGL::GetCurrentContext(); - const HDC frontend_dc = WGL::GetCurrentDC(); - if (!share || !frontend_dc) - return nullptr; - - const bool gles = mode == GLContext::Mode::OpenGLES; - const CurrentGLVersion ver = QueryCurrentGLVersion(gles); - const int profile = gles ? WGL::WGL_CONTEXT_ES2_PROFILE_BIT_EXT : - ver.core_profile ? WGL::WGL_CONTEXT_CORE_PROFILE_BIT_ARB : - WGL::WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - const int ctx_attribs[] = {WGL::WGL_CONTEXT_MAJOR_VERSION_ARB, ver.major, - WGL::WGL_CONTEXT_MINOR_VERSION_ARB, ver.minor, - WGL::WGL_CONTEXT_PROFILE_MASK_ARB, profile, - 0}; - - HANDLE pbuffer = nullptr; - HDC dc = frontend_dc; - if (WGL::CreatePbufferARB && WGL::GetPbufferDCARB && WGL::ReleasePbufferDCARB && - WGL::DestroyPbufferARB) - { - const int pbuffer_attribs[] = {0}; - pbuffer = WGL::CreatePbufferARB(frontend_dc, GetPixelFormat(frontend_dc), 1, 1, - pbuffer_attribs); - HDC pbuffer_dc = pbuffer ? WGL::GetPbufferDCARB(pbuffer) : nullptr; - if (pbuffer_dc) - dc = pbuffer_dc; - else if (pbuffer) - { - WGL::DestroyPbufferARB(pbuffer); - pbuffer = nullptr; - } - } - - const HGLRC context = WGL::CreateContextAttribsARB(dc, share, ctx_attribs); - if (!context) - { - WARN_LOG_FMT(VIDEO, "Shared context: wglCreateContextAttribsARB failed {:#x}", GetLastError()); - if (pbuffer) - { - WGL::ReleasePbufferDCARB(pbuffer, dc); - WGL::DestroyPbufferARB(pbuffer); - } - return nullptr; - } - - INFO_LOG_FMT(VIDEO, "Created WGL shared context for shader compiling ({})", - pbuffer ? "pbuffer" : "frontend DC"); - return std::make_unique(mode, dc, context, pbuffer); -} -#endif // LR_SHARED_WGL - -} // namespace GLContextLR::GLContextLR() { @@ -605,24 +57,6 @@ void GLContextLR::Swap() } -std::unique_ptr GLContextLR::CreateSharedContext() -{ - // Must be called on the thread the frontend's context is current on. -#if defined(LR_SHARED_EGL) - if (auto context = CreateSharedEGL(m_opengl_mode)) - return context; -#endif -#if defined(LR_SHARED_GLX) - if (auto context = CreateSharedGLX(m_opengl_mode)) - return context; -#endif -#if defined(LR_SHARED_WGL) - if (auto context = CreateSharedWGL(m_opengl_mode)) - return context; -#endif - return nullptr; -} - void GLContextLR::Shutdown() { m_initialized = false; diff --git a/Source/Core/DolphinLibretro/VideoContexts/GLContextLR.h b/Source/Core/DolphinLibretro/VideoContexts/GLContextLR.h index 1bf7a790db..1b33da92e1 100644 --- a/Source/Core/DolphinLibretro/VideoContexts/GLContextLR.h +++ b/Source/Core/DolphinLibretro/VideoContexts/GLContextLR.h @@ -17,10 +17,6 @@ public: bool IsInitialized() const { return m_initialized; } void Shutdown(); - // libretro has no API for additional contexts, so this creates one directly through - // EGL/GLX, sharing with whatever frontend context is current on the calling thread. - std::unique_ptr CreateSharedContext() override; - private: bool m_initialized = false; }; diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.cpp b/Source/Core/VideoBackends/OGL/OGLConfig.cpp index 07277c97bd..ae2ce48ca0 100644 --- a/Source/Core/VideoBackends/OGL/OGLConfig.cpp +++ b/Source/Core/VideoBackends/OGL/OGLConfig.cpp @@ -699,9 +699,8 @@ bool PopulateConfig(GLContext* m_main_gl_context) g_backend_info.bSupportsComputeShaders && g_ogl_config.bSupportsImageLoadStore; - // Background compiling is supported only when shared contexts aren't broken. - g_backend_info.bSupportsBackgroundCompiling = - !DriverDetails::HasBug(DriverDetails::BUG_SHARED_CONTEXT_SHADER_COMPILATION); + // Programs are compiled on the frontend's context alone: the core makes no contexts of its own. + g_backend_info.bSupportsBackgroundCompiling = false; // Program binaries are supported on GL4.1+, ARB_get_program_binary, or ES3. if (supports_glsl_cache) diff --git a/Source/Core/VideoBackends/OGL/OGLGfx.cpp b/Source/Core/VideoBackends/OGL/OGLGfx.cpp index 08f00ddf1a..e0963db0f3 100644 --- a/Source/Core/VideoBackends/OGL/OGLGfx.cpp +++ b/Source/Core/VideoBackends/OGL/OGLGfx.cpp @@ -671,7 +671,7 @@ void OGLGfx::UnbindTexture(const AbstractTexture* texture) std::unique_ptr OGLGfx::CreateAsyncShaderCompiler() { - return std::make_unique(); + return std::make_unique(); } bool OGLGfx::IsGLES() const diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 39d7480e5c..0a5fc864a9 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -52,7 +52,6 @@ atomic_slot_map_t* ProgramShaderCache::s_pipeline_programs; quiesce_t ProgramShaderCache::s_pipeline_program_quiesce; static std::string s_glsl_header; static retro_atomic_64_t s_shader_counter; -static thread_local bool s_is_shared_context = false; static std::string GetGLSLVersionString() { @@ -586,7 +585,7 @@ PipelineProgram* ProgramShaderCache::GetPipelineProgram(const GLVertexFormat* ve // We temporarily change the vertex array to the pipeline's vertex format. // This can prevent the NVIDIA OpenGL driver from recompiling on first use. GLuint vao = vertex_format ? vertex_format->VAO : s_attributeless_VAO; - if (s_is_shared_context || vao != s_last_VAO) + if (vao != s_last_VAO) glBindVertexArray(vao); // Attach shaders. @@ -608,7 +607,7 @@ PipelineProgram* ProgramShaderCache::GetPipelineProgram(const GLVertexFormat* ve glLinkProgram(prog->shader.glprogid); // Restore VAO binding after linking. - if (!s_is_shared_context && vao != s_last_VAO) + if (vao != s_last_VAO) glBindVertexArray(s_last_VAO); if (!CheckProgramLinkResult(prog->shader.glprogid, @@ -625,11 +624,6 @@ PipelineProgram* ProgramShaderCache::GetPipelineProgram(const GLVertexFormat* ve // This is only needed for drivers which don't support binding layout. prog->shader.SetProgramVariables(); - // If this is a shared context, ensure we sync before we return the program to - // the main thread. If we don't do this, some driver can lock up (e.g. AMD). - if (s_is_shared_context) - glFinish(); - // Publish it, unless another thread made the same program meanwhile; a dead program in the // slot is simply replaced. for (;;) @@ -915,48 +909,4 @@ u64 ProgramShaderCache::GenerateShaderID() return static_cast(retro_atomic_fetch_add_64(&s_shader_counter, 1)); } -bool SharedContextAsyncShaderCompiler::WorkerThreadInitMainThread(void** param) -{ - std::unique_ptr context = GetOGLGfx()->GetMainGLContext()->CreateSharedContext(); - if (!context) - { - PanicAlertFmt("Failed to create shared context for shader compiling."); - return false; - } - - *param = context.release(); - return true; -} - -bool SharedContextAsyncShaderCompiler::WorkerThreadInitWorkerThread(void* param) -{ - GLContext* context = static_cast(param); - if (!context->MakeCurrent()) - return false; - - s_is_shared_context = true; - - // Make the state match the main context to have a better chance of avoiding recompiles. - if (!context->IsGLES()) - glEnable(GL_PROGRAM_POINT_SIZE); - if (g_backend_info.bSupportsClipControl) - glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); - if (g_backend_info.bSupportsDepthClamp) - { - glEnable(GL_CLIP_DISTANCE0); - glEnable(GL_CLIP_DISTANCE1); - glEnable(GL_DEPTH_CLAMP); - } - if (g_backend_info.bSupportsPrimitiveRestart) - GLUtil::EnablePrimitiveRestart(context); - - return true; -} - -void SharedContextAsyncShaderCompiler::WorkerThreadExit(void* param) -{ - GLContext* context = static_cast(param); - context->ClearCurrent(); - delete context; -} } // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.h b/Source/Core/VideoBackends/OGL/ProgramShaderCache.h index e4005cb7f0..400b127e17 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.h +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.h @@ -121,12 +121,4 @@ private: static GLuint s_last_VAO; }; -class SharedContextAsyncShaderCompiler : public VideoCommon::AsyncShaderCompiler -{ -protected: - bool WorkerThreadInitMainThread(void** param) override; - bool WorkerThreadInitWorkerThread(void* param) override; - void WorkerThreadExit(void* param) override; -}; - } // namespace OGL diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp index 762e6e8b8d..e68c25fe8e 100644 --- a/Source/Core/VideoCommon/DriverDetails.cpp +++ b/Source/Core/VideoCommon/DriverDetails.cpp @@ -106,10 +106,6 @@ constexpr BugInfo m_known_bugs[] = { -1.0, true}, {API_VULKAN, OS_ALL, VENDOR_ARM, DRIVER_ARM, Family::UNKNOWN, BUG_PRIMITIVE_RESTART, -1.0, -1.0, true}, - {API_OPENGL, OS_LINUX, VENDOR_MESA, DRIVER_I965, Family::UNKNOWN, - BUG_SHARED_CONTEXT_SHADER_COMPILATION, -1.0, -1.0, true}, - {API_OPENGL, OS_LINUX, VENDOR_MESA, DRIVER_NOUVEAU, Family::UNKNOWN, - BUG_SHARED_CONTEXT_SHADER_COMPILATION, -1.0, -1.0, true}, {API_VULKAN, OS_ALL, VENDOR_NVIDIA, DRIVER_NVIDIA, Family::UNKNOWN, BUG_BROKEN_MSAA_CLEAR, -1.0, -1.0, true}, {API_VULKAN, OS_ALL, VENDOR_IMGTEC, DRIVER_IMGTEC, Family::UNKNOWN, diff --git a/Source/Core/VideoCommon/DriverDetails.h b/Source/Core/VideoCommon/DriverDetails.h index 8f6207f3f8..416e75d752 100644 --- a/Source/Core/VideoCommon/DriverDetails.h +++ b/Source/Core/VideoCommon/DriverDetails.h @@ -245,15 +245,6 @@ enum Bug // the negated value to a temporary variable then using that in the bitwise op. BUG_BROKEN_BITWISE_OP_NEGATION, - // BUG: The GPU shader code appears to be context-specific on Mesa/i965. - // This means that if we compiled the ubershaders asynchronously, they will be recompiled - // on the main thread the first time they are used, causing stutter. For now, disable - // asynchronous compilation on Mesa i965. On nouveau, our use of glFinish() can cause - // crashes and/or lockups. - // Started version: -1 - // Ended Version: -1 - BUG_SHARED_CONTEXT_SHADER_COMPILATION, - // Bug: Fast clears on a MSAA framebuffer can cause NVIDIA GPU resets/lockups. // Started version: -1 // Ended version: -1