From 3d4ea4398aef905d55bf084ece4d934629b23622 Mon Sep 17 00:00:00 2001 From: Medusa Slockbower Date: Mon, 28 Jul 2025 21:06:52 -0400 Subject: [PATCH] - Setup Contexts to pull more info from the GPU - Started outlining OpenGL implementation --- CMakeLists.txt | 1 + PLANNING.md | 34 +++++++-- cmake/opengl.cmake | 17 ++--- .../fennec/platform/interface/gfxcontext.h | 6 ++ include/fennec/platform/opengl/egl/context.h | 8 +- include/fennec/renderers/interface/renderer.h | 22 ++++++ include/fennec/renderers/opengl/fallback.h | 34 +++++++++ include/fennec/renderers/opengl/legacy.h | 27 +++++++ include/fennec/renderers/opengl/modern.h | 34 +++++++++ source/platform/opengl/egl/context.cpp | 73 ++++++++++++------- test/tests/test_platform.h | 7 ++ 11 files changed, 217 insertions(+), 46 deletions(-) create mode 100644 include/fennec/renderers/interface/renderer.h create mode 100644 include/fennec/renderers/opengl/fallback.h create mode 100644 include/fennec/renderers/opengl/legacy.h create mode 100644 include/fennec/renderers/opengl/modern.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e4a922d..e565a35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,6 +189,7 @@ add_library(fennec STATIC # EXTRA SOURCES ======================================================================================================== ${FENNEC_EXTRA_SOURCES} + include/fennec/renderers/interface/renderer.h ) add_dependencies(fennec metaprogramming) diff --git a/PLANNING.md b/PLANNING.md index c4a9a39..a48c533 100644 --- a/PLANNING.md +++ b/PLANNING.md @@ -162,22 +162,31 @@ management would be used. Platform support will be implemented in the following order: - Linux/BSD - Wayland - - OpenGL (EGL) + - OpenGL (EGL) ✔ + - XKB - PulseAudio - Vulkan - X11 - - OpenGL (EGL) - ALSA - Vulkan - Microsoft Windows - XInput - - OpenGL - - DirectSound + - OpenGL (WGL) + - WASAPI - Vulkan - Android - OpenGL ES - - macOS - - iOS + - AAudio + - openslES + - macOS/iOS + - cocoa + - OpenGL + - Core Audio + - Vulkan + - Metal + +Linux Wayland will be implemented first. Once setup, the core engine will be implemented and tested on top of Wayland. +Once the engine is in a stable state, then support for other platforms will be resumed. Most consoles will never get official platform support due to NDAs which conflict with the principles of this engine. fennec will avoid using proprietary libraries except when strictly necessary, such as support for Windows and MacOS. @@ -328,8 +337,8 @@ in their operation order: - AI - **Physics** - Newtonian Commit - - Apply Forces (Updates Acceleration and Torque) - - Apply Torque & Acceleration (Updates Velocities) + - Apply Forces (Updates Accelerations) + - Acceleration (Updates Velocities) - Apply Velocities (Updates Position and Rotation) - Constraint Resolution - Collision Detection @@ -453,6 +462,15 @@ This allows the GPU to draw every single deferred rendered mesh in a single draw Specifications for debugging views via early breaks are included in the stages. +There will be three profiles for OpenGL implementation: + - modern + - fallback + - legacy + +All profiles will have the same feature set, however their implementations will differ. +The modern context will use up-to-date features to get as much performance out of the pipeline as +possible. + ### Structures (`gfx3d`) diff --git a/cmake/opengl.cmake b/cmake/opengl.cmake index da9e597..83f45d9 100644 --- a/cmake/opengl.cmake +++ b/cmake/opengl.cmake @@ -23,18 +23,9 @@ else() find_package(OpenGL) endif() -if(TARGET OpenGL::GL) # Core OpenGL Desktop Profile - list(APPEND FENNEC_LINK_LIBRARIES OpenGL::OpenGL) +if(TARGET OpenGL::GL) + list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GL) list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_OPENGL=1) - -elseif(TARGET OpenGL::GLES3) # OpenGL for Embedded Systems 3 - list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GLES3) - list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_GLES3=1) - -elseif (TARGET OpenGL::GLES2) # OpenGL for Embedded Systems 2 - list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GLES2) - list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_GLES2=1) - else() message(FATAL_ERROR "No Suitable OpenGL implementation found.") endif() @@ -48,5 +39,9 @@ if(FENNEC_GRAPHICS_WANT_EGL) list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_EGL=1) list(APPEND FENNEC_EXTRA_SOURCES include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp + + include/fennec/renderers/opengl/modern.h + include/fennec/renderers/opengl/fallback.h + include/fennec/renderers/opengl/legacy.h ) endif() \ No newline at end of file diff --git a/include/fennec/platform/interface/gfxcontext.h b/include/fennec/platform/interface/gfxcontext.h index 2c06868..7b2ff94 100644 --- a/include/fennec/platform/interface/gfxcontext.h +++ b/include/fennec/platform/interface/gfxcontext.h @@ -32,6 +32,12 @@ public: const uint64_t uuid; virtual bool connected() = 0; + virtual int32_t get_version_major() = 0; + virtual int32_t get_version_minor() = 0; + virtual int32_t get_context_version() = 0; + virtual const cstring& get_context_name() = 0; + + virtual bool check_extension(const cstring& ext) = 0; virtual void make_current(gfxsurface* surface) = 0; virtual ~gfxcontext() = default; diff --git a/include/fennec/platform/opengl/egl/context.h b/include/fennec/platform/opengl/egl/context.h index 896c5c7..b81ecb4 100644 --- a/include/fennec/platform/opengl/egl/context.h +++ b/include/fennec/platform/opengl/egl/context.h @@ -32,6 +32,11 @@ public: ~eglcontext() override; bool connected() override; + int32_t get_version_major() override { return _eglvmajor; } + int32_t get_version_minor() override { return _eglvminor; } + int32_t get_context_version() override { return _eglctype; } + const cstring& get_context_name() override; + bool check_extension(const cstring& ext) override; void make_current(gfxsurface* surface) override; @@ -39,7 +44,8 @@ private: EGLDisplay _egldisplay; EGLContext _eglcontext; EGLConfig _eglconfig; - EGLint _eglvmajor, _eglvminor; + EGLint _eglvmajor, _eglvminor, _eglctype; + cstring _extensions; void cleanup(); }; diff --git a/include/fennec/renderers/interface/renderer.h b/include/fennec/renderers/interface/renderer.h new file mode 100644 index 0000000..0732b5e --- /dev/null +++ b/include/fennec/renderers/interface/renderer.h @@ -0,0 +1,22 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_RENDERERS_INTERFACE_RENDERER_H +#define FENNEC_RENDERERS_INTERFACE_RENDERER_H + +#endif // FENNEC_RENDERERS_INTERFACE_RENDERER_H diff --git a/include/fennec/renderers/opengl/fallback.h b/include/fennec/renderers/opengl/fallback.h new file mode 100644 index 0000000..d23ab59 --- /dev/null +++ b/include/fennec/renderers/opengl/fallback.h @@ -0,0 +1,34 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_RENDERERS_OPENGL_FALLBACK_H +#define FENNEC_RENDERERS_OPENGL_FALLBACK_H + +/* + * This should be implemented using the OpenGL ES 3.2 profile + * https://registry.khronos.org/OpenGL/specs/es/3.2/es_spec_3.2.pdf + * + * Requires the following: + * OpenGL ES 3.2 / OpenGL 4.3 OR + * - EXT_texture_array + * - ARB_compute_shader + * - ARB_shader_image_load_store + * - ARB_texture_cube_map_array + */ + +#endif // FENNEC_RENDERERS_OPENGL_FALLBACK_H diff --git a/include/fennec/renderers/opengl/legacy.h b/include/fennec/renderers/opengl/legacy.h new file mode 100644 index 0000000..e610e0f --- /dev/null +++ b/include/fennec/renderers/opengl/legacy.h @@ -0,0 +1,27 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_RENDERERS_OPENGL_LEGACY_H +#define FENNEC_RENDERERS_OPENGL_LEGACY_H + +/* + * This should be implemented using the OpenGL ES 2.0 profile + * https://registry.khronos.org/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf + */ + +#endif // FENNEC_RENDERERS_OPENGL_LEGACY_H diff --git a/include/fennec/renderers/opengl/modern.h b/include/fennec/renderers/opengl/modern.h new file mode 100644 index 0000000..58c1427 --- /dev/null +++ b/include/fennec/renderers/opengl/modern.h @@ -0,0 +1,34 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_RENDERERS_OPENGL_MODERN_H +#define FENNEC_RENDERERS_OPENGL_MODERN_H + +/* + * + * Requires the following: + * OpenGL 4.6 OR + * - ARB_shader_draw_parameters + * - ARB_multi_draw_indirect + * - EXT_texture_array + * - ARB_compute_shader + * - ARB_shader_image_load_store + * - ARB_texture_cube_map_array + */ + +#endif // FENNEC_RENDERERS_OPENGL_MODERN_H diff --git a/source/platform/opengl/egl/context.cpp b/source/platform/opengl/egl/context.cpp index 2769e8d..d6ffd2e 100644 --- a/source/platform/opengl/egl/context.cpp +++ b/source/platform/opengl/egl/context.cpp @@ -16,11 +16,14 @@ // along with this program. If not, see . // ===================================================================================================================== +#include #include #include #include #include +#include + namespace fennec { @@ -39,22 +42,15 @@ STATIC_CONSTRUCTOR(_egl_init) { eglcontext::eglcontext(display* display) : gfxcontext(display, "EGL", this) { + // Get the display format const display::pixel_format& fmt = _display->get_color_format(); + // Currently empty EGLint context_attrs[] = { -#if FENNEC_GRAPHICS_OPENGL - EGL_CONTEXT_MAJOR_VERSION, 4, - EGL_CONTEXT_MINOR_VERSION, 3, -#elif FENNEC_GRAPHICS_GLES3 - EGL_CONTEXT_MAJOR_VERSION, 3, - EGL_CONTEXT_MINOR_VERSION, 2, -#elif FENNEC_GRAPHICS_GLES2 - EGL_CONTEXT_MAJOR_VERSION, 2, - EGL_CONTEXT_MINOR_VERSION, 0, -#endif EGL_NONE }; + // Configure the depth and rgb bit-depth EGLint config_attrs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, @@ -62,50 +58,59 @@ eglcontext::eglcontext(display* display) EGL_RED_SIZE, fmt.r, EGL_RED_SIZE, fmt.g, EGL_RED_SIZE, fmt.b, - EGL_RENDERABLE_TYPE, -#if FENNEC_GRAPHICS_OPENGL - EGL_OPENGL_BIT, -#elif FENNEC_GRAPHICS_GLES3 - EGL_OPENGL_ES3_BIT, -#elif FENNEC_GRAPHICS_GLES2 - EGL_OPENGL_ES2_BIT, -#endif + EGL_RENDERABLE_TYPE, + EGL_OPENGL_BIT, // 7 EGL_NONE }; - + // Attempt to retrieve an egl display from the native display _egldisplay = eglGetDisplay(_display->get_native_handle()); if (_egldisplay == nullptr) { cleanup(); return; } - if (not eglInitialize(_egldisplay, &_eglvmajor, &_eglvminor)) { + // Attempt to initialize egl + if (not eglInitialize(_egldisplay, nullptr, nullptr)) { cleanup(); return; } -#if FENNEC_GRAPHICS_OPENGL + // Attempt to bind to Core OpenGL, otherwise OpenGL ES if (not eglBindAPI(EGL_OPENGL_API)) { -#elif FENNEC_GRAPHICS_GLES3 or FENNEC_GRAPHICS_GLES2 - if (not eglBindAPI(EGL_OPENGL_ES_API)) { -#endif - cleanup(); - return; + if (not eglBindAPI(EGL_OPENGL_ES_API)) { + cleanup(); + return; + } + config_attrs[7] = EGL_OPENGL_ES_BIT; // Change the support bit to OpenGL ES } + // Select a configuration EGLint n; if (not eglChooseConfig(_egldisplay, config_attrs, &_eglconfig, 1, &n)) { cleanup(); return; } + // Create the context _eglcontext = eglCreateContext(_egldisplay, _eglconfig, EGL_NO_CONTEXT, context_attrs); if (_eglcontext == nullptr) { cleanup(); return; } + + // make this the current context so we can retrieve the information below + eglMakeCurrent(_egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, _eglcontext); + + // Query available extensions + const char* ptr = eglQueryString(_egldisplay, EGL_EXTENSIONS); + _extensions = { ptr, strlen(ptr) + 1 }; + + // Query the context and version + eglQueryContext(_egldisplay, _eglcontext, EGL_CONTEXT_CLIENT_TYPE, &_eglctype); + glGetIntegerv(GL_MAJOR_VERSION, &_eglvmajor); + glGetIntegerv(GL_MINOR_VERSION, &_eglvminor); } eglcontext::~eglcontext() { @@ -116,6 +121,22 @@ bool eglcontext::connected() { return _eglcontext != nullptr; } +const cstring& eglcontext::get_context_name() { + static constexpr cstring opengl = "OpenGL"; + static constexpr cstring gles = "GLES"; + static constexpr cstring openvg = "OpenVG"; // this should never be used + switch (_eglctype) { + default: + case EGL_OPENGL_API: return opengl; + case EGL_OPENGL_ES_API: return gles; + case EGL_OPENVG_API: return openvg; + } +} + +bool eglcontext::check_extension(const cstring& ext) { + return _extensions.find(ext) != _extensions.size(); +} + void eglcontext::make_current(gfxsurface*) { } diff --git a/test/tests/test_platform.h b/test/tests/test_platform.h index bc275e8..c9d3ed8 100644 --- a/test/tests/test_platform.h +++ b/test/tests/test_platform.h @@ -19,7 +19,10 @@ #ifndef FENNEC_TEST_PLATFORM_H #define FENNEC_TEST_PLATFORM_H +#include "../test.h" + #include +#include #include @@ -34,6 +37,10 @@ inline void fennec_test_platform() { fennec_test_run(instance->get_display() != nullptr, true); fennec_test_run(instance->get_display()->get_context() != nullptr, true); + std::cout << instance->get_display()->get_context()->get_context_name() << " "; + std::cout << instance->get_display()->get_context()->get_version_major() << "."; + std::cout << instance->get_display()->get_context()->get_version_minor() << std::endl; + instance->shutdown(); }