2020-05-07 12:48:13 +00:00
|
|
|
#include "context.h"
|
|
|
|
#include "../log.h"
|
|
|
|
#include "glad.h"
|
|
|
|
#include <cstdlib>
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#include <stdlib.h>
|
|
|
|
#else
|
|
|
|
#include <malloc.h>
|
|
|
|
#endif
|
|
|
|
Log_SetChannel(GL::Context);
|
|
|
|
|
|
|
|
#if defined(WIN32)
|
|
|
|
#include "context_wgl.h"
|
2020-09-13 01:56:56 +00:00
|
|
|
#elif defined(__APPLE__) && !defined(LIBERTRO)
|
2020-05-07 12:48:13 +00:00
|
|
|
#include "context_agl.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_EGL
|
|
|
|
#if defined(USE_X11)
|
|
|
|
#include "context_egl_x11.h"
|
2020-07-07 11:40:55 +00:00
|
|
|
#elif defined(USE_WAYLAND)
|
|
|
|
#include "context_egl_wayland.h"
|
2020-05-07 12:48:13 +00:00
|
|
|
#elif defined(ANDROID)
|
|
|
|
#include "context_egl_android.h"
|
|
|
|
#else
|
|
|
|
#error Unknown EGL platform
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_GLX
|
|
|
|
#include "context_glx.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace GL {
|
|
|
|
|
|
|
|
static bool ShouldPreferESContext()
|
|
|
|
{
|
|
|
|
#ifndef _MSC_VER
|
|
|
|
const char* value = std::getenv("PREFER_GLES_CONTEXT");
|
|
|
|
return (value && std::strcmp(value, "1") == 0);
|
|
|
|
#else
|
|
|
|
char buffer[2] = {};
|
|
|
|
size_t buffer_size = sizeof(buffer);
|
|
|
|
getenv_s(&buffer_size, buffer, "PREFER_GLES_CONTEXT");
|
|
|
|
return (std::strcmp(buffer, "1") == 0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
Context::Context(const WindowInfo& wi) : m_wi(wi) {}
|
|
|
|
|
|
|
|
Context::~Context() = default;
|
|
|
|
|
|
|
|
std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version* versions_to_try,
|
|
|
|
size_t num_versions_to_try)
|
|
|
|
{
|
|
|
|
if (ShouldPreferESContext())
|
|
|
|
{
|
|
|
|
// move ES versions to the front
|
|
|
|
Version* new_versions_to_try = static_cast<Version*>(alloca(sizeof(Version) * num_versions_to_try));
|
|
|
|
size_t count = 0;
|
|
|
|
for (size_t i = 0; i < num_versions_to_try; i++)
|
|
|
|
{
|
|
|
|
if (versions_to_try[i].profile == Profile::ES)
|
|
|
|
new_versions_to_try[count++] = versions_to_try[i];
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < num_versions_to_try; i++)
|
|
|
|
{
|
|
|
|
if (versions_to_try[i].profile != Profile::ES)
|
|
|
|
new_versions_to_try[count++] = versions_to_try[i];
|
|
|
|
}
|
|
|
|
versions_to_try = new_versions_to_try;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Context> context;
|
|
|
|
#if defined(WIN32)
|
|
|
|
context = ContextWGL::Create(wi, versions_to_try, num_versions_to_try);
|
2020-09-13 01:56:56 +00:00
|
|
|
#elif defined(__APPLE__) && !defined(LIBRETRO)
|
2020-05-07 12:48:13 +00:00
|
|
|
context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try);
|
2020-07-06 14:59:49 +00:00
|
|
|
#elif defined(ANDROID)
|
2020-07-07 10:27:06 +00:00
|
|
|
#ifdef USE_EGL
|
2020-07-06 14:59:49 +00:00
|
|
|
context = ContextEGLAndroid::Create(wi, versions_to_try, num_versions_to_try);
|
2020-07-07 10:27:06 +00:00
|
|
|
#endif
|
2020-07-07 11:40:55 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(USE_X11)
|
2020-05-07 12:48:13 +00:00
|
|
|
if (wi.type == WindowInfo::Type::X11)
|
|
|
|
{
|
|
|
|
#ifdef USE_EGL
|
|
|
|
const char* use_egl_x11 = std::getenv("USE_EGL_X11");
|
|
|
|
if (use_egl_x11 && std::strcmp(use_egl_x11, "1") == 0)
|
|
|
|
context = ContextEGLX11::Create(wi, versions_to_try, num_versions_to_try);
|
|
|
|
else
|
|
|
|
context = ContextGLX::Create(wi, versions_to_try, num_versions_to_try);
|
|
|
|
#else
|
|
|
|
context = ContextGLX::Create(wi, versions_to_try, num_versions_to_try);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-07-07 11:40:55 +00:00
|
|
|
#if defined(USE_WAYLAND)
|
|
|
|
if (wi.type == WindowInfo::Type::Wayland)
|
|
|
|
context = ContextEGLWayland::Create(wi, versions_to_try, num_versions_to_try);
|
|
|
|
#endif
|
|
|
|
|
2020-05-07 12:48:13 +00:00
|
|
|
if (!context)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
Log_InfoPrintf("Created a %s context", context->IsGLES() ? "OpenGL ES" : "OpenGL");
|
|
|
|
|
|
|
|
// TODO: Not thread-safe.
|
|
|
|
static Context* context_being_created;
|
|
|
|
context_being_created = context.get();
|
|
|
|
|
|
|
|
// load up glad
|
|
|
|
if (!context->IsGLES())
|
|
|
|
{
|
|
|
|
if (!gladLoadGLLoader([](const char* name) { return context_being_created->GetProcAddress(name); }))
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Failed to load GL functions for GLAD");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!gladLoadGLES2Loader([](const char* name) { return context_being_created->GetProcAddress(name); }))
|
|
|
|
{
|
|
|
|
Log_ErrorPrintf("Failed to load GLES functions for GLAD");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
|
|
|
const char* gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
|
|
|
|
const char* gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
2020-05-25 08:36:52 +00:00
|
|
|
const char* gl_shading_language_version = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
|
2020-05-07 12:48:13 +00:00
|
|
|
Log_InfoPrintf("GL_VENDOR: %s", gl_vendor);
|
|
|
|
Log_InfoPrintf("GL_RENDERER: %s", gl_renderer);
|
|
|
|
Log_InfoPrintf("GL_VERSION: %s", gl_version);
|
2020-05-25 08:36:52 +00:00
|
|
|
Log_InfoPrintf("GL_SHADING_LANGUAGE_VERSION: %s", gl_shading_language_version);
|
2020-05-07 12:48:13 +00:00
|
|
|
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::array<Context::Version, 11>& Context::GetAllDesktopVersionsList()
|
|
|
|
{
|
|
|
|
static constexpr std::array<Version, 11> vlist = {{{Profile::Core, 4, 6},
|
|
|
|
{Profile::Core, 4, 5},
|
|
|
|
{Profile::Core, 4, 4},
|
|
|
|
{Profile::Core, 4, 3},
|
|
|
|
{Profile::Core, 4, 2},
|
|
|
|
{Profile::Core, 4, 1},
|
|
|
|
{Profile::Core, 4, 0},
|
|
|
|
{Profile::Core, 3, 3},
|
|
|
|
{Profile::Core, 3, 2},
|
|
|
|
{Profile::Core, 3, 1},
|
|
|
|
{Profile::Core, 3, 0}}};
|
|
|
|
return vlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::array<Context::Version, 12>& Context::GetAllDesktopVersionsListWithFallback()
|
|
|
|
{
|
|
|
|
static constexpr std::array<Version, 12> vlist = {{{Profile::Core, 4, 6},
|
|
|
|
{Profile::Core, 4, 5},
|
|
|
|
{Profile::Core, 4, 4},
|
|
|
|
{Profile::Core, 4, 3},
|
|
|
|
{Profile::Core, 4, 2},
|
|
|
|
{Profile::Core, 4, 1},
|
|
|
|
{Profile::Core, 4, 0},
|
|
|
|
{Profile::Core, 3, 3},
|
|
|
|
{Profile::Core, 3, 2},
|
|
|
|
{Profile::Core, 3, 1},
|
|
|
|
{Profile::Core, 3, 0},
|
|
|
|
{Profile::NoProfile, 0, 0}}};
|
|
|
|
return vlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::array<Context::Version, 4>& Context::GetAllESVersionsList()
|
|
|
|
{
|
|
|
|
static constexpr std::array<Version, 4> vlist = {
|
|
|
|
{{Profile::ES, 3, 2}, {Profile::ES, 3, 1}, {Profile::ES, 3, 0}, {Profile::ES, 2, 0}}};
|
|
|
|
return vlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::array<Context::Version, 16>& Context::GetAllVersionsList()
|
|
|
|
{
|
|
|
|
static constexpr std::array<Version, 16> vlist = {{{Profile::Core, 4, 6},
|
|
|
|
{Profile::Core, 4, 5},
|
|
|
|
{Profile::Core, 4, 4},
|
|
|
|
{Profile::Core, 4, 3},
|
|
|
|
{Profile::Core, 4, 2},
|
|
|
|
{Profile::Core, 4, 1},
|
|
|
|
{Profile::Core, 4, 0},
|
|
|
|
{Profile::Core, 3, 3},
|
|
|
|
{Profile::Core, 3, 2},
|
|
|
|
{Profile::Core, 3, 1},
|
|
|
|
{Profile::Core, 3, 0},
|
|
|
|
{Profile::ES, 3, 2},
|
|
|
|
{Profile::ES, 3, 1},
|
|
|
|
{Profile::ES, 3, 0},
|
|
|
|
{Profile::ES, 2, 0},
|
|
|
|
{Profile::NoProfile, 0, 0}}};
|
|
|
|
return vlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace GL
|