diff options
Diffstat (limited to 'Source/Core/Common/GL/GLInterface/EGL.cpp')
| -rw-r--r-- | Source/Core/Common/GL/GLInterface/EGL.cpp | 281 |
1 files changed, 121 insertions, 160 deletions
diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index e71b365928..93a60ca9d8 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -9,7 +9,6 @@ #include "Common/GL/GLInterface/EGL.h" #include "Common/Logging/Log.h" -#include "Core/Config/GraphicsSettings.h" #ifndef EGL_KHR_create_context #define EGL_KHR_create_context 1 @@ -28,35 +27,37 @@ #define EGL_OPENGL_ES3_BIT_KHR 0x00000040 #endif /* EGL_KHR_create_context */ -// Show the current FPS -void cInterfaceEGL::Swap() +GLContextEGL::~GLContextEGL() { - if (egl_surf != EGL_NO_SURFACE) - eglSwapBuffers(egl_dpy, egl_surf); + DestroyWindowSurface(); + DestroyContext(); } -void cInterfaceEGL::SwapInterval(int Interval) + +bool GLContextEGL::IsHeadless() const { - eglSwapInterval(egl_dpy, Interval); + return m_host_window == nullptr; } -void* cInterfaceEGL::GetFuncAddress(const std::string& name) +void GLContextEGL::Swap() { - return (void*)eglGetProcAddress(name.c_str()); + 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::DetectMode() +void* GLContextEGL::GetFuncAddress(const std::string& name) { - if (s_opengl_mode != GLInterfaceMode::MODE_DETECT) - return; - bool preferGLES = Config::Get(Config::GFX_PREFER_GLES); + return (void*)eglGetProcAddress(name.c_str()); +} +void GLContextEGL::DetectMode(bool has_handle) +{ 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 +72,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 +85,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,80 +96,68 @@ 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; } - if (preferGLES) - { - if (supportsGLES3) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3; - else if (supportsGLES2) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2; - else if (supportsGL) - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; - } - else - { - if (supportsGL) - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; - else if (supportsGLES3) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3; - else if (supportsGLES2) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2; - } - - if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL) + if (supportsGL) { INFO_LOG(VIDEO, "Using OpenGL"); + m_opengl_mode = Mode::OpenGL; } - else if (s_opengl_mode == GLInterfaceMode::MODE_OPENGLES3) - { - INFO_LOG(VIDEO, "Using OpenGL|ES 3"); - } - else if (s_opengl_mode == GLInterfaceMode::MODE_OPENGLES2) + else if (supportsGLES3) { - INFO_LOG(VIDEO, "Using OpenGL|ES 2"); + INFO_LOG(VIDEO, "Using OpenGL|ES"); + m_opengl_mode = Mode::OpenGLES; } - else if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) + else { // 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* display_handle, 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_host_display = display_handle; + m_host_window = window_handle; + m_egl_display = OpenEGLDisplay(); - 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 +166,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 +180,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,19 +220,9 @@ 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}, - {4, 4}, - {4, 3}, - {4, 2}, - {4, 1}, - {4, 0}, - {3, 3}, - }}; - - for (const auto& version : versions_to_try) + for (const auto& version : s_desktop_opengl_versions) { std::vector<EGLint> core_attribs = {EGL_CONTEXT_MAJOR_VERSION_KHR, version.first, @@ -259,8 +234,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 +243,13 @@ 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_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; @@ -286,56 +260,45 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError()); return false; } - return true; -} -std::unique_ptr<cInterfaceBase> cInterfaceEGL::CreateSharedContext() -{ - std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceEGL>(); - if (!context->Create(this)) - return nullptr; - return context; + return MakeCurrent(); } -bool cInterfaceEGL::Create(cInterfaceBase* main_context) +std::unique_ptr<GLContext> GLContextEGL::CreateSharedContext() { - cInterfaceEGL* egl_context = static_cast<cInterfaceEGL*>(main_context); - - egl_dpy = egl_context->egl_dpy; - m_core = egl_context->m_core; - 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) - 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) + 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(VIDEO, "Error: eglCreateContext failed 0x%04x", eglGetError()); - return false; + return nullptr; } - if (!CreateWindowSurface()) + std::unique_ptr<GLContextEGL> new_context = std::make_unique<GLContextEGL>(); + new_context->m_opengl_mode = m_opengl_mode; + new_context->m_egl_context = new_egl_context; + new_context->m_host_display = m_host_display; + 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(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError()); - return false; + return nullptr; } - return true; + + return new_context; } -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 +309,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 +318,54 @@ 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)) - NOTICE_LOG(VIDEO, "Could not destroy window surface."); - egl_surf = EGL_NO_SURFACE; -} + if (m_egl_surface == EGL_NO_SURFACE) + return; -bool cInterfaceEGL::MakeCurrent() -{ - return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx); + 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(VIDEO, "Could not destroy window surface."); + 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::DestroyContext() { - ShutdownPlatform(); - if (egl_ctx) - { - if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) - 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)) - NOTICE_LOG(VIDEO, "Could not destroy drawing context."); - DestroyWindowSurface(); - if (!m_is_shared && !eglTerminate(egl_dpy)) - NOTICE_LOG(VIDEO, "Could not destroy display connection."); - egl_ctx = nullptr; - } + 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(VIDEO, "Could not destroy drawing context."); + if (!m_is_shared && !eglTerminate(m_egl_display)) + NOTICE_LOG(VIDEO, "Could not destroy display connection."); + m_egl_context = EGL_NO_CONTEXT; + m_egl_display = EGL_NO_DISPLAY; } |
