From aed693eded4bea4be9610f2bbd132288236d06b4 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 21 Jan 2016 19:03:58 -0600 Subject: [PATCH] Implement shared contexts in the EGL context. This is being implemented here first under EGL since the infrastructure is already in place for this due to the Android code requiring some bits. The rest of the interfaces will come in a little bit. This will be required for threaded shader compiling in the near future. --- Source/Core/Common/GL/GLInterface/EGL.cpp | 118 +++++++++++++++++----- Source/Core/Common/GL/GLInterface/EGL.h | 10 +- Source/Core/Common/GL/GLInterfaceBase.h | 4 + 3 files changed, 102 insertions(+), 30 deletions(-) diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index e61627cbdf..3edee9e478 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -104,6 +104,7 @@ bool cInterfaceEGL::Create(void *window_handle, bool core) egl_dpy = OpenDisplay(); m_host_window = (EGLNativeWindowType) window_handle; m_has_handle = !!window_handle; + m_core = false; if (!egl_dpy) { @@ -137,28 +138,28 @@ bool cInterfaceEGL::Create(void *window_handle, bool core) }; switch (s_opengl_mode) { - case GLInterfaceMode::MODE_OPENGL: - attribs[1] = EGL_OPENGL_BIT; - ctx_attribs[0] = EGL_NONE; - break; - case GLInterfaceMode::MODE_OPENGLES2: - attribs[1] = EGL_OPENGL_ES2_BIT; - ctx_attribs[1] = 2; - break; - case GLInterfaceMode::MODE_OPENGLES3: - attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */ - ctx_attribs[1] = 3; - break; - default: - ERROR_LOG(VIDEO, "Unknown opengl mode set\n"); - return false; - break; + case GLInterfaceMode::MODE_OPENGL: + attribs[1] = EGL_OPENGL_BIT; + ctx_attribs[0] = EGL_NONE; + break; + case GLInterfaceMode::MODE_OPENGLES2: + attribs[1] = EGL_OPENGL_ES2_BIT; + ctx_attribs[1] = 2; + break; + case GLInterfaceMode::MODE_OPENGLES3: + attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */ + ctx_attribs[1] = 3; + break; + default: + ERROR_LOG(VIDEO, "Unknown opengl mode set\n"); + return false; + break; } if (!eglChooseConfig( egl_dpy, attribs, &m_config, 1, &num_configs)) { INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n"); - exit(1); + return false; } if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL) @@ -170,7 +171,7 @@ bool cInterfaceEGL::Create(void *window_handle, bool core) if (!egl_ctx) { INFO_LOG(VIDEO, "Error: eglCreateContext failed\n"); - exit(1); + return false; } std::string tmp; @@ -184,12 +185,76 @@ bool cInterfaceEGL::Create(void *window_handle, bool core) } } - - CreateWindowSurface(); + if (!CreateWindowSurface()) + { + ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x\n", eglGetError()); + return false; + } return true; } -void cInterfaceEGL::CreateWindowSurface() +std::unique_ptr cInterfaceEGL::CreateSharedContext() +{ + std::unique_ptr context = std::make_unique(); + if (!context->Create(this)) + return nullptr; + return context; +} + +bool cInterfaceEGL::Create(cInterfaceBase* main_context) +{ + cInterfaceEGL* egl_context = static_cast(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; + + EGLint ctx_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + switch (egl_context->GetMode()) + { + case GLInterfaceMode::MODE_OPENGL: + ctx_attribs[0] = EGL_NONE; + break; + case GLInterfaceMode::MODE_OPENGLES2: + ctx_attribs[1] = 2; + break; + case GLInterfaceMode::MODE_OPENGLES3: + ctx_attribs[1] = 3; + break; + default: + INFO_LOG(VIDEO, "Unknown opengl mode set\n"); + return false; + break; + } + + 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, ctx_attribs ); + if (!egl_ctx) + { + INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x\n", eglGetError()); + return false; + } + + if (!CreateWindowSurface()) + { + ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x\n", eglGetError()); + return false; + } + return true; +} + +bool cInterfaceEGL::CreateWindowSurface() { if (m_has_handle) { @@ -198,7 +263,7 @@ void cInterfaceEGL::CreateWindowSurface() if (!egl_surf) { INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed\n"); - exit(1); + return false; } } else if (!m_supports_surfaceless) @@ -211,13 +276,14 @@ void cInterfaceEGL::CreateWindowSurface() if (!egl_surf) { INFO_LOG(VIDEO, "Error: eglCreatePbufferSurface failed"); - exit(2); + return false; } } else { egl_surf = EGL_NO_SURFACE; } + return true; } void cInterfaceEGL::DestroyWindowSurface() @@ -255,15 +321,15 @@ bool cInterfaceEGL::ClearCurrent() void cInterfaceEGL::Shutdown() { ShutdownPlatform(); - if (egl_ctx && !eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) - NOTICE_LOG(VIDEO, "Could not release drawing context."); 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 (!eglTerminate(egl_dpy)) + if (!m_is_shared && !eglTerminate(egl_dpy)) NOTICE_LOG(VIDEO, "Could not destroy display connection."); egl_ctx = nullptr; } diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index 8811aa0c97..fec46ec9e9 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -17,7 +17,7 @@ private: EGLNativeWindowType m_host_window; bool m_supports_surfaceless = false; - void CreateWindowSurface(); + bool CreateWindowSurface(); void DestroyWindowSurface(); protected: @@ -26,9 +26,9 @@ protected: EGLContext egl_ctx; EGLDisplay egl_dpy; - virtual EGLDisplay OpenDisplay() = 0; - virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) = 0; - virtual void ShutdownPlatform() = 0; + virtual EGLDisplay OpenDisplay() { return EGL_NO_DISPLAY; } + virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) { return (EGLNativeWindowType)EGL_DEFAULT_DISPLAY; } + virtual void ShutdownPlatform() {} public: void Swap() override; @@ -36,9 +36,11 @@ public: void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; } void* GetFuncAddress(const std::string& name) override; bool Create(void* window_handle, bool core) override; + bool Create(cInterfaceBase* main_context) override; bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; void UpdateHandle(void* window_handle) override; void UpdateSurface() override; + std::unique_ptr CreateSharedContext() override; }; diff --git a/Source/Core/Common/GL/GLInterfaceBase.h b/Source/Core/Common/GL/GLInterfaceBase.h index 34834403e5..2cc022faee 100644 --- a/Source/Core/Common/GL/GLInterfaceBase.h +++ b/Source/Core/Common/GL/GLInterfaceBase.h @@ -23,6 +23,8 @@ protected: // Window dimensions. u32 s_backbuffer_width = 0; u32 s_backbuffer_height = 0; + bool m_core = false; + bool m_is_shared = false; GLInterfaceMode s_opengl_mode = GLInterfaceMode::MODE_DETECT; public: @@ -32,6 +34,7 @@ public: virtual GLInterfaceMode GetMode() { return s_opengl_mode; } virtual void* GetFuncAddress(const std::string& name) { return nullptr; } virtual bool Create(void *window_handle, bool core = true) { return true; } + virtual bool Create(cInterfaceBase* main_context) { return true; } virtual bool MakeCurrent() { return true; } virtual bool ClearCurrent() { return true; } virtual void Shutdown() {} @@ -44,6 +47,7 @@ public: virtual bool PeekMessages() { return false; } virtual void UpdateHandle(void* window_handle) {} virtual void UpdateSurface() {} + virtual std::unique_ptr CreateSharedContext() { return nullptr; } }; extern std::unique_ptr GLInterface;