#include "egl_context.h" #include "logger.h" #include #include #include #include #include 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 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; }