- Setup Contexts to pull more info from the GPU

- Started outlining OpenGL implementation
This commit is contained in:
2025-07-28 21:06:52 -04:00
parent 7aafa4c9aa
commit 3d4ea4398a
11 changed files with 217 additions and 46 deletions

View File

@@ -189,6 +189,7 @@ add_library(fennec STATIC
# EXTRA SOURCES ======================================================================================================== # EXTRA SOURCES ========================================================================================================
${FENNEC_EXTRA_SOURCES} ${FENNEC_EXTRA_SOURCES}
include/fennec/renderers/interface/renderer.h
) )
add_dependencies(fennec metaprogramming) add_dependencies(fennec metaprogramming)

View File

@@ -162,22 +162,31 @@ management would be used.
Platform support will be implemented in the following order: Platform support will be implemented in the following order:
- Linux/BSD - Linux/BSD
- Wayland - Wayland
- OpenGL (EGL) - OpenGL (EGL)
- XKB
- PulseAudio - PulseAudio
- Vulkan - Vulkan
- X11 - X11
- OpenGL (EGL)
- ALSA - ALSA
- Vulkan - Vulkan
- Microsoft Windows - Microsoft Windows
- XInput - XInput
- OpenGL - OpenGL (WGL)
- DirectSound - WASAPI
- Vulkan - Vulkan
- Android - Android
- OpenGL ES - OpenGL ES
- macOS - AAudio
- iOS - 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. 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. 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 - AI
- **Physics** - **Physics**
- Newtonian Commit - Newtonian Commit
- Apply Forces (Updates Acceleration and Torque) - Apply Forces (Updates Accelerations)
- Apply Torque & Acceleration (Updates Velocities) - Acceleration (Updates Velocities)
- Apply Velocities (Updates Position and Rotation) - Apply Velocities (Updates Position and Rotation)
- Constraint Resolution - Constraint Resolution
- Collision Detection - 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. 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`) ### Structures (`gfx3d`)

View File

@@ -23,18 +23,9 @@ else()
find_package(OpenGL) find_package(OpenGL)
endif() endif()
if(TARGET OpenGL::GL) # Core OpenGL Desktop Profile if(TARGET OpenGL::GL)
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::OpenGL) list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GL)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_OPENGL=1) 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() else()
message(FATAL_ERROR "No Suitable OpenGL implementation found.") message(FATAL_ERROR "No Suitable OpenGL implementation found.")
endif() endif()
@@ -48,5 +39,9 @@ if(FENNEC_GRAPHICS_WANT_EGL)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_EGL=1) list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_EGL=1)
list(APPEND FENNEC_EXTRA_SOURCES list(APPEND FENNEC_EXTRA_SOURCES
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp 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() endif()

View File

@@ -32,6 +32,12 @@ public:
const uint64_t uuid; const uint64_t uuid;
virtual bool connected() = 0; 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 void make_current(gfxsurface* surface) = 0;
virtual ~gfxcontext() = default; virtual ~gfxcontext() = default;

View File

@@ -32,6 +32,11 @@ public:
~eglcontext() override; ~eglcontext() override;
bool connected() 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; void make_current(gfxsurface* surface) override;
@@ -39,7 +44,8 @@ private:
EGLDisplay _egldisplay; EGLDisplay _egldisplay;
EGLContext _eglcontext; EGLContext _eglcontext;
EGLConfig _eglconfig; EGLConfig _eglconfig;
EGLint _eglvmajor, _eglvminor; EGLint _eglvmajor, _eglvminor, _eglctype;
cstring _extensions;
void cleanup(); void cleanup();
}; };

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_RENDERERS_INTERFACE_RENDERER_H
#define FENNEC_RENDERERS_INTERFACE_RENDERER_H
#endif // FENNEC_RENDERERS_INTERFACE_RENDERER_H

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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

View File

@@ -16,11 +16,14 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
#include <fennec/fproc/filesystem/file.h>
#include <fennec/lang/startup.h> #include <fennec/lang/startup.h>
#include <fennec/platform/interface/display.h> #include <fennec/platform/interface/display.h>
#include <fennec/platform/interface/platform.h> #include <fennec/platform/interface/platform.h>
#include <fennec/platform/opengl/egl/context.h> #include <fennec/platform/opengl/egl/context.h>
#include <GL/gl.h>
namespace fennec namespace fennec
{ {
@@ -39,22 +42,15 @@ STATIC_CONSTRUCTOR(_egl_init) {
eglcontext::eglcontext(display* display) eglcontext::eglcontext(display* display)
: gfxcontext(display, "EGL", this) { : gfxcontext(display, "EGL", this) {
// Get the display format
const display::pixel_format& fmt = _display->get_color_format(); const display::pixel_format& fmt = _display->get_color_format();
// Currently empty
EGLint context_attrs[] = { 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 EGL_NONE
}; };
// Configure the depth and rgb bit-depth
EGLint config_attrs[] = { EGLint config_attrs[] = {
EGL_SURFACE_TYPE, EGL_SURFACE_TYPE,
EGL_WINDOW_BIT, EGL_WINDOW_BIT,
@@ -62,50 +58,59 @@ eglcontext::eglcontext(display* display)
EGL_RED_SIZE, fmt.r, EGL_RED_SIZE, fmt.r,
EGL_RED_SIZE, fmt.g, EGL_RED_SIZE, fmt.g,
EGL_RED_SIZE, fmt.b, EGL_RED_SIZE, fmt.b,
EGL_RENDERABLE_TYPE,
#if FENNEC_GRAPHICS_OPENGL EGL_RENDERABLE_TYPE,
EGL_OPENGL_BIT, EGL_OPENGL_BIT, // 7
#elif FENNEC_GRAPHICS_GLES3
EGL_OPENGL_ES3_BIT,
#elif FENNEC_GRAPHICS_GLES2
EGL_OPENGL_ES2_BIT,
#endif
EGL_NONE EGL_NONE
}; };
// Attempt to retrieve an egl display from the native display
_egldisplay = eglGetDisplay(_display->get_native_handle()); _egldisplay = eglGetDisplay(_display->get_native_handle());
if (_egldisplay == nullptr) { if (_egldisplay == nullptr) {
cleanup(); cleanup();
return; return;
} }
if (not eglInitialize(_egldisplay, &_eglvmajor, &_eglvminor)) { // Attempt to initialize egl
if (not eglInitialize(_egldisplay, nullptr, nullptr)) {
cleanup(); cleanup();
return; return;
} }
#if FENNEC_GRAPHICS_OPENGL // Attempt to bind to Core OpenGL, otherwise OpenGL ES
if (not eglBindAPI(EGL_OPENGL_API)) { if (not eglBindAPI(EGL_OPENGL_API)) {
#elif FENNEC_GRAPHICS_GLES3 or FENNEC_GRAPHICS_GLES2 if (not eglBindAPI(EGL_OPENGL_ES_API)) {
if (not eglBindAPI(EGL_OPENGL_ES_API)) { cleanup();
#endif return;
cleanup(); }
return; config_attrs[7] = EGL_OPENGL_ES_BIT; // Change the support bit to OpenGL ES
} }
// Select a configuration
EGLint n; EGLint n;
if (not eglChooseConfig(_egldisplay, config_attrs, &_eglconfig, 1, &n)) { if (not eglChooseConfig(_egldisplay, config_attrs, &_eglconfig, 1, &n)) {
cleanup(); cleanup();
return; return;
} }
// Create the context
_eglcontext = eglCreateContext(_egldisplay, _eglconfig, EGL_NO_CONTEXT, context_attrs); _eglcontext = eglCreateContext(_egldisplay, _eglconfig, EGL_NO_CONTEXT, context_attrs);
if (_eglcontext == nullptr) { if (_eglcontext == nullptr) {
cleanup(); cleanup();
return; 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() { eglcontext::~eglcontext() {
@@ -116,6 +121,22 @@ bool eglcontext::connected() {
return _eglcontext != nullptr; 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*) { void eglcontext::make_current(gfxsurface*) {
} }

View File

@@ -19,7 +19,10 @@
#ifndef FENNEC_TEST_PLATFORM_H #ifndef FENNEC_TEST_PLATFORM_H
#define FENNEC_TEST_PLATFORM_H #define FENNEC_TEST_PLATFORM_H
#include "../test.h"
#include <fennec/platform/interface/display.h> #include <fennec/platform/interface/display.h>
#include <fennec/platform/interface/gfxcontext.h>
#include <fennec/platform/interface/platform.h> #include <fennec/platform/interface/platform.h>
@@ -34,6 +37,10 @@ inline void fennec_test_platform() {
fennec_test_run(instance->get_display() != nullptr, true); fennec_test_run(instance->get_display() != nullptr, true);
fennec_test_run(instance->get_display()->get_context() != 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(); instance->shutdown();
} }