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;