Common: Add DRM display helper class and GBM GL context

This commit is contained in:
Connor McLaughlin
2021-01-31 02:25:05 +10:00
parent b267020d07
commit b09da307b5
15 changed files with 946 additions and 12 deletions

View File

@ -1,6 +1,8 @@
#include "context_egl.h"
#include "../assert.h"
#include "../log.h"
#include <optional>
#include <vector>
Log_SetChannel(GL::ContextEGL);
namespace GL {
@ -33,12 +35,8 @@ bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_
return false;
}
m_display = eglGetDisplay(static_cast<EGLNativeDisplayType>(m_wi.display_connection));
if (!m_display)
{
Log_ErrorPrintf("eglGetDisplay() failed: %d", eglGetError());
if (!SetDisplay())
return false;
}
int egl_major, egl_minor;
if (!eglInitialize(m_display, &egl_major, &egl_minor))
@ -66,6 +64,18 @@ bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_
return false;
}
bool ContextEGL::SetDisplay()
{
m_display = eglGetDisplay(static_cast<EGLNativeDisplayType>(m_wi.display_connection));
if (!m_display)
{
Log_ErrorPrintf("eglGetDisplay() failed: %d", eglGetError());
return false;
}
return true;
}
void* ContextEGL::GetProcAddress(const char* name)
{
return reinterpret_cast<void*>(eglGetProcAddress(name));
@ -216,6 +226,36 @@ bool ContextEGL::CreatePBufferSurface()
return true;
}
bool ContextEGL::CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceFormat format) const
{
int red_size, green_size, blue_size, alpha_size;
if (!eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &red_size) ||
!eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &green_size) ||
!eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &blue_size) ||
!eglGetConfigAttrib(m_display, config, EGL_ALPHA_SIZE, &alpha_size))
{
return false;
}
switch (format)
{
case WindowInfo::SurfaceFormat::Auto:
return true;
case WindowInfo::SurfaceFormat::RGB8:
return (red_size == 8 && green_size == 8 && blue_size == 8);
case WindowInfo::SurfaceFormat::RGBA8:
return (red_size == 8 && green_size == 8 && blue_size == 8 && alpha_size == 8);
case WindowInfo::SurfaceFormat::RGB565:
return (red_size == 5 && green_size == 6 && blue_size == 5);
default:
return false;
}
}
bool ContextEGL::CreateContext(const Version& version, EGLContext share_context)
{
Log_DevPrintf(
@ -263,6 +303,9 @@ bool ContextEGL::CreateContext(const Version& version, EGLContext share_context)
surface_attribs[nsurface_attribs++] = 5;
break;
case WindowInfo::SurfaceFormat::Auto:
break;
default:
UnreachableCode();
break;
@ -272,13 +315,36 @@ bool ContextEGL::CreateContext(const Version& version, EGLContext share_context)
surface_attribs[nsurface_attribs++] = 0;
EGLint num_configs;
EGLConfig config;
if (!eglChooseConfig(m_display, surface_attribs, &config, 1, &num_configs) || num_configs == 0)
if (!eglChooseConfig(m_display, surface_attribs, nullptr, 0, &num_configs) || num_configs == 0)
{
Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError());
return false;
}
std::vector<EGLConfig> configs(static_cast<u32>(num_configs));
if (!eglChooseConfig(m_display, surface_attribs, configs.data(), num_configs, &num_configs))
{
Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError());
return false;
}
configs.resize(static_cast<u32>(num_configs));
std::optional<EGLConfig> config;
for (EGLConfig check_config : configs)
{
if (CheckConfigSurfaceFormat(check_config, m_wi.surface_format))
{
config = check_config;
break;
}
}
if (!config.has_value())
{
Log_WarningPrintf("No EGL configs matched exactly, using first.");
config = configs.front();
}
int attribs[8];
int nattribs = 0;
if (version.profile != Profile::NoProfile)
@ -297,7 +363,7 @@ bool ContextEGL::CreateContext(const Version& version, EGLContext share_context)
return false;
}
m_context = eglCreateContext(m_display, config, share_context, attribs);
m_context = eglCreateContext(m_display, config.value(), share_context, attribs);
if (!m_context)
{
Log_ErrorPrintf("eglCreateContext() failed: %d", eglGetError());
@ -308,7 +374,7 @@ bool ContextEGL::CreateContext(const Version& version, EGLContext share_context)
"Got version %u.%u (%s)", version.major_version, version.minor_version,
version.profile == Context::Profile::ES ? "ES" : (version.profile == Context::Profile::Core ? "Core" : "None"));
m_config = config;
m_config = config.value();
m_version = version;
return true;
}