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.
This commit is contained in:
Ryan Houdek
2016-01-21 19:03:58 -06:00
parent fdf6fb47e0
commit aed693eded
3 changed files with 102 additions and 30 deletions

View File

@ -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<cInterfaceBase> cInterfaceEGL::CreateSharedContext()
{
std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceEGL>();
if (!context->Create(this))
return nullptr;
return context;
}
bool cInterfaceEGL::Create(cInterfaceBase* main_context)
{
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;
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;
}