Files
MosisService/src/main/cpp/egl_context.cpp
2025-12-31 16:12:43 +01:00

164 lines
4.3 KiB
C++

#include "egl_context.h"
#include "logger.h"
#include <glad/gles2.h>
#include <glad/egl.h>
#include <android/native_window_jni.h>
#include <vector>
#include <format>
static void debug_handler(GLenum source, GLenum type,
GLuint id, GLenum severity, GLsizei length, const GLchar* message,
const void* userParam)
{
Logger::Log(std::format("GL Error: {}", std::string_view(message, length)));
}
bool egl::Context::create(ANativeWindow* window)
{
int version = gladLoaderLoadEGL(EGL_NO_DISPLAY);
if (version == 0)
{
Logger::Log("glad failed to load EGL");
return false;
}
if (m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
m_display == EGL_NO_DISPLAY)
{
Logger::Log("eglGetDisplay failed");
return false;
}
EGLint major, minor;
if (!eglInitialize(m_display, &major, &minor))
{
Logger::Log("eglInitialize failed");
return false;
}
version = gladLoadEGL(m_display, eglGetProcAddress);
std::vector<EGLint> config_attribs =
{
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
};
if (window)
{
config_attribs.append_range(std::to_array({
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
}));
}
config_attribs.push_back(EGL_NONE);
EGLint num_configs;
if (!eglChooseConfig(m_display, config_attribs.data(), &m_config, 1, &num_configs) || num_configs == 0)
{
Logger::Log("eglChooseConfig failed");
return false;
}
const EGLint context_attribs[] =
{
EGL_CONTEXT_MAJOR_VERSION, 3,
EGL_CONTEXT_MINOR_VERSION, 2,
EGL_NONE,
};
if (m_context = eglCreateContext(m_display, m_config, EGL_NO_CONTEXT, context_attribs);
m_context == EGL_NO_CONTEXT)
{
Logger::Log("eglCreateContext failed");
return false;
}
if (window)
{
m_surface = eglCreateWindowSurface(m_display, m_config, window, nullptr);
ANativeWindow_acquire(window);
m_native_window = window;
}
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
{
Logger::Log("eglMakeCurrent failed");
return false;
}
int gl_version = gladLoaderLoadGLES2();
if (gl_version == 0)
{
Logger::Log("glad failed to load GLES2");
return false;
}
if (glDebugMessageCallback)
{
glDebugMessageCallback(debug_handler, nullptr);
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
}
return true;
}
void egl::Context::destroy()
{
if (m_display != EGL_NO_DISPLAY)
{
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (m_surface != EGL_NO_SURFACE)
{
eglDestroySurface(m_display, m_surface);
}
if (m_context != EGL_NO_CONTEXT)
{
eglDestroyContext(m_display, m_context);
}
if (m_native_window)
{
ANativeWindow_release(m_native_window);
}
eglTerminate(m_display);
}
m_display = EGL_NO_DISPLAY;
m_context = EGL_NO_CONTEXT;
m_config = EGL_NO_CONFIG_KHR;
m_surface = EGL_NO_SURFACE;
m_native_window = nullptr;
}
egl::Context::Context() :
m_display(EGL_NO_DISPLAY), m_config(EGL_NO_CONFIG_KHR),
m_context(EGL_NO_CONTEXT), m_surface(EGL_NO_SURFACE),
m_native_window(nullptr)
{
Logger::Log("egl::Context::Context");
}
void egl::Context::swap()
{
eglSwapBuffers(m_display, m_surface);
}
bool egl::Context::make_current(ANativeWindow* window)
{
if (window == m_native_window)
{
return true;
}
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (m_surface != EGL_NO_SURFACE)
{
eglDestroySurface(m_display, m_surface);
m_surface = EGL_NO_SURFACE;
}
if (m_native_window)
{
ANativeWindow_release(m_native_window);
m_native_window = nullptr;
}
if (window)
{
m_surface = eglCreateWindowSurface(m_display, m_config, window, nullptr);
ANativeWindow_acquire(window);
m_native_window = window;
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
{
Logger::Log("eglMakeCurrent failed");
return false;
}
}
return true;
}