Compare commits

..

2 Commits

Author SHA1 Message Date
cbcd699ab0 - Decided to remove boost due to extensive dependencies
- Huge refactor on Wayland loading to support retrieval of Protocol headers
 - Setup EGL to create surfaces for Wayland windows
2025-08-22 02:15:57 -04:00
ff27caab4f - Fixed some variable naming with graph and it's PrettyPrinter
- Added boost-atomic and boost-thread as dependencies for concurrency support
2025-08-21 06:44:22 -04:00
50 changed files with 10644 additions and 2528 deletions

View File

@@ -20,14 +20,29 @@ cmake_minimum_required(VERSION 3.30)
project(fennec) project(fennec)
# External dependencies should be loaded here # External dependencies should be loaded here
# CppTrace is a dependency of the project, added as a git submodule
add_subdirectory(external/cpptrace) add_subdirectory(external/cpptrace)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_C_STANDARD 23) set(CMAKE_C_STANDARD 23)
set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(fennec-dependencies
COMMAND ${CMAKE_COMMAND} -E echo "Running dependencies."
COMMENT "Running dependencies."
)
macro(fennec_add_sources)
list(APPEND FENNEC_EXTRA_SOURCES ${ARGN})
endmacro()
macro(fennec_add_definitions)
list(APPEND FENNEC_COMPILE_DEFINITIONS ${ARGN})
endmacro()
macro(fennec_add_link_libraries)
list(APPEND FENNEC_LINK_LIBRARIES ${ARGN})
endmacro()
# include scripts # include scripts
include("${FENNEC_SOURCE_DIR}/cmake/version.cmake") include("${FENNEC_SOURCE_DIR}/cmake/version.cmake")
include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake") include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake")
@@ -85,6 +100,7 @@ add_library(fennec STATIC
include/fennec/containers/set.h include/fennec/containers/set.h
include/fennec/containers/traversal.h include/fennec/containers/traversal.h
include/fennec/containers/tuple.h include/fennec/containers/tuple.h
include/fennec/containers/variant.h
include/fennec/containers/detail/_tuple.h include/fennec/containers/detail/_tuple.h
@@ -138,11 +154,6 @@ add_library(fennec STATIC
include/fennec/memory/detail/_ptr_traits.h include/fennec/memory/detail/_ptr_traits.h
# CONCURRENCY ==========================================================================================================
include/fennec/concurrency/thread.h
include/fennec/concurrency/mutex.h
include/fennec/concurrency/atomic.h
# DEBUG ================================================================================================================ # DEBUG ================================================================================================================
source/debug/assert_impl.cpp source/debug/assert_impl.cpp
@@ -203,15 +214,15 @@ add_library(fennec STATIC
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
include/fennec/platform/interface/display.h source/platform/interface/display.cpp include/fennec/platform/interface/display.h source/platform/interface/display.cpp
include/fennec/platform/interface/gfxcontext.h include/fennec/platform/interface/gfxcontext.h
include/fennec/platform/interface/gfxsurface.h
# EXTRA SOURCES ======================================================================================================== # EXTRA SOURCES ========================================================================================================
${FENNEC_EXTRA_SOURCES} ${FENNEC_EXTRA_SOURCES}
include/fennec/containers/variant.h
) )
add_dependencies(fennec metaprogramming) add_dependencies(fennec metaprogramming fennec-dependencies)
target_compile_definitions(fennec PUBLIC target_compile_definitions(fennec PUBLIC
${FENNEC_COMPILE_DEFINITIONS} ${FENNEC_COMPILE_DEFINITIONS}
@@ -223,8 +234,9 @@ target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS}) # Do not comp
# This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated # This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
target_link_libraries(fennec PRIVATE target_link_libraries(fennec PRIVATE
cpptrace::cpptrace
${FENNEC_LINK_LIBRARIES} ${FENNEC_LINK_LIBRARIES}
cpptrace::cpptrace
) )

View File

@@ -3,7 +3,7 @@
# Readings # Readings
Here is a list of relevant books and articles on various concepts related to Here is a list of relevant books and articles on various concepts related to
developing a game engine and its subsystems. developing a game engine and its subsystems.
- Game Engine Architecture, Ed. 3 – Jason Gregory - Game Engine Architecture, Ed. 3 – Jason Gregory

View File

@@ -90,7 +90,7 @@ fennec Standards:
immediate events to listeners so that outside functionality may decide how to handle the impending crash. immediate events to listeners so that outside functionality may decide how to handle the impending crash.
In Debug Mode there is nothing that can be done to stop the crash, as soon as the branch finishes, In Debug Mode there is nothing that can be done to stop the crash, as soon as the branch finishes,
`abort()` will be called. `abort()` will be called.
<br> <br>

View File

@@ -22,4 +22,4 @@ add_compile_options("-mxsave" "-Wall" "-Wextra" "-pedantic" "-Werror")
set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates") set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER_GCC=1 FENNEC_NO_INLINE=[[gnu::noinline]]) list(APPEND FENNEC_COMPILE_DEFINITIONS _GLIBCXX_INCLUDE_NEXT_C_HEADERS FENNEC_COMPILER_GCC=1 FENNEC_NO_INLINE=[[gnu::noinline]])

View File

@@ -23,13 +23,13 @@ macro(fennec_check_platform)
include("${FENNEC_SOURCE_DIR}/cmake/unix.cmake") include("${FENNEC_SOURCE_DIR}/cmake/unix.cmake")
# compile definitions # compile definitions
list(APPEND FENNEC_COMPILE_DEFINITIONS fennec_add_definitions(
FENNEC_PLATFORM_NAME="Linux" FENNEC_PLATFORM_NAME="Linux"
FENNEC_PLATFORM_LINUX=1 FENNEC_PLATFORM_LINUX=1
) )
# extra source files # extra source files
list(APPEND FENNEC_EXTRA_SOURCES fennec_add_sources(
include/fennec/platform/linux/platform.h source/platform/linux/platform.cpp include/fennec/platform/linux/platform.h source/platform/linux/platform.cpp
) )

View File

@@ -27,8 +27,8 @@ endif()
if(TARGET OpenGL::GL AND TARGET GLEW::GLEW) if(TARGET OpenGL::GL AND TARGET GLEW::GLEW)
message(STATUS "Found OpenGL: ${OPENGL_gl_LIBRARY}") message(STATUS "Found OpenGL: ${OPENGL_gl_LIBRARY}")
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GL GLEW::GLEW) fennec_add_link_libraries(OpenGL::GL GLEW::GLEW)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_OPENGL=1) fennec_add_definitions(FENNEC_GRAPHICS_OPENGL=1)
else() else()
message(FATAL_ERROR "No Suitable OpenGL implementation found.") message(FATAL_ERROR "No Suitable OpenGL implementation found.")
endif() endif()
@@ -39,15 +39,19 @@ if(FENNEC_GRAPHICS_WANT_EGL)
endif() endif()
message(STATUS "Found EGL: ${OPENGL_egl_LIBRARY}") message(STATUS "Found EGL: ${OPENGL_egl_LIBRARY}")
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::EGL)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_EGL=1) fennec_add_link_libraries(OpenGL::EGL)
list(APPEND FENNEC_EXTRA_SOURCES fennec_add_definitions(FENNEC_GRAPHICS_EGL=1)
fennec_add_sources(
include/fennec/platform/opengl/lib/fwd.h include/fennec/platform/opengl/lib/fwd.h
include/fennec/platform/opengl/lib/enum.h include/fennec/platform/opengl/lib/enum.h
include/fennec/platform/opengl/lib/buffer.h include/fennec/platform/opengl/lib/buffer.h
include/fennec/platform/opengl/lib/texture.h include/fennec/platform/opengl/lib/texture.h
include/fennec/platform/opengl/lib/vertex_array.h include/fennec/platform/opengl/lib/vertex_array.h
include/fennec/platform/opengl/egl/fwd.h
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/platform/opengl/egl/surface.h source/platform/opengl/egl/surface.cpp
) )
endif() endif()

View File

@@ -19,11 +19,11 @@
# generic unix functionality # generic unix functionality
# compile definitions # compile definitions
list(APPEND FENNEC_COMPILE_DEFINITIONS fennec_add_definitions(
FENNEC_PLATFORM_UNIX=1 FENNEC_PLATFORM_UNIX=1
) )
# extra source files # extra source files
list(APPEND FENNEC_EXTRA_SOURCES fennec_add_sources(
include/fennec/platform/unix/platform.h source/platform/unix/platform.cpp include/fennec/platform/unix/platform.h source/platform/unix/platform.cpp
) )

View File

@@ -19,6 +19,20 @@
# https://gist.github.com/mariobadr/acc3c8adf4b4e722705be38c3deac59a # https://gist.github.com/mariobadr/acc3c8adf4b4e722705be38c3deac59a
# this script finds libwayland and dependencies # this script finds libwayland and dependencies
# some of this code is based on SDL3's use of wayland-scanner
macro(fennec_wayland_get_header _SCANNER _XML _FILE)
set(_WAYLAND_PROT_H_CODE "${WAYLAND_HEADERS_DIR}/${_FILE}-client-protocols.h")
add_custom_command(
TARGET fennec-dependencies PRE_BUILD
COMMAND ${_SCANNER}
ARGS client-header "${_XML}" "${_WAYLAND_PROT_H_CODE}"
)
fennec_add_sources(${_WAYLAND_PROT_H_CODE})
endmacro()
macro(fennec_check_wayland) macro(fennec_check_wayland)
set(WAYLAND_CLIENT_FOUND 0) set(WAYLAND_CLIENT_FOUND 0)
@@ -30,6 +44,7 @@ macro(fennec_check_wayland)
WAYLAND_CLIENT_LIBRARY WAYLAND_CLIENT_LIBRARY
NAMES wayland-client libwayland-client NAMES wayland-client libwayland-client
) )
find_program(WAYLAND_SCANNER NAMES wayland-scanner)
# EGL is required # EGL is required
find_path( find_path(
@@ -41,13 +56,29 @@ macro(fennec_check_wayland)
NAMES wayland-egl libwayland-egl NAMES wayland-egl libwayland-egl
) )
if( (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY) if( (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY AND WAYLAND_SCANNER)
AND (WAYLAND_EGL_INCLUDE_DIR AND WAYLAND_EGL_LIBRARY)) AND (WAYLAND_EGL_INCLUDE_DIR AND WAYLAND_EGL_LIBRARY))
message(STATUS "Found Wayland: ${WAYLAND_CLIENT_LIBRARY}") message(STATUS "Found Wayland: ${WAYLAND_CLIENT_LIBRARY}")
set(WAYLAND_PROTOCOLS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/protocols)
set(WAYLAND_HEADERS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/headers)
# Search for base protocol xml
find_file(WAYLAND_PROTOCOL NAMES wayland.xml PATHS /usr/share/wayland /usr/share/wayland-protocols)
file(COPY ${WAYLAND_PROTOCOL} DESTINATION ${WAYLAND_PROTOCOLS_DIR})
# include sub-dependencies
include("${FENNEC_SOURCE_DIR}/cmake/xkb.cmake") include("${FENNEC_SOURCE_DIR}/cmake/xkb.cmake")
fennec_check_xkb() fennec_check_xkb()
# generate protocols, based on SDL3
file(GLOB WAYLAND_PROTOCOLS_XML RELATIVE "${WAYLAND_PROTOCOLS_DIR}" "${WAYLAND_PROTOCOLS_DIR}/*.xml")
foreach(_XML IN LISTS WAYLAND_PROTOCOLS_XML)
get_filename_component(_FILE ${_XML} NAME_WLE)
fennec_wayland_get_header("${WAYLAND_SCANNER}" "${WAYLAND_PROTOCOLS_DIR}/${_XML}" "${_FILE}")
endforeach()
# Add sources and libraries
get_filename_component( get_filename_component(
WAYLAND_CLIENT_LIBRARY WAYLAND_CLIENT_LIBRARY
${WAYLAND_CLIENT_LIBRARY} ${WAYLAND_CLIENT_LIBRARY}
@@ -63,19 +94,19 @@ macro(fennec_check_wayland)
set(WAYLAND_EGL_FOUND 1) set(WAYLAND_EGL_FOUND 1)
set(FENNEC_GRAPHICS_WANT_EGL 1) set(FENNEC_GRAPHICS_WANT_EGL 1)
list(APPEND FENNEC_EXTRA_SOURCES fennec_add_sources(
# Dynamic Library Files # Dynamic Library Files
include/fennec/platform/linux/wayland/lib/fwd.h include/fennec/platform/linux/wayland/lib/fwd.h
include/fennec/platform/linux/wayland/lib/sym.h include/fennec/platform/linux/wayland/lib/sym.h
include/fennec/platform/linux/wayland/lib/wayland-client.h include/fennec/platform/linux/wayland/lib/wayland.h
include/fennec/platform/linux/wayland/lib/wayland-util.h
include/fennec/platform/linux/wayland/lib/loader.h source/platform/linux/wayland/lib/loader.cpp include/fennec/platform/linux/wayland/lib/loader.h source/platform/linux/wayland/lib/loader.cpp
# Fennec Files # Fennec Files
include/fennec/platform/linux/wayland/display.h source/platform/linux/wayland/display.cpp include/fennec/platform/linux/wayland/display.h source/platform/linux/wayland/display.cpp
include/fennec/platform/linux/wayland/window.h source/platform/linux/wayland/window.cpp
) )
list(APPEND FENNEC_COMPILE_DEFINITIONS fennec_add_definitions(
FENNEC_HAS_WAYLAND=1 FENNEC_HAS_WAYLAND=1
FENNEC_LIB_WAYLAND="${WAYLAND_CLIENT_LIBRARY}" FENNEC_LIB_WAYLAND="${WAYLAND_CLIENT_LIBRARY}"
FENNEC_LIB_WAYLAND_EGL="${WAYLAND_EGL_LIBRARY}" FENNEC_LIB_WAYLAND_EGL="${WAYLAND_EGL_LIBRARY}"

View File

@@ -41,7 +41,7 @@ macro(fennec_check_xkb)
set(XKB_FOUND 1) set(XKB_FOUND 1)
list(APPEND FENNEC_EXTRA_SOURCES fennec_add_sources(
# Dynamic Library Files # Dynamic Library Files
include/fennec/platform/linux/xkb/lib/fwd.h include/fennec/platform/linux/xkb/lib/fwd.h
include/fennec/platform/linux/xkb/lib/sym.h include/fennec/platform/linux/xkb/lib/sym.h
@@ -51,7 +51,7 @@ macro(fennec_check_xkb)
# Fennec files # Fennec files
) )
list(APPEND FENNEC_COMPILE_DEFINITIONS fennec_add_definitions(
FENNEC_HAS_XKB=1 FENNEC_HAS_XKB=1
FENNEC_LIB_XKB="${XKB_LIBRARY}" FENNEC_LIB_XKB="${XKB_LIBRARY}"
) )

View File

@@ -396,10 +396,10 @@ class GraphPrinter:
class Iterator: class Iterator:
def __init__(self, val): def __init__(self, val):
self.node_pool = val['_node_pool']['_table']['_alloc']['_data'] self.node_pool = val['_vertex_pool']['_table']['_alloc']['_data']
self.max_nodes = val['_node_pool']['_table']['_alloc']['_capacity'] self.max_nodes = val['_vertex_pool']['_table']['_alloc']['_capacity']
self.conn_map = val['_conn_map']['_alloc']['_data'] self.conn_map = val['_edge_map']['_alloc']['_data']
self.max_conn = val['_conn_map']['_size'] self.max_conn = val['_edge_map']['_size']
self.index = 0 self.index = 0
def __iter__(self): def __iter__(self):
@@ -447,7 +447,7 @@ class GraphPrinter:
def __init__(self, val): def __init__(self, val):
self.val = val self.val = val
self.size = val['_node_pool']['_size'] self.size = val['_vertex_pool']['_size']
def to_string(self): def to_string(self):
if self.size == 0: if self.size == 0:

View File

@@ -1,22 +0,0 @@
// =====================================================================================================================
// 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_CONCURRENCY_THREAD_H
#define FENNEC_CONCURRENCY_THREAD_H
#endif // FENNEC_CONCURRENCY_THREAD_H

View File

@@ -149,7 +149,7 @@ public:
/// ///
/// \returns The number of edges in the graph /// \returns The number of edges in the graph
constexpr size_t num_edges() const { constexpr size_t num_edges() const {
return _conn_pool.size(); return _edge_pool.size();
} }
/// ///
@@ -170,7 +170,7 @@ public:
/// \param b The second vertex /// \param b The second vertex
/// \returns `true` if the edge exists, `false` otherwise /// \returns `true` if the edge exists, `false` otherwise
constexpr bool exists(size_t a, size_t b) const { constexpr bool exists(size_t a, size_t b) const {
return _conn_map[a][b] != nullptr; return _edge_map[a][b] != nullptr;
} }
/// ///
@@ -189,8 +189,8 @@ public:
/// \param b The second vertex /// \param b The second vertex
/// \returns `true` if both edges exist, `false` otherwise /// \returns `true` if both edges exist, `false` otherwise
constexpr bool is_undirected(size_t a, size_t b) const { constexpr bool is_undirected(size_t a, size_t b) const {
const auto* e0 = _conn_map[a][b]; const auto* e0 = _edge_map[a][b];
const auto* e1 = _conn_map[b][a]; const auto* e1 = _edge_map[b][a];
if (not (e0 != nullptr && e1 != nullptr)) { if (not (e0 != nullptr && e1 != nullptr)) {
return false; return false;
} }
@@ -232,9 +232,9 @@ public:
if (empty()) { if (empty()) {
return nullptr; return nullptr;
} }
edge_t* it = _conn_map[a][b]; edge_t* it = _edge_map[a][b];
if (it) { if (it) {
return _conn_pool[*it]; return _edge_pool[*it];
} }
return nullptr; return nullptr;
} }
@@ -248,9 +248,9 @@ public:
if (empty()) { if (empty()) {
return nullptr; return nullptr;
} }
const edge_t* it = _conn_map[a][b]; const edge_t* it = _edge_map[a][b];
if (it) { if (it) {
return _conn_pool[*it]; return _edge_pool[*it];
} }
return nullptr; return nullptr;
} }
@@ -261,10 +261,10 @@ public:
/// \returns A list containing all vertices `x` with edges from `vertex` to `x...` /// \returns A list containing all vertices `x` with edges from `vertex` to `x...`
list<size_t> outgoing(size_t vertex) { list<size_t> outgoing(size_t vertex) {
list<size_t> res; list<size_t> res;
if (empty() || vertex >= _conn_map.size()) { if (empty() || vertex >= _edge_map.size()) {
return res; return res;
} }
for (const auto& it : _conn_map[vertex]) { for (const auto& it : _edge_map[vertex]) {
res.push_back(it.first); res.push_back(it.first);
} }
return res; return res;
@@ -276,11 +276,11 @@ public:
/// \returns A list containing all vertices `x` with edges from `x...` to `vertex` /// \returns A list containing all vertices `x` with edges from `x...` to `vertex`
list<size_t> incoming(size_t vertex) { list<size_t> incoming(size_t vertex) {
list<size_t> res; list<size_t> res;
if (empty() || vertex >= _conn_map.size()) { if (empty() || vertex >= _edge_map.size()) {
return res; return res;
} }
for (size_t n = 0; n < _conn_map.size(); ++n) { for (size_t n = 0; n < _edge_map.size(); ++n) {
if (_conn_map[n][vertex]) { if (_edge_map[n][vertex]) {
res.push_back(n); res.push_back(n);
} }
} }
@@ -293,11 +293,11 @@ public:
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex` /// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
list<size_t> symmetric(size_t vertex) { list<size_t> symmetric(size_t vertex) {
list<size_t> res; list<size_t> res;
if (empty() || vertex >= _conn_map.size()) { if (empty() || vertex >= _edge_map.size()) {
return res; return res;
} }
for (const auto& it : _conn_map[vertex]) { for (const auto& it : _edge_map[vertex]) {
if (_conn_map[it.first][vertex]) { if (_edge_map[it.first][vertex]) {
res.push_back(it.first); res.push_back(it.first);
} }
} }
@@ -314,11 +314,11 @@ public:
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex` /// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
list<size_t> undirected(size_t vertex) { list<size_t> undirected(size_t vertex) {
list<size_t> res; list<size_t> res;
if (empty() || vertex >= _conn_map.size()) { if (empty() || vertex >= _edge_map.size()) {
return res; return res;
} }
for (const auto& it : _conn_map[vertex]) { for (const auto& it : _edge_map[vertex]) {
const auto* at = _conn_map[it.first][vertex]; const auto* at = _edge_map[it.first][vertex];
if (at != nullptr && *at == it.second) { if (at != nullptr && *at == it.second) {
res.push_back(it.first); res.push_back(it.first);
} }
@@ -332,10 +332,10 @@ public:
/// \param vertex The id of the vertex /// \param vertex The id of the vertex
/// \returns A pointer to a map containing edges mapped from this vertex /// \returns A pointer to a map containing edges mapped from this vertex
const auto* edges(size_t vertex) { const auto* edges(size_t vertex) {
if (empty() || vertex >= _conn_map.size()) { if (empty() || vertex >= _edge_map.size()) {
return nullptr; return nullptr;
} }
return &_conn_map[vertex]; return &_edge_map[vertex];
} }
/// @} /// @}
@@ -392,19 +392,19 @@ public:
return; return;
} }
if (_conn_map.size() < _vertex_pool.capacity()) { if (_edge_map.size() < _vertex_pool.capacity()) {
_conn_map.resize(_vertex_pool.capacity()); _edge_map.resize(_vertex_pool.capacity());
} }
auto it = _conn_map[a][b]; auto it = _edge_map[a][b];
size_t conn; size_t conn;
if (it != nullptr) { if (it != nullptr) {
conn = *it; conn = *it;
_conn_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...); _edge_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
} else { } else {
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...); conn = _edge_pool.emplace(fennec::forward<ArgsT>(args)...);
} }
_conn_map[a].emplace(b, conn); _edge_map[a].emplace(b, conn);
} }
/// ///
@@ -419,21 +419,21 @@ public:
return; return;
} }
if (_conn_map.size() < _vertex_pool.capacity()) { if (_edge_map.size() < _vertex_pool.capacity()) {
_conn_map.resize(_vertex_pool.capacity()); _edge_map.resize(_vertex_pool.capacity());
} }
auto it = _conn_map[a][b]; auto it = _edge_map[a][b];
size_t conn; size_t conn;
if (it != nullptr) { if (it != nullptr) {
conn = *it; conn = *it;
_conn_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...); _edge_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
} else { } else {
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...); conn = _edge_pool.emplace(fennec::forward<ArgsT>(args)...);
} }
_conn_map[a].emplace(b, conn); _edge_map[a].emplace(b, conn);
_conn_map[b].emplace(a, conn); _edge_map[b].emplace(a, conn);
} }
/// ///
@@ -443,20 +443,20 @@ public:
constexpr void cut_edge(size_t a, size_t b) { constexpr void cut_edge(size_t a, size_t b) {
// Find the edge object // Find the edge object
const auto* it = _conn_map[a][b]; const auto* it = _edge_map[a][b];
if (not it) { if (not it) {
return; return;
} }
size_t c = *it; size_t c = *it;
// Check if undirected // Check if undirected
const auto* at = _conn_map[b][a]; const auto* at = _edge_map[b][a];
if (not at || *at != c) { if (not at || *at != c) {
_conn_pool.erase(c); _edge_pool.erase(c);
} }
// Erase the edge mapping // Erase the edge mapping
_conn_map[a].erase(b); _edge_map[a].erase(b);
} }
/// ///
@@ -464,15 +464,15 @@ public:
/// \param a The first vertex id /// \param a The first vertex id
/// \param b The second vertex id /// \param b The second vertex id
constexpr void cut_edge2(size_t a, size_t b) { constexpr void cut_edge2(size_t a, size_t b) {
const auto* ita = _conn_map[a][b]; const auto* ita = _edge_map[a][b];
const auto* itb = _conn_map[a][b]; const auto* itb = _edge_map[a][b];
if (not (ita || itb)) { if (not (ita || itb)) {
return; return;
} }
if (ita) _conn_pool.erase(*ita); if (ita) _edge_pool.erase(*ita);
if (itb) _conn_pool.erase(*itb); if (itb) _edge_pool.erase(*itb);
_conn_map[a].erase(b); _edge_map[a].erase(b);
_conn_map[b].erase(a); _edge_map[b].erase(a);
} }
/// ///
@@ -491,8 +491,8 @@ public:
/// \brief Clear the graph, destructing all vertices and edges. /// \brief Clear the graph, destructing all vertices and edges.
void clear() { void clear() {
_vertex_pool.clear(); _vertex_pool.clear();
_conn_pool.clear(); _edge_pool.clear();
_conn_map.clear(); _edge_map.clear();
} }
/// @} /// @}
@@ -503,8 +503,8 @@ public:
private: private:
vertex_pool_t _vertex_pool; vertex_pool_t _vertex_pool;
edge_pool_t _conn_pool; edge_pool_t _edge_pool;
edge_map_t _conn_map; edge_map_t _edge_map;
template<typename...ArgsT> template<typename...ArgsT>
size_t _insert(ArgsT&&...args) { size_t _insert(ArgsT&&...args) {

View File

@@ -42,6 +42,22 @@ FENNEC_NO_INLINE uint64_t typeuuid() {
return id = detail::_typeuuid<RootT>(); return id = detail::_typeuuid<RootT>();
} }
template<typename RootT = void>
struct typed {
public:
const uint64_t type;
template<typename TypeT>
bool is_type() const {
return type == typeuuid<TypeT, RootT>();
}
template<typename TypeT>
typed(TypeT*)
: type(typeuuid<TypeT, RootT>()) {
}
};
} }
#endif // FENNEC_LANG_TYPEUUID_H #endif // FENNEC_LANG_TYPEUUID_H

View File

@@ -55,7 +55,7 @@ public:
/// \param str the cstring to convert /// \param str the cstring to convert
path(const cstring& str) path(const cstring& str)
: _str(str) { : _str(str) {
while (not _str.empty() && _str[_str.size() - 1] == '/') { if (str.size() > 2 && str[str.size() - 1] == '/') {
_str = _str.substring(0, str.size() - 1); _str = _str.substring(0, str.size() - 1);
} }
} }
@@ -64,8 +64,8 @@ public:
/// \brief String Conversion Constructor /// \brief String Conversion Constructor
/// \param str the string to convert /// \param str the string to convert
path(const string& str) path(const string& str)
: _str(str) { : _str(str) {
while (_str[_str.size() - 1] == '/') { if (str.size() > 2 && str[str.size() - 1] == '/') {
_str = _str.substring(0, str.size() - 1); _str = _str.substring(0, str.size() - 1);
} }
} }
@@ -85,6 +85,16 @@ public:
// Assignment Operators ================================================================================================ // Assignment Operators ================================================================================================
///
/// \brief C-String Assignment Operator
/// \param str the cstring to assign
/// \returns a reference to `this` after assigning `p`
template<size_t n>
path& operator=(const char (&str)[n]) {
_str = str;
return *this;
}
/// ///
/// \brief C-String Assignment Operator /// \brief C-String Assignment Operator
/// \param p the cstring to assign /// \param p the cstring to assign
@@ -177,7 +187,7 @@ public:
#else #else
size_t start = _str.size() - 1; size_t start = _str.size() - 1;
start = _str[start] == '/' ? start - 1 : start; start = _str[start] == '/' ? start - 1 : start;
return _str.substring(0, _str.rfind('/', start)); return path(_str.substring(0, _str.rfind('/', start)));
#endif #endif
} }

View File

@@ -27,7 +27,7 @@
namespace fennec namespace fennec
{ {
class display class display : public typed<display>
{ {
public: public:
struct pixel_format { struct pixel_format {
@@ -42,7 +42,7 @@ public:
virtual bool connected() const = 0; virtual bool connected() const = 0;
virtual ~display(); virtual ~display();
virtual window* create_window() = 0; virtual window* create_window(window* parent) = 0;
const pixel_format& get_color_format() const { const pixel_format& get_color_format() const {
return _config.format; return _config.format;
@@ -55,7 +55,6 @@ public:
gfxcontext* get_context() { return _context; } gfxcontext* get_context() { return _context; }
const string name; const string name;
const uint64_t uuid;
protected: protected:
platform* _platform; platform* _platform;
@@ -63,9 +62,9 @@ protected:
config _config; config _config;
template<typename DisplayT> template<typename DisplayT>
explicit display(platform* platform, const cstring& name, DisplayT*) explicit display(platform* platform, const cstring& name, DisplayT* type)
: name(name) : typed(type)
, uuid(typeuuid<DisplayT>()) , name(name)
, _platform(platform) , _platform(platform)
, _context(nullptr) , _context(nullptr)
, _config { , _config {

View File

@@ -22,33 +22,39 @@
#include <fennec/langproc/strings/string.h> #include <fennec/langproc/strings/string.h>
#include <fennec/lang/typeuuid.h> #include <fennec/lang/typeuuid.h>
#include <fennec/platform/interface/fwd.h> #include <fennec/platform/interface/fwd.h>
#include <fennec/platform/interface/window.h>
namespace fennec namespace fennec
{ {
class gfxcontext { class gfxcontext : public typed<gfxcontext> {
public: public:
const string name; const string name;
const uint64_t uuid;
virtual bool connected() = 0; virtual bool connected() = 0;
virtual const cstring& get_name() = 0;
virtual int32_t get_version_major() = 0; virtual int32_t get_version_major() = 0;
virtual int32_t get_version_minor() = 0; virtual int32_t get_version_minor() = 0;
virtual int32_t get_context_version() = 0; virtual int32_t get_version() = 0;
virtual const cstring& get_context_name() = 0;
virtual bool check_extension(const cstring& ext) = 0; virtual bool check_extension(const cstring& ext) = 0;
virtual void make_current(gfxsurface* surface) = 0; virtual void make_current(gfxsurface* surface) = 0;
virtual gfxsurface* create_surface(window* window) = 0;
virtual ~gfxcontext() = default; virtual ~gfxcontext() = default;
display* get_display() {
return _display;
}
protected: protected:
display* _display; display* _display;
template<typename ContextT> template<typename ContextT>
gfxcontext(display* display, const cstring& name, ContextT*) gfxcontext(display* display, const cstring& name, ContextT* type)
: name(name) : typed(type)
, uuid(typeuuid<ContextT>()) , name(name)
, _display(display) { , _display(display) {
} }
}; };

View File

@@ -0,0 +1,76 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
///
/// \file gfxsurface.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_PLATFORM_INTERFACE_GFXSURFACE_H
#define FENNEC_PLATFORM_INTERFACE_GFXSURFACE_H
#include <fennec/lang/types.h>
#include <fennec/lang/typeuuid.h>
#include <fennec/platform/interface/fwd.h>
#include <fennec/platform/interface/window.h>
namespace fennec
{
class gfxsurface : public typed<gfxsurface> {
public:
virtual ~gfxsurface() = default;
virtual void resize(size_t width, size_t height) {
_width = width;
_height = height;
}
gfxcontext* get_context() {
return _context;
}
window* get_window() {
return _window;
}
protected:
gfxcontext* _context;
window* _window;
size_t _width, _height;
template<typename SurfaceT>
gfxsurface(gfxcontext* ctx, window* window, SurfaceT* type)
: typed(type)
, _context(ctx)
, _window(window)
, _width(window->get_width()), _height(window->get_height()) {
}
};
}
#endif // FENNEC_PLATFORM_INTERFACE_GFXSURFACE_H

View File

@@ -59,13 +59,12 @@
namespace fennec namespace fennec
{ {
class platform { class platform : public typed<platform> {
public: public:
using shared_object = struct shared_object; using shared_object = struct shared_object;
using symbol = void*; using symbol = void*;
const string name; const string name;
const uint64_t uuid;
virtual ~platform() = default; virtual ~platform() = default;
@@ -81,9 +80,9 @@ public:
protected: protected:
template<typename PlatformT> template<typename PlatformT>
explicit platform(const cstring& name, PlatformT*) explicit platform(const cstring& name, PlatformT* type)
: name(name) : typed(type)
, uuid(typeuuid<PlatformT>()) { , name(name) {
auto& globals = _get_globals(); auto& globals = _get_globals();
assertf(globals.singleton == nullptr, "Conflicting Platform Definitions."); assertf(globals.singleton == nullptr, "Conflicting Platform Definitions.");
globals.singleton = this; globals.singleton = this;

View File

@@ -22,6 +22,7 @@
#include <fennec/containers/optional.h> #include <fennec/containers/optional.h>
#include <fennec/langproc/strings/string.h> #include <fennec/langproc/strings/string.h>
#include <fennec/platform/interface/fwd.h> #include <fennec/platform/interface/fwd.h>
#include <fennec/platform/linux/wayland/display.h>
namespace fennec namespace fennec
{ {
@@ -29,7 +30,7 @@ namespace fennec
/// ///
/// \brief interface for handling windows /// \brief interface for handling windows
/// \details the interface makes no guarantees about the bit-depth and is completely dependent on the implementation. /// \details the interface makes no guarantees about the bit-depth and is completely dependent on the implementation.
class window { class window : public typed<window> {
public: public:
enum class fullscreen_mode { enum class fullscreen_mode {
windowed = 0, windowed = 0,
@@ -53,6 +54,8 @@ public:
fullscreen_mode fullscreen; fullscreen_mode fullscreen;
}; };
virtual ~window() = default;
virtual bool running() = 0; virtual bool running() = 0;
virtual void configure(const config& config) = 0; virtual void configure(const config& config) = 0;
virtual bool initialize(bool modal) = 0; virtual bool initialize(bool modal) = 0;
@@ -63,7 +66,7 @@ public:
virtual bool set_width(size_t w) = 0; virtual bool set_width(size_t w) = 0;
virtual bool set_height(size_t h) = 0; virtual bool set_height(size_t h) = 0;
virtual bool set_size(size_t w, size_t h) = 0; virtual bool resize(size_t w, size_t h) = 0;
virtual bool set_fullscreen_mode(fullscreen_mode mode) = 0; virtual bool set_fullscreen_mode(fullscreen_mode mode) = 0;
@@ -73,6 +76,8 @@ public:
virtual bool grab_mouse(bool e) = 0; virtual bool grab_mouse(bool e) = 0;
virtual bool block_screensaver(bool e) = 0; virtual bool block_screensaver(bool e) = 0;
virtual struct wl_surface* get_native_handle() = 0;
bool is_child() const { bool is_child() const {
if (not _config) return false; if (not _config) return false;
return _config->flags & flags_child; return _config->flags & flags_child;
@@ -91,9 +96,13 @@ public:
return _display; return _display;
} }
const config& get_config() const {
return *_config;
}
const string& get_title() const { const string& get_title() const {
static const string _null = { "null" }; static const string _null{"null"};
if (not _config) return _null; if (not _config) return _null;
return _config->title; return _config->title;
} }
@@ -137,13 +146,20 @@ public:
} }
protected: protected:
virtual ~window() = default; template<typename TypeT>
window(display* display, window* parent); window(display* display, window* parent, TypeT* type)
: typed(type)
, _display(display)
, _parent(parent)
, _surface(nullptr) {
}
display* _display; display* _display;
window* _parent; window* _parent;
optional<config> _config; optional<config> _config;
gfxsurface* _context; gfxsurface* _surface;
private:
private: private:
}; };

View File

@@ -33,13 +33,28 @@ public:
bool connected() const override; bool connected() const override;
void* get_native_handle() override { return _handle; } void* get_native_handle() override { return _handle; }
window* create_window() override; window* create_window(window* parent) override;
wl_registry* get_registry() { return _registry; }
const wl_registry* get_registry() const { return _registry; }
wl_compositor* get_compositor() { return _compositor; }
const wl_compositor* get_compositor() const { return _compositor; }
// xdg_wm_base* get_shell() { return _shell; }
//const xdg_wm_base* get_shell() const { return _shell; }
wl_seat* get_seat() { return _seat; }
const wl_seat* get_seat() const { return _seat; }
wl_shm* get_shm() { return _shm; }
const wl_shm* get_shm() const { return _shm; }
private: private:
wl_display* _handle; wl_display* _handle;
wl_registry* _registry; wl_registry* _registry;
wl_compositor* _compositor; wl_compositor* _compositor;
wl_shell* _shell; //xdg_wm_base* _shell;
wl_seat* _seat; wl_seat* _seat;
wl_shm* _shm; wl_shm* _shm;
bool _fifo; bool _fifo;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -60,7 +60,7 @@
FENNEC_LIB(WAYLAND); FENNEC_LIB(WAYLAND);
FENNEC_SYMBOL(void, wl_proxy_marshal, struct wl_proxy*, uint32_t, ...); FENNEC_SYMBOL(void, wl_proxy_marshal, struct wl_proxy*, uint32_t, ...);
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_flags, struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, uint32_t flags, ...); FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_flags, struct wl_proxy*, uint32_t, const struct wl_interface*, uint32_t, uint32_t, ...);
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_create, struct wl_proxy*, const struct wl_interface*); FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_create, struct wl_proxy*, const struct wl_interface*);
FENNEC_SYMBOL(void, wl_proxy_destroy, struct wl_proxy*); FENNEC_SYMBOL(void, wl_proxy_destroy, struct wl_proxy*);
FENNEC_SYMBOL(int, wl_proxy_add_listener, struct wl_proxy*, void (**)(void), void*); FENNEC_SYMBOL(int, wl_proxy_add_listener, struct wl_proxy*, void (**)(void), void*);
@@ -72,6 +72,11 @@ FENNEC_SYMBOL(const char*, wl_proxy_get_class, st
FENNEC_SYMBOL(void, wl_proxy_set_queue, struct wl_proxy*, struct wl_event_queue*); FENNEC_SYMBOL(void, wl_proxy_set_queue, struct wl_proxy*, struct wl_event_queue*);
FENNEC_SYMBOL(void*, wl_proxy_create_wrapper, void*); FENNEC_SYMBOL(void*, wl_proxy_create_wrapper, void*);
FENNEC_SYMBOL(void, wl_proxy_wrapper_destroy, void*); FENNEC_SYMBOL(void, wl_proxy_wrapper_destroy, void*);
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_constructor, struct wl_proxy*, uint32_t, const struct wl_interface*, ...);
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_constructor_versioned, struct wl_proxy*, uint32_t, const struct wl_interface*, uint32_t, ...);
FENNEC_SYMBOL(void, wl_proxy_set_tag, struct wl_proxy*, const char* const*);
FENNEC_SYMBOL(const char* const*, wl_proxy_get_tag, struct wl_proxy*);
FENNEC_SYMBOL(struct wl_display*, wl_display_connect, const char*); FENNEC_SYMBOL(struct wl_display*, wl_display_connect, const char*);
FENNEC_SYMBOL(struct wl_display*, wl_display_connect_to_fd, int); FENNEC_SYMBOL(struct wl_display*, wl_display_connect_to_fd, int);
FENNEC_SYMBOL(void, wl_display_disconnect, struct wl_display*); FENNEC_SYMBOL(void, wl_display_disconnect, struct wl_display*);
@@ -88,6 +93,7 @@ FENNEC_SYMBOL(int, wl_display_get_error, st
FENNEC_SYMBOL(int, wl_display_flush, struct wl_display*); FENNEC_SYMBOL(int, wl_display_flush, struct wl_display*);
FENNEC_SYMBOL(int, wl_display_roundtrip, struct wl_display*); FENNEC_SYMBOL(int, wl_display_roundtrip, struct wl_display*);
FENNEC_SYMBOL(struct wl_event_queue*, wl_display_create_queue, struct wl_display*); FENNEC_SYMBOL(struct wl_event_queue*, wl_display_create_queue, struct wl_display*);
FENNEC_SYMBOL(void, wl_event_queue_destroy, struct wl_event_queue*); FENNEC_SYMBOL(void, wl_event_queue_destroy, struct wl_event_queue*);
FENNEC_SYMBOL(void, wl_log_set_handler_client, wl_log_func_t); FENNEC_SYMBOL(void, wl_log_set_handler_client, wl_log_func_t);
FENNEC_SYMBOL(void, wl_list_init, struct wl_list*); FENNEC_SYMBOL(void, wl_list_init, struct wl_list*);
@@ -96,10 +102,6 @@ FENNEC_SYMBOL(void, wl_list_remove, st
FENNEC_SYMBOL(int, wl_list_length, const struct wl_list*); FENNEC_SYMBOL(int, wl_list_length, const struct wl_list*);
FENNEC_SYMBOL(int, wl_list_empty, const struct wl_list*); FENNEC_SYMBOL(int, wl_list_empty, const struct wl_list*);
FENNEC_SYMBOL(void, wl_list_insert_list, struct wl_list*, struct wl_list*); FENNEC_SYMBOL(void, wl_list_insert_list, struct wl_list*, struct wl_list*);
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_constructor, struct wl_proxy*, uint32_t opcode, const struct wl_interface*interface, ...);
FENNEC_SYMBOL(struct wl_proxy*, wl_proxy_marshal_constructor_versioned, struct wl_proxy*proxy, uint32_t opcode, const struct wl_interface*interface, uint32_t version, ...);
FENNEC_SYMBOL(void, wl_proxy_set_tag, struct wl_proxy*, const char* const*);
FENNEC_SYMBOL(const char* const*, wl_proxy_get_tag, struct wl_proxy*);
FENNEC_GLOBAL(const struct wl_interface, wl_display_interface); FENNEC_GLOBAL(const struct wl_interface, wl_display_interface);
FENNEC_GLOBAL(const struct wl_interface, wl_registry_interface); FENNEC_GLOBAL(const struct wl_interface, wl_registry_interface);

File diff suppressed because it is too large Load Diff

View File

@@ -1,198 +0,0 @@
// =====================================================================================================================
// 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_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_UTIL_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_UTIL_H
/*
* Copyright © 2008 Kristian Høgsberg
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stddef.h>
#include <inttypes.h>
#include <stdarg.h>
#if defined(__GNUC__) && __GNUC__ >= 4
#define WL_EXPORT __attribute__ ((visibility("default")))
#else
#define WL_EXPORT
#endif
#if __STDC_VERSION__ >= 202311L
#define WL_DEPRECATED [[deprecated]]
#elif defined(__GNUC__) && __GNUC__ >= 4
#define WL_DEPRECATED __attribute__ ((deprecated))
#else
#define WL_DEPRECATED
#endif
#if defined(__GNUC__) && __GNUC__ >= 4
#define WL_PRINTF(x, y) __attribute__((__format__(__printf__, x, y)))
#else
#define WL_PRINTF(x, y)
#endif
#if __STDC_VERSION__ >= 202311L
#define WL_TYPEOF(expr) typeof(expr)
#else
#define WL_TYPEOF(expr) __typeof__(expr)
#endif
struct wl_message {
const char *name;
const char *signature;
const struct wl_interface **types;
};
struct wl_interface {
const char *name;
int version;
int method_count;
const struct wl_message *methods;
int event_count;
const struct wl_message *events;
};
struct wl_list {
struct wl_list *prev;
struct wl_list *next;
};
#define wl_container_of(ptr, sample, member) \
(WL_TYPEOF(sample))((char *)(ptr) - \
offsetof(WL_TYPEOF(*sample), member))
#define wl_list_for_each(pos, head, member) \
for (pos = wl_container_of((head)->next, pos, member); \
&pos->member != (head); \
pos = wl_container_of(pos->member.next, pos, member))
#define wl_list_for_each_safe(pos, tmp, head, member) \
for (pos = wl_container_of((head)->next, pos, member), \
tmp = wl_container_of((pos)->member.next, tmp, member); \
&pos->member != (head); \
pos = tmp, \
tmp = wl_container_of(pos->member.next, tmp, member))
#define wl_list_for_each_reverse(pos, head, member) \
for (pos = wl_container_of((head)->prev, pos, member); \
&pos->member != (head); \
pos = wl_container_of(pos->member.prev, pos, member))
#define wl_list_for_each_reverse_safe(pos, tmp, head, member) \
for (pos = wl_container_of((head)->prev, pos, member), \
tmp = wl_container_of((pos)->member.prev, tmp, member); \
&pos->member != (head); \
pos = tmp, \
tmp = wl_container_of(pos->member.prev, tmp, member))
struct wl_array {
size_t size;
size_t alloc;
void *data;
};
void
wl_array_init(struct wl_array *array);
void
wl_array_release(struct wl_array *array);
void *
wl_array_add(struct wl_array *array, size_t size);
int
wl_array_copy(struct wl_array *array, struct wl_array *source);
#define wl_array_for_each(pos, array) \
for (pos = (array)->data; \
(array)->size != 0 && \
(const char *) pos < ((const char *) (array)->data + (array)->size); \
(pos)++)
typedef int32_t wl_fixed_t;
static inline double
wl_fixed_to_double(wl_fixed_t f)
{
return f / 256.0;
}
static inline wl_fixed_t
wl_fixed_from_double(double d)
{
return (wl_fixed_t) (d * 256.0);
}
static inline int
wl_fixed_to_int(wl_fixed_t f)
{
return f / 256;
}
static inline wl_fixed_t
wl_fixed_from_int(int i)
{
return i * 256;
}
union wl_argument {
int32_t i;
uint32_t u;
wl_fixed_t f;
const char *s;
struct wl_object *o;
uint32_t n;
struct wl_array *a;
int32_t h;
};
typedef int (*wl_dispatcher_func_t)(const void *user_data, void *target,
uint32_t opcode, const struct wl_message *msg,
union wl_argument *args);
typedef void (*wl_log_func_t)(const char *fmt, va_list args) WL_PRINTF(1, 0);
enum wl_iterator_result {
WL_ITERATOR_STOP,
WL_ITERATOR_CONTINUE
};
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_UTIL_H

View File

@@ -0,0 +1,98 @@
// =====================================================================================================================
// 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_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_CLIENT_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_CLIENT_H
#define FENNEC_LIB(name) extern "C" bool FENNEC_HAS_LIB_##name;
#define FENNEC_SYMBOL(ret, fn, ...) using WAYLAND_sym_##fn = ret(*)(__VA_ARGS__); \
extern "C" WAYLAND_sym_##fn WAYLAND_##fn;
#define FENNEC_GLOBAL(type, name) extern "C" type* WAYLAND_##name;
#include <fennec/platform/linux/wayland/lib/sym.h>
#include <wayland-client-core.h>
#define wl_proxy_marshal WAYLAND_wl_proxy_marshal
#define wl_proxy_marshal_flags WAYLAND_wl_proxy_marshal_flags
#define wl_proxy_create WAYLAND_wl_proxy_create
#define wl_proxy_destroy WAYLAND_wl_proxy_destroy
#define wl_proxy_add_listener WAYLAND_wl_proxy_add_listener
#define wl_proxy_set_user_data WAYLAND_wl_proxy_set_user_data
#define wl_proxy_get_user_data WAYLAND_wl_proxy_get_user_data
#define wl_proxy_get_version WAYLAND_wl_proxy_get_version
#define wl_proxy_get_id WAYLAND_wl_proxy_get_id
#define wl_proxy_get_class WAYLAND_wl_proxy_get_class
#define wl_proxy_set_queue WAYLAND_wl_proxy_set_queue
#define wl_proxy_create_wrapper WAYLAND_wl_proxy_create_wrapper
#define wl_proxy_wrapper_destroy WAYLAND_wl_proxy_wrapper_destroy
#define wl_proxy_marshal_constructor WAYLAND_wl_proxy_marshal_constructor
#define wl_proxy_marshal_constructor_versioned WAYLAND_wl_proxy_marshal_constructor_versioned
#define wl_proxy_set_tag WAYLAND_wl_proxy_set_tag
#define wl_proxy_get_tag WAYLAND_wl_proxy_get_tag
#define wl_event_queue_destroy WAYLAND_wl_event_queue_destroy
#define wl_log_set_handler_client WAYLAND_wl_log_set_handler_client
#define wl_list_init WAYLAND_wl_list_init
#define wl_list_insert WAYLAND_wl_list_insert
#define wl_list_remove WAYLAND_wl_list_remove
#define wl_list_length WAYLAND_wl_list_length
#define wl_list_empty WAYLAND_wl_list_empty
#define wl_list_insert_list WAYLAND_wl_list_insert_list
#define wl_display_connect WAYLAND_wl_display_connect
#define wl_display_connect_to_fd WAYLAND_wl_display_connect_to_fd
#define wl_display_reconnect WAYLAND_wl_display_reconnect
#define wl_display_disconnect WAYLAND_wl_display_disconnect
#define wl_display_get_fd WAYLAND_wl_display_get_fd
#define wl_display_dispatch WAYLAND_wl_display_dispatch
#define wl_display_dispatch_queue WAYLAND_wl_display_dispatch_queue
#define wl_display_dispatch_queue_pending WAYLAND_wl_display_dispatch_queue_pending
#define wl_display_dispatch_pending WAYLAND_wl_display_dispatch_pending
#define wl_display_prepare_read WAYLAND_wl_display_prepare_read
#define wl_display_prepare_read_queue WAYLAND_wl_display_prepare_read_queue
#define wl_display_read_events WAYLAND_wl_display_read_events
#define wl_display_cancel_read WAYLAND_wl_display_cancel_read
#define wl_display_get_error WAYLAND_wl_display_get_error
#define wl_display_flush WAYLAND_wl_display_flush
#define wl_display_roundtrip WAYLAND_wl_display_roundtrip
#define wl_display_create_queue WAYLAND_wl_display_create_queue
#define wl_seat_interface *WAYLAND_wl_seat_interface
#define wl_surface_interface *WAYLAND_wl_surface_interface
#define wl_shm_pool_interface *WAYLAND_wl_shm_pool_interface
#define wl_buffer_interface *WAYLAND_wl_buffer_interface
#define wl_registry_interface *WAYLAND_wl_registry_interface
#define wl_region_interface *WAYLAND_wl_region_interface
#define wl_pointer_interface *WAYLAND_wl_pointer_interface
#define wl_keyboard_interface *WAYLAND_wl_keyboard_interface
#define wl_compositor_interface *WAYLAND_wl_compositor_interface
#define wl_output_interface *WAYLAND_wl_output_interface
#define wl_shm_interface *WAYLAND_wl_shm_interface
#define wl_data_device_interface *WAYLAND_wl_data_device_interface
#define wl_data_offer_interface *WAYLAND_wl_data_offer_interface
#define wl_data_source_interface *WAYLAND_wl_data_source_interface
#define wl_data_device_manager_interface *WAYLAND_wl_data_device_manager_interface
#define wl_egl_window_create WAYLAND_wl_egl_window_create
#define wl_egl_window_destroy WAYLAND_wl_egl_window_destroy
#define wl_egl_window_resize WAYLAND_wl_egl_window_resize
#define wl_egl_window_get_attached_size WAYLAND_wl_egl_window_get_attached_size
#include <fennec/platform/linux/wayland/lib/headers/wayland-client-protocols.h>
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_CLIENT_H

View File

@@ -0,0 +1,83 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
///
/// \file window.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
#include <fennec/platform/interface/window.h>
#include <fennec/platform/linux/wayland/display.h>
namespace fennec
{
class wayland_window : public window {
public:
bool running() override;
void configure(const config& config) override;
bool initialize(bool modal) override;
bool shutdown() override;
bool set_title(const cstring& title) override;
bool set_title(const string& title) override;
bool set_width(size_t w) override;
bool set_height(size_t h) override;
bool resize(size_t w, size_t h) override;
bool set_resizable(bool e) override;
bool set_fullscreen_mode(fullscreen_mode mode) override;
bool grab_keyboard(bool e) override;
bool grab_mouse(bool e) override;
bool block_screensaver(bool e) override;
wayland_window(wayland_display* display, wayland_window* parent);
~wayland_window() override;
struct wl_surface* get_native_handle() override {
return _handle;
}
private:
wl_surface* _handle;
wl_shell_surface* _shell;
size_t _nfs_width, _nfs_height;
static void listen_ping(void*, wl_shell_surface*, uint32_t);
static void listen_configure(void*, wl_shell_surface*, uint32_t, int32_t, int32_t);
static void listen_popup_done(void*, wl_shell_surface*);
};
}
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H

View File

@@ -21,6 +21,7 @@
#include <EGL/egl.h> #include <EGL/egl.h>
#include <fennec/platform/interface/gfxcontext.h> #include <fennec/platform/interface/gfxcontext.h>
#include <fennec/platform/opengl/egl/fwd.h>
namespace fennec namespace fennec
{ {
@@ -34,12 +35,26 @@ public:
bool connected() override; bool connected() override;
int32_t get_version_major() override { return _eglvmajor; } int32_t get_version_major() override { return _eglvmajor; }
int32_t get_version_minor() override { return _eglvminor; } int32_t get_version_minor() override { return _eglvminor; }
int32_t get_context_version() override { return _eglctype; } int32_t get_version() override { return _eglctype; }
const cstring& get_context_name() override; const cstring& get_name() override;
bool check_extension(const cstring& ext) override; bool check_extension(const cstring& ext) override;
gfxsurface* create_surface(window* window) override;
void make_current(gfxsurface* surface) override; void make_current(gfxsurface* surface) override;
EGLDisplay get_egl_display() {
return _egldisplay;
}
EGLDisplay get_egl_context() {
return _eglcontext;
}
EGLDisplay get_egl_config() {
return _eglconfig;
}
private: private:
EGLDisplay _egldisplay; EGLDisplay _egldisplay;
EGLContext _eglcontext; EGLContext _eglcontext;

View File

@@ -16,7 +16,27 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
#ifndef FENNEC_CONCURRENCY_ATOMIC_H ///
#define FENNEC_CONCURRENCY_ATOMIC_H /// \file fwd.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#endif // FENNEC_CONCURRENCY_ATOMIC_H #ifndef FENNEC_PLATFORM_OPENGL_EGL_FWD_H
#define FENNEC_PLATFORM_OPENGL_EGL_FWD_H
namespace fennec
{
class eglcontext;
class eglsurface;
}
#endif // FENNEC_PLATFORM_OPENGL_EGL_FWD_H

View File

@@ -16,7 +16,45 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
#ifndef FENNEC_CONCURRENCY_MUTEX_H ///
#define FENNEC_CONCURRENCY_MUTEX_H /// \file surface.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#endif // FENNEC_CONCURRENCY_MUTEX_H #ifndef FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
#define FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
#include <fennec/platform/interface/gfxsurface.h>
#include <fennec/platform/linux/wayland/window.h>
#include <fennec/platform/opengl/egl/context.h>
namespace fennec
{
class eglsurface : public gfxsurface {
public:
~eglsurface() override;
void resize(size_t width, size_t height) override;
eglsurface(eglcontext* context, window* window);
EGLSurface get_egl_surface() {
return _surface;
}
private:
void* _handle;
EGLSurface _surface;
};
}
#endif // FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H

View File

@@ -23,8 +23,8 @@ Links:
### Structures (`gfx2d`) ### Structures (`gfx2d`)
For the 2d rendering framework, Materials need to be rendered independently because we have For the 2d rendering framework, Materials need to be rendered independently because we have
no size constraints for images. This disallows us from using a meta-shader like in no size constraints for images. This disallows us from using a meta-shader like in
the 3d rendering framework. the 3d rendering framework.
```c++ ```c++
@@ -59,6 +59,6 @@ struct Object
- Adjust Buffer Size using the counts - Adjust Buffer Size using the counts
- Insert using another atomic buffer - Insert using another atomic buffer
- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate. - Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate.
This will allow us to sort objects as they are created. We can still bulk render each z-index, This will allow us to sort objects as they are created. We can still bulk render each z-index,
with meshes and objects being grouped by material. with meshes and objects being grouped by material.

View File

@@ -15,16 +15,16 @@
## Introduction ## Introduction
&ensp; This system handles the rendering of 3D meshes, materials, lights, and post-processing &ensp; This system handles the rendering of 3D meshes, materials, lights, and post-processing
effects. effects.
**DirectX will never have official support.** **DirectX will never have official support.**
If you would like to make a fork, have at it, but know that I will hold a deep disdain for you. If you would like to make a fork, have at it, but know that I will hold a deep disdain for you.
The graphics pipeline will have a buffer with a list of objects and their rendering data. The graphics pipeline will have a buffer with a list of objects and their rendering data.
This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes. This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes.
The buffers will be optimized by scene prediction. The buffers will be optimized by scene prediction.
This involves tracking the meshes and textures directly and indirectly used by a scene. This involves tracking the meshes and textures directly and indirectly used by a scene.
A callback function in the graphics system for scene loading can do this. A callback function in the graphics system for scene loading can do this.
@@ -66,8 +66,8 @@ Objects are identified with a manually provided type and ID. Object types includ
A user should never have to specify these and should be automatically generated by the respective components. A user should never have to specify these and should be automatically generated by the respective components.
Textures for 3D rendering are stored in various buffers with sizes of powers of 2. Ratios of `1:1` Textures for 3D rendering are stored in various buffers with sizes of powers of 2. Ratios of `1:1`
and `2:1` are allowed. The `2:1` ratio is specifically for spherical and cylindrical projection. UVs and `2:1` are allowed. The `2:1` ratio is specifically for spherical and cylindrical projection. UVs
may be transformed to use a `2:1` as if it were `1:2`. may be transformed to use a `2:1` as if it were `1:2`.
Cubemaps and 3D textures may only be `1:1`. Cubemaps and 3D textures may only be `1:1`.

View File

@@ -14,10 +14,10 @@
## Introduction ## Introduction
&ensp; This system will handle newtonian physics for 3D rigid and soft-bodies. This should include &ensp; This system will handle newtonian physics for 3D rigid and soft-bodies. This should include
articulated skeletal systems, particle physics, and soft-body physics. The following soft-body systems articulated skeletal systems, particle physics, and soft-body physics. The following soft-body systems
will be supported with the associated implementation; elastics with finite element simulation, cloth will be supported with the associated implementation; elastics with finite element simulation, cloth
physics with position-based dynamics, oceans with iWave, 3D fluid dynamics with smoothed-particle physics with position-based dynamics, oceans with iWave, 3D fluid dynamics with smoothed-particle
hydrodynamics, 2D surface fluid dynamics with force-based dynamics. hydrodynamics, 2D surface fluid dynamics with force-based dynamics.

View File

@@ -8,10 +8,10 @@
## Introduction ## Introduction
&ensp; This system implements pathing and decision systems for general-purpose traditional &ensp; This system implements pathing and decision systems for general-purpose traditional
artifical intelligence algorithms. This library will not support Machine-Learning Artificial artifical intelligence algorithms. This library will not support Machine-Learning Artificial
Intelligence (ML/AI). This artificial intelligence method only differs in static generation Intelligence (ML/AI). This artificial intelligence method only differs in static generation
between 2D and 3D. The solvers are dimension independent since they work on a graph. between 2D and 3D. The solvers are dimension independent since they work on a graph.
## General Process ## General Process
@@ -25,5 +25,5 @@ between 2D and 3D. The solvers are dimension independent since they work on a gr
* update paths using dijkstra's algorithm * update paths using dijkstra's algorithm
* apply rigid-body forces with constraints * apply rigid-body forces with constraints
The update loop for artificial intelligence should only update every `n` ticks. Where The update loop for artificial intelligence should only update every `n` ticks. Where
`n <= k`, with `k` being the tick rate of the physics engine. `n <= k`, with `k` being the tick rate of the physics engine.

View File

@@ -16,8 +16,8 @@
## Introduction ## Introduction
&ensp; This library contains headers and classes that implement common data &ensp; This library contains headers and classes that implement common data
structures. The contents include the Containers Library of the C++ Standard structures. The contents include the Containers Library of the C++ Standard
Library and Template Library. Library and Template Library.
@@ -29,29 +29,29 @@ Library and Template Library.
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
|:-------------------------------------|:-----------:|:------:| |:-------------------------------------|:-----------:|:------:|
| map (`std::unordered_map`) | ✅ | ✅ | | map (`std::unordered_map`) | ✅ | ✅ |
| map_sequence (`std::map`) | ⛔ | ⛔ | | map_sequence (`std::map`) | ⛔ | ⛔ |
| multiset (`std::unordered_multiset`) | ⛔ | ⛔ | | multiset (`std::unordered_multiset`) | ⛔ | ⛔ |
| multisequence (`std::multiset`) | ⛔ | ⛔ | | multisequence (`std::multiset`) | ⛔ | ⛔ |
| multimap (`std::unordered_multimap`) | ⛔ | ⛔ | | multimap (`std::unordered_multimap`) | ⛔ | ⛔ |
| multimap_sequence (`std::multimap`) | ⛔ | ⛔ | | multimap_sequence (`std::multimap`) | ⛔ | ⛔ |
| pair | ✅ | ✅ | | pair | ✅ | ✅ |
| tuple | 🚧 | 🚧 | | tuple | 🚧 | 🚧 |
| optional | ✅ | ✅ | | optional | ✅ | ✅ |
| variant | ⛔ | ⛔ | | variant | ⛔ | ⛔ |
| any | ⛔ | ⛔ | | any | ⛔ | ⛔ |
| bitset | ⛔ | ⛔ | | bitset | ⛔ | ⛔ |
| array | ✅ | ✅ | | array | ✅ | ✅ |
| dynarray (`std::vector`) | 🚧 | 🚧 | | dynarray (`std::vector`) | 🚧 | 🚧 |
| deque | ⛔ | ⛔ | | deque | ⛔ | ⛔ |
| list | ✅ | ✅ | | list | ✅ | ✅ |
| set (`std::unordered_set`) | ✅ | ✅ | | set (`std::unordered_set`) | ✅ | ✅ |
| sequence (`std::set`) | ⛔ | ⛔ | | sequence (`std::set`) | ⛔ | ⛔ |
### fennec ### fennec
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
|:------------|:-----------:|:------:| |:------------|:-----------:|:------:|
| graph | 🚧 | 🚧 | | graph | 🚧 | 🚧 |
| object_pool | 🚧 | 🚧 | | object_pool | 🚧 | 🚧 |
| rd_tree | ✅ | ✅ | | rd_tree | ✅ | ✅ |

View File

@@ -15,41 +15,49 @@
## Introduction ## Introduction
&ensp; These files serve as general planning documentation for engine structure, systems, &ensp; These files serve as general planning documentation for engine structure, systems,
pipelines, and implementation. pipelines, and implementation.
&ensp; Implementations of core engine systems should strive to be `O(1)` in &ensp; Implementations of core engine systems should strive to be `O(1)` in
implementations, both in terms of runtime and memory performance. This is obviously implementations, both in terms of runtime and memory performance. This is obviously
not a realistic goal, so rather than the goal requiring the entire engine to be `O(1)`, not a realistic goal, so rather than the goal requiring the entire engine to be `O(1)`,
we should more specifically look at achieving `O(1)` performance on hot paths. we should more specifically look at achieving `O(1)` performance on hot paths.
I distinctly use 'strive' and 'goal' as different concepts, where designs should I distinctly use 'strive' and 'goal' as different concepts, where designs should
*strive* to accommodate function implementations for `O(1)`, however the specifics *strive* to accommodate function implementations for `O(1)`, however the specifics
of the implementation might not always be able to achieve that, so the end *goal* is of the implementation might not always be able to achieve that, so the end *goal* is
that hot paths should be `O(1)`. that hot paths should be `O(1)`.
&ensp; Functions should be highly verbose and any bugprone or erroneous behaviour should &ensp; Functions should be highly verbose and any bugprone or erroneous behaviour should
throw assertions. **DO NOT USE EXCEPTIONS**. throw assertions. **DO NOT USE EXCEPTIONS**.
&ensp; System implementations should be independent of architecture or platforms. i.e. &ensp; System implementations should be independent of architecture or platforms. i.e.
the code of the graphics system should not care if OpenGL or Vulkan is used and should the code of the graphics system should not care if OpenGL or Vulkan is used and should
not use any direct calls to OpenGL or Vulkan. not use any direct calls to OpenGL or Vulkan.
&ensp; The engine should not care about the types of objects loaded from a so/dll. In &ensp; The engine should not care about the types of objects loaded from a so/dll. In
fact, most of the code should be type independent. Any shared information among a fact, most of the code should be type independent. Any shared information among a
collection of objects should be held either implicitly or explicitly in the super-class. collection of objects should be held either implicitly or explicitly in the super-class.
It will be the responsibility of the linked code to initialize and cleanup the objects It will be the responsibility of the linked code to initialize and cleanup the objects
related to it. This principle should extend to the submodules of the engine. related to it. This principle should extend to the submodules of the engine.
&ensp; It is also best to avoid objects having behaviour that is not defined by the system &ensp; It is also best to avoid objects having behaviour that is not defined by the system
they are in. There are some exceptions in extensions or mods, which should be given they are in. There are some exceptions in extensions or mods, which should be given
configurability and programmability within those systems and their stages. This can configurability and programmability within those systems and their stages. This can
be achieved using events at different stages of those engines that are on-demand. be achieved using events at different stages of those engines that are on-demand.
## External Libraries
* `cpptrace`
* Walking the stack and retrieving information about the code is *very* platform
dependent, and it makes little sense spending days writing a library that will
be less effective.
## Definitions ## Definitions
&ensp; Many subpages of these documents will contain tables that use symbols to &ensp; Many subpages of these documents will contain tables that use symbols to
denote implementation and testing progress. The symbols are defined below. denote implementation and testing progress. The symbols are defined below.
| Symbol | Meaning | Notes | | Symbol | Meaning | Notes |
@@ -62,4 +70,7 @@ denote implementation and testing progress. The symbols are defined below.
## Libraries ## Libraries
- [C++ Language Library](./CPP_LANGUAGE.md#c-language-library-lang) - [C++ Language Library](./CPP_LANGUAGE.md#c-language-library-lang)
- [Platform Support Library](./PLATFORM_SUPPORT.md#platform--api-support) - [Platform Support Library](./PLATFORM_SUPPORT.md#platform-support-library-platform)
- [Memory Library](./MEMORY.md#memory-library-memory)
- [Containers Library](./CONTAINERS.md#containers-library-containers)
- [Language Processing Library](./LANGUAGE_PROCESSING.md#language-processing-library-langproc)

View File

@@ -26,8 +26,8 @@
## Introduction ## Introduction
&ensp; This library contains headers and classes related to the C++ language. The &ensp; This library contains headers and classes related to the C++ language. The
contents of this library include the Language Support, Diagnostics, and contents of this library include the Language Support, Diagnostics, and
Metaprogramming libraries of the C++ Standard Library and Template Library. Metaprogramming libraries of the C++ Standard Library and Template Library.
See: See:
@@ -59,22 +59,22 @@ See:
| is_null_pointer | ✅ | ✅ | | is_null_pointer | ✅ | ✅ |
| is_integral | ✅ | ✅ | | is_integral | ✅ | ✅ |
| is_floating_point | ✅ | ✅ | | is_floating_point | ✅ | ✅ |
| is_array | ✅ | | | is_array | ✅ | 🚧 |
| is_enum | ⛔ | ⛔ | | is_enum | ⛔ | ⛔ |
| is_union | ⛔ | ⛔ | | is_union | ⛔ | ⛔ |
| is_class | ✅ | ✅ | | is_class | ✅ | ✅ |
| is_function | ⛔ | ⛔ | | is_function | ⛔ | ⛔ |
| is_pointer | ✅ | ✅ | | is_pointer | ✅ | ✅ |
| is_lvalue_reference | ✅ | ✅ | | is_lvalue_reference | ✅ | ✅ |
| is_rvalue_reference | | | | is_rvalue_reference | | |
| is_member_object_pointer | ⛔ | ⛔ | | is_member_object_pointer | ⛔ | ⛔ |
| is_member_function_pointer | ⛔ | ⛔ | | is_member_function_pointer | ⛔ | ⛔ |
### Composite Types ### Composite Types
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
|:------------------|:-----------:|:------:| |:------------------|:-----------:|:------:|
| is_fundamental | | | | is_fundamental | | |
| is_arithmetic | | | | is_arithmetic | | |
| is_scalar | ⛔ | ⛔ | | is_scalar | ⛔ | ⛔ |
| is_object | ⛔ | ⛔ | | is_object | ⛔ | ⛔ |
| is_compound | ⛔ | ⛔ | | is_compound | ⛔ | ⛔ |
@@ -84,9 +84,9 @@ See:
### Type Properties ### Type Properties
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
|:----------------------------------|:-----------:|:------:| |:----------------------------------|:-----------:|:------:|
| is_const | | | | is_const | | |
| is_volatile | | | | is_volatile | | |
| is_trivially_copyable | | | | is_trivially_copyable | | |
| is_standard_layout | ⛔ | ⛔ | | is_standard_layout | ⛔ | ⛔ |
| has_unique_object_representations | ⛔ | ⛔ | | has_unique_object_representations | ⛔ | ⛔ |
| is_empty | ⛔ | ⛔ | | is_empty | ⛔ | ⛔ |
@@ -95,8 +95,8 @@ See:
| is_final | ⛔ | ⛔ | | is_final | ⛔ | ⛔ |
| is_aggregate | ⛔ | ⛔ | | is_aggregate | ⛔ | ⛔ |
| is_implicit_lifetime | ⛔ | ⛔ | | is_implicit_lifetime | ⛔ | ⛔ |
| is_signed | | | | is_signed | | |
| is_unsigned | | | | is_unsigned | | |
| is_bounded_array | ⛔ | ⛔ | | is_bounded_array | ⛔ | ⛔ |
| is_unbounded_array | ⛔ | ⛔ | | is_unbounded_array | ⛔ | ⛔ |
| is_scoped_enum | ⛔ | ⛔ | | is_scoped_enum | ⛔ | ⛔ |
@@ -104,16 +104,16 @@ See:
### Supported Operations ### Supported Operations
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
|:------------------------------------|:-----------:|:------:| |:------------------------------------|:-----------:|:------:|
| is_constructible | | | | is_constructible | | |
| is_trivially_constructible | | | | is_trivially_constructible | | |
| is_nothrow_constructible | ⛔ | ⛔ | | is_nothrow_constructible | ⛔ | ⛔ |
| is_default_constructible | | | | is_default_constructible | | |
| is_trivially_default_constructible | ⛔ | ⛔ | | is_trivially_default_constructible | ⛔ | ⛔ |
| is_nothrow_default_constructible | ⛔ | ⛔ | | is_nothrow_default_constructible | ⛔ | ⛔ |
| is_copy_constructible | | | | is_copy_constructible | | |
| is_trivially_copy_constructible | ⛔ | ⛔ | | is_trivially_copy_constructible | ⛔ | ⛔ |
| is_nothrow_copy_constructible | ⛔ | ⛔ | | is_nothrow_copy_constructible | ⛔ | ⛔ |
| is_move_constructible | | | | is_move_constructible | | |
| is_trivially_move_constructible | ⛔ | ⛔ | | is_trivially_move_constructible | ⛔ | ⛔ |
| is_nothrow_move_constructible | ⛔ | ⛔ | | is_nothrow_move_constructible | ⛔ | ⛔ |
| is_destructible | ⛔ | ⛔ | | is_destructible | ⛔ | ⛔ |
@@ -137,10 +137,10 @@ See:
### Type Relationships ### Type Relationships
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
|:------------------------------------|:-----------:|:------:| |:------------------------------------|:-----------:|:------:|
| is_same | | | | is_same | | |
| is_base_of | ❌ | ❌ | | is_base_of | ❌ | ❌ |
| is_virtual_base_of | ❌ | ❌ | | is_virtual_base_of | ❌ | ❌ |
| is_convertible | | | | is_convertible | | |
| is_nothrow_convertible | ❌ | ❌ | | is_nothrow_convertible | ❌ | ❌ |
| is_layout_compatible | ❌ | ❌ | | is_layout_compatible | ❌ | ❌ |
| is_pointer_interconvertible_base_of | ❌ | ❌ | | is_pointer_interconvertible_base_of | ❌ | ❌ |
@@ -152,19 +152,19 @@ See:
### Type Transformations ### Type Transformations
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
|:---------------------|:-----------:|:------:| |:---------------------|:-----------:|:------:|
| add_const | | | | add_const | | |
| add_volatile | | | | add_volatile | | |
| add_cv | | | | add_cv | | |
| remove_const | | | | remove_const | | |
| remove_volatile | | | | remove_volatile | | |
| remove_cv | | | | remove_cv | | |
| add_lvalue_reference | | | | add_lvalue_reference | | |
| add_rvalue_reference | | | | add_rvalue_reference | | |
| remove_reference | | | | remove_reference | | |
| add_pointer | | | | add_pointer | | |
| remove_pointer | | | | remove_pointer | | |
| make_signed | | | | make_signed | | |
| make_unsigned | | | | make_unsigned | | |
| remove_extent | ❌ | ❌ | | remove_extent | ❌ | ❌ |
| remove_all_extents | ❌ | ❌ | | remove_all_extents | ❌ | ❌ |
@@ -174,17 +174,17 @@ See:
| aligned_storage | ❌ | ❌ | | aligned_storage | ❌ | ❌ |
| aligned_union | ❌ | ❌ | | aligned_union | ❌ | ❌ |
| aligned_union | ❌ | ❌ | | aligned_union | ❌ | ❌ |
| decay | 🚧 | 🚧 | | decay | 🚧 | 🚧 |
| remove_cvref | | | | remove_cvref | | |
| enable_if | | | | enable_if | | |
| conditional | | | | conditional | | |
| common_type | ❌ | ❌ | | common_type | ❌ | ❌ |
| common_reference | ❌ | ❌ | | common_reference | ❌ | ❌ |
| basic_common_reference | ❌ | ❌ | | basic_common_reference | ❌ | ❌ |
| underlying_type | ❌ | ❌ | | underlying_type | ❌ | ❌ |
| result_of | ❌ | ❌ | | result_of | ❌ | ❌ |
| invoke_result | ❌ | ❌ | | invoke_result | ❌ | ❌ |
| void_t | | | | void_t | | |
### Logical Operations ### Logical Operations
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
@@ -196,9 +196,9 @@ See:
### Sequences ### Sequences
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |
|:-------------------------------------------------|:-----------:|:------:| |:-------------------------------------------------|:-----------:|:------:|
| const_sequence | | | | const_sequence | | |
| const_integer_sequence (`std::integer_sequence`) | | | | const_integer_sequence (`std::integer_sequence`) | | |
| make_integer_sequence | | | | make_integer_sequence | | |
| const_index_sequence (`std::index_sequence`) | | | | const_index_sequence (`std::index_sequence`) | | |
| make_index_sequence | | | | make_index_sequence | | |
| concat_sequence | | | | concat_sequence | | |

View File

@@ -24,7 +24,7 @@
## Introduction ## Introduction
&ensp; This file outlines the core engine structure and all necessary systems for &ensp; This file outlines the core engine structure and all necessary systems for
the engine to run. the engine to run.
@@ -35,70 +35,70 @@ This section outlines core systems to the engine and brief overviews.
### Events ### Events
&ensp; fennec will be largely event based, the system should be able to handle multiple &ensp; fennec will be largely event based, the system should be able to handle multiple
event types without having any type-specific code. There will be a few categories of events, event types without having any type-specific code. There will be a few categories of events,
predominantly on-demand and delayed events. On-demand events are fired immediately, which is predominantly on-demand and delayed events. On-demand events are fired immediately, which is
useful for events related to graphics and audio. Delayed events are fired at the next tick or useful for events related to graphics and audio. Delayed events are fired at the next tick or
after a certain period of time, this is useful for physics events which can't be handled after a certain period of time, this is useful for physics events which can't be handled
immediately without potentially harming the state of the physics engine. Events should be immediately without potentially harming the state of the physics engine. Events should be
optionally able to be handled with multithreading. optionally able to be handled with multithreading.
### Scene ### Scene
&ensp; The core structure of the engine and its levels will be a scene hierarchy. The hierarchy &ensp; The core structure of the engine and its levels will be a scene hierarchy. The hierarchy
will be implemented using a rooted-directed tree (rdtree, not to be confused with rbtree). will be implemented using a rooted-directed tree (rdtree, not to be confused with rbtree).
Each element in the tree will be a node with a name and some very basic flags. Component Each element in the tree will be a node with a name and some very basic flags. Component
dependent behaviour *must* be handled in systems to avoid the overhead of an object-oriented dependent behaviour *must* be handled in systems to avoid the overhead of an object-oriented
scene hierarchy. This is predominantly caused by the recursive nature of parsing an object- scene hierarchy. This is predominantly caused by the recursive nature of parsing an object-
oriented scene hierarchy where each node records its children and updates them accordingly. oriented scene hierarchy where each node records its children and updates them accordingly.
### Scripts ### Scripts
&ensp; Scripts won't be handled the same way scripts are in other engines, they will be translated &ensp; Scripts won't be handled the same way scripts are in other engines, they will be translated
as a system which will be data-oriented. This is to reduce the overhead of the object-oriented as a system which will be data-oriented. This is to reduce the overhead of the object-oriented
approach in C++ while maintaining the appearance of being object-oriented. approach in C++ while maintaining the appearance of being object-oriented.
### AI ### AI
&ensp; AI will be a fairly multi-parted system as we need to handle different use-cases. &ensp; AI will be a fairly multi-parted system as we need to handle different use-cases.
The first use case is characters that can "walk" and "jump" on surfaces. The second use-case The first use case is characters that can "walk" and "jump" on surfaces. The second use-case
is characters that "fly" in some manner. The static path generation will be the only difference is characters that "fly" in some manner. The static path generation will be the only difference
between 2D and 3D. between 2D and 3D.
### Physics ### Physics
&ensp; Physics, like other systems, will be separated into 2D and 3D specific implementations. &ensp; Physics, like other systems, will be separated into 2D and 3D specific implementations.
This system should be able to handle both Newtonian Rigid-Bodies and Soft-Bodies. The 2D This system should be able to handle both Newtonian Rigid-Bodies and Soft-Bodies. The 2D
and 3D systems should be able to co-exist but not interact. This is for such cases where one and 3D systems should be able to co-exist but not interact. This is for such cases where one
might decide to have a minigame with physics enabled in a 2D environment. might decide to have a minigame with physics enabled in a 2D environment.
### Graphics ### Graphics
&ensp; Graphics, like other systems, will be separated into 2D and 3D specific implementations. &ensp; Graphics, like other systems, will be separated into 2D and 3D specific implementations.
Graphics will exist on a separate thread that handles "frames" vs "ticks," see definitions below Graphics will exist on a separate thread that handles "frames" vs "ticks," see definitions below
for more information. From an abstract, the graphics system should be able to handle static models, for more information. From an abstract, the graphics system should be able to handle static models,
dynamic models, skeletons, materials, lights, lighting models, and post-processing effects. dynamic models, skeletons, materials, lights, lighting models, and post-processing effects.
### Audio ### Audio
&ensp; Audio may actually be implemented generically since the principles of spatial audio apply &ensp; Audio may actually be implemented generically since the principles of spatial audio apply
identically in both 2D and 3D. The only thing that may change for 2D is which axis is "up" and which identically in both 2D and 3D. The only thing that may change for 2D is which axis is "up" and which
axis is "forwards," for example side-scrollers vs top-down. However, this does not mandate specific axis is "forwards," for example side-scrollers vs top-down. However, this does not mandate specific
implementations and rather just aliases which axis is "up." The X-axis can always be "left" and "right" implementations and rather just aliases which axis is "up." The X-axis can always be "left" and "right"
while the Y axis may be interpreted as "up" or "forwards." Audio also won't be handled in the same while the Y axis may be interpreted as "up" or "forwards." Audio also won't be handled in the same
manner as other systems which have explicit ticks and frames. manner as other systems which have explicit ticks and frames.
## Core Game Loop ## Core Game Loop
&ensp; The core game loop is divided into Ticks and Frames. Ticks represent updates in the engine &ensp; The core game loop is divided into Ticks and Frames. Ticks represent updates in the engine
state while Frames represent the generation of the visual output of the engine. state while Frames represent the generation of the visual output of the engine.
### Tick ### Tick

View File

@@ -17,20 +17,20 @@
## Introduction ## Introduction
&ensp; This library contains implementations of headers and classes related to processing &ensp; This library contains implementations of headers and classes related to processing
languages. This includes; ascii/utf8/utf16 string processing, file formats, machine language, languages. This includes; ascii/utf8/utf16 string processing, file formats, machine language,
and programming languages. and programming languages.
&ensp; fennec should be able to process documentation in files, the main ways it will support &ensp; fennec should be able to process documentation in files, the main ways it will support
this is through Doxygen and LaTeX. Consider including binaries with releases. this is through Doxygen and LaTeX. Consider including binaries with releases.
## String Analysis (`langproc/strings`) ## String Analysis (`langproc/strings`)
&ensp; fennec reimplements the C++ Strings Library as a submodule of this library. This &ensp; fennec reimplements the C++ Strings Library as a submodule of this library. This
is because C++ `std::string` has a lot of overhead. I would say that `std::string` is because C++ `std::string` has a lot of overhead. I would say that `std::string`
is a Jeep, while `fennec::string` is an F2 Car, if that analogy makes any sense. i.e. is a Jeep, while `fennec::string` is an F2 Car, if that analogy makes any sense. i.e.
`std::string` offers a lot of use cases, but is slower, while an F2 Car is barebones and `std::string` offers a lot of use cases, but is slower, while an F2 Car is barebones and
highly performant on the right surface. highly performant on the right surface.
### Implementation ### Implementation
@@ -46,7 +46,7 @@ highly performant on the right surface.
## File System (`filesystem`) ## File System (`filesystem`)
&ensp; fennec *does not* reimplement the C++ I/O Library. What it does do &ensp; fennec *does not* reimplement the C++ I/O Library. What it does do
is create C++ classes that handle file streams, directory streams, and file paths. is create C++ classes that handle file streams, directory streams, and file paths.
### Implementation ### Implementation
@@ -86,7 +86,7 @@ certain specification. Here are some concepts that will need to be implemented a
### Writing ### Writing
&ensp; The writers will be responsible for writing data as a specific format. I.E. converting &ensp; The writers will be responsible for writing data as a specific format. I.E. converting
data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/utf16). data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/utf16).
- Writer - Writer
@@ -96,7 +96,7 @@ data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/ut
## Formats (`langproc/formats`) ## Formats (`langproc/formats`)
&ensp; This submodule will contain classes for processing a variety of file formats. &ensp; This submodule will contain classes for processing a variety of file formats.
### Serialization ### Serialization
@@ -166,8 +166,8 @@ data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/ut
#### 3D Model Formats #### 3D Model Formats
&ensp; unfortunately, most formats are esoteric due to copyright/trademark/etc. &ensp; unfortunately, most formats are esoteric due to copyright/trademark/etc.
I will be using assimp for the time being, below is a list of formats supported I will be using assimp for the time being, below is a list of formats supported
by assimp. by assimp.
| Symbol | Implemented | Passed | | Symbol | Implemented | Passed |

View File

@@ -14,9 +14,9 @@
## Introduction ## Introduction
&ensp; This library contains headers and classes related to memory allocation and &ensp; This library contains headers and classes related to memory allocation and
management in C++. The contents include the Memory Management Library of management in C++. The contents include the Memory Management Library of
the C++ Standard Library and Template Library. This pulls some functions from the the C++ Standard Library and Template Library. This pulls some functions from the
C stdlib and either wraps them or aliases them. C stdlib and either wraps them or aliases them.

View File

@@ -15,8 +15,8 @@
## Introduction ## Introduction
&ensp; The platform support library will include headers, functions, and classes related &ensp; The platform support library will include headers, functions, and classes related
to supporting various platforms. Platforms may be defined as any Hardware, OS, or to supporting various platforms. Platforms may be defined as any Hardware, OS, or
Drivers that must be initialized for the engine context. Drivers that must be initialized for the engine context.
@@ -48,14 +48,14 @@ Platform Support will be implemented in the following order:
- Vulkan - Vulkan
- Metal - Metal
&ensp; Linux Wayland will be implemented first. Once setup, the core engine will be &ensp; 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, implemented and tested on top of Wayland. Once the engine is in a stable state,
then support for other platforms will be resumed. then support for other platforms will be resumed.
## Consoles ## Consoles
&ensp; Most consoles will never get official platform support due to NDAs which conflict &ensp; 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 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 interact when strictly necessary, such as support for Windows and MacOS. fennec will interact
with any drivers required for the listed operating systems above, even if proprietary. with any drivers required for the listed operating systems above, even if proprietary.

View File

@@ -138,8 +138,8 @@ file& file::operator=(file&& file) noexcept {
_error = file._error; _error = file._error;
file._handle = nullptr; file._handle = nullptr;
file._path = ""; file._path = "";
file._error = nullptr; file._error = nullptr;
return *this; return *this;
} }

View File

@@ -40,7 +40,7 @@ path path::current() {
path path::current() { path path::current() {
char cstr[PATH_MAX]; char cstr[PATH_MAX];
if (getcwd(cstr, sizeof(cstr)) == nullptr) { if (getcwd(cstr, sizeof(cstr)) == nullptr) {
return string(""); return path("");
} }
return path(cstring(cstr, strlen(cstr) + 1)); return path(cstring(cstr, strlen(cstr) + 1));
} }

View File

@@ -18,9 +18,11 @@
#include <fennec/platform/linux/wayland/display.h> #include <fennec/platform/linux/wayland/display.h>
#include <fennec/platform/linux/wayland/lib/loader.h> #include <fennec/platform/linux/wayland/lib/loader.h>
#include <fennec/platform/linux/wayland/lib/wayland-client.h> #include <fennec/platform/linux/wayland/lib/wayland.h>
#include <fennec/lang/startup.h> #include <fennec/lang/startup.h>
#include <fennec/platform/linux/wayland/window.h>
#include <fennec/platform/linux/wayland/lib/headers/wayland-client-protocols.h>
namespace fennec namespace fennec
{ {
@@ -42,7 +44,6 @@ wayland_display::wayland_display(platform* platform)
, _handle(nullptr) , _handle(nullptr)
, _registry(nullptr) , _registry(nullptr)
, _compositor(nullptr) , _compositor(nullptr)
, _shell(nullptr)
, _seat(nullptr) , _seat(nullptr)
, _shm(nullptr) , _shm(nullptr)
, _fifo(false) { , _fifo(false) {
@@ -89,14 +90,13 @@ bool wayland_display::connected() const {
return _handle != nullptr; return _handle != nullptr;
} }
window* wayland_display::create_window() { window* wayland_display::create_window(window* parent) {
return nullptr; return new wayland_window(this, static_cast<wayland_window*>(parent));
} }
void wayland_display::cleanup() { void wayland_display::cleanup() {
// Cleanup members // Cleanup members
if (_shell) wl_shell_destroy(_shell);
if (_compositor) wl_compositor_destroy(_compositor); if (_compositor) wl_compositor_destroy(_compositor);
if (_registry) wl_registry_destroy(_registry); if (_registry) wl_registry_destroy(_registry);
if (_handle) { if (_handle) {
@@ -104,7 +104,6 @@ void wayland_display::cleanup() {
wl_display_disconnect(_handle); wl_display_disconnect(_handle);
} }
_shell = nullptr;
_compositor = nullptr; _compositor = nullptr;
_registry = nullptr; _registry = nullptr;
_handle = nullptr; _handle = nullptr;
@@ -121,11 +120,9 @@ void wayland_display::listen_global(void* data, wl_registry* registry, uint32_t
const cstring interface = cstring(itfc, strlen(itfc) + 1); const cstring interface = cstring(itfc, strlen(itfc) + 1);
if (interface == "wl_compositor") { if (interface == "wl_compositor") {
device->_compositor = static_cast<wl_compositor*>(wl_registry_bind(registry, name, wl_compositor_interface, version)); device->_compositor = static_cast<wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, version));
} else if (interface == "wl_shell") {
device->_shell = static_cast<wl_shell*>(wl_registry_bind(registry, name, wl_shell_interface, version));
} else if (interface == "wl_seat") { } else if (interface == "wl_seat") {
device->_seat = static_cast<wl_seat*>(wl_registry_bind(registry, name, wl_seat_interface, version)); device->_seat = static_cast<wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, version));
wl_seat_add_listener(device->_seat, &seat_listener, device); wl_seat_add_listener(device->_seat, &seat_listener, device);
} else if (interface == "wp_fifo_manager_v1") { } else if (interface == "wp_fifo_manager_v1") {
device->_fifo = true; device->_fifo = true;

View File

@@ -16,13 +16,13 @@
// 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/platform/linux/wayland/lib/wayland-client.h> #include <fennec/platform/linux/wayland/lib/headers/wayland-client-protocols.h>
#include <fennec/platform/linux/wayland/lib/loader.h> #include <fennec/platform/linux/wayland/lib/loader.h>
#define FENNEC_LIB(name) bool FENNEC_HAS_LIB_##name; #define FENNEC_LIB(name) bool FENNEC_HAS_LIB_##name;
#define FENNEC_SYMBOL(ret, fn, ...) using sym_##fn = ret(*)(__VA_ARGS__); \ #define FENNEC_SYMBOL(ret, fn, ...) using WAYLAND_sym_##fn = ret(*)(__VA_ARGS__); \
sym_##fn fn; WAYLAND_sym_##fn WAYLAND_##fn;
#define FENNEC_GLOBAL(type, name) type* name; #define FENNEC_GLOBAL(type, name) type* WAYLAND_##name;
#include <fennec/platform/linux/wayland/lib/sym.h> #include <fennec/platform/linux/wayland/lib/sym.h>
namespace fennec namespace fennec
@@ -57,10 +57,10 @@ bool load_symbols(platform* platform) {
return false; \ return false; \
} \ } \
current_lib = &_FENNEC_LIB_##lib; current_lib = &_FENNEC_LIB_##lib;
#define FENNEC_SYMBOL(ret, fn, ...) fn = (sym_##fn)(platform->find_symbol(current_lib->obj, #fn)); \ #define FENNEC_SYMBOL(ret, fn, ...) WAYLAND_##fn = (WAYLAND_sym_##fn)(platform->find_symbol(current_lib->obj, #fn)); \
assertf(fn != nullptr, "Failed to find symbol: " #fn); assertf(WAYLAND_##fn != nullptr, "Failed to find symbol: " #fn);
#define FENNEC_GLOBAL(type, name) name = (type*)(platform->find_symbol(current_lib->obj, #name)); \ #define FENNEC_GLOBAL(type, name) WAYLAND_##name = (type*)(platform->find_symbol(current_lib->obj, #name)); \
assertf(name != nullptr, "Failed to find global: " #name); assertf(WAYLAND_##name != nullptr, "Failed to find global: " #name);
#include <fennec/platform/linux/wayland/lib/sym.h> #include <fennec/platform/linux/wayland/lib/sym.h>
@@ -74,9 +74,9 @@ void unload_symbols(platform* platform) {
} }
#define FENNEC_LIB(lib) platform->unload_object(_FENNEC_LIB_##lib.obj); \ #define FENNEC_LIB(lib) platform->unload_object(_FENNEC_LIB_##lib.obj); \
_FENNEC_LIB_##lib.obj = nullptr; _FENNEC_LIB_##lib.obj = nullptr;
#define FENNEC_SYMBOL(ret, fn, ...) fn = nullptr; #define FENNEC_SYMBOL(ret, fn, ...) WAYLAND_##fn = nullptr;
#define FENNEC_GLOBAL(type, name) name = nullptr; #define FENNEC_GLOBAL(type, name) WAYLAND_##name = nullptr;
#include <fennec/platform/linux/wayland/lib/sym.h> #include <fennec/platform/linux/wayland/lib/sym.h>
} }

View File

@@ -0,0 +1,139 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
#include <fennec/platform/interface/gfxcontext.h>
#include <fennec/platform/interface/gfxsurface.h>
#include <fennec/platform/linux/wayland/window.h>
#include <fennec/platform/linux/wayland/lib/wayland.h>
namespace fennec
{
bool wayland_window::running() {
return _surface != nullptr;
}
void wayland_window::configure(const config& config) {
_config = config;
}
bool wayland_window::initialize(bool) {
wayland_display* display = static_cast<wayland_display*>(_display);
_handle = wl_compositor_create_surface(display->get_compositor());
_surface = display->get_context()->create_surface(this);
return false;
}
bool wayland_window::shutdown() {
delete _surface;
wl_surface_destroy(_handle);
_display = nullptr;
_surface = nullptr;
_shell = nullptr;
_handle = nullptr;
return false;
}
bool wayland_window::set_title(const cstring& title) {
if (not _config) {
return true;
}
_config->title = title;
wl_shell_surface_set_title(_shell, _config->title.cstr());
return false;
}
bool wayland_window::set_title(const string& title) {
if (not _config) {
return true;
}
_config->title = title;
wl_shell_surface_set_title(_shell, _config->title.cstr());
return false;
}
bool wayland_window::set_width(size_t w) {
if (not _config) {
return true;
}
_config->width = w;
_surface->resize(_config->width, _config->height);
return false;
}
bool wayland_window::set_height(size_t h) {
if (not _config) {
return true;
}
_config->height = h;
_surface->resize(_config->width, _config->height);
return false;
}
bool wayland_window::resize(size_t w, size_t h) {
if (not _config) {
return true;
}
_config->width = w;
_config->height = h;
_surface->resize(_config->width, _config->height);
return false;
}
bool wayland_window::set_resizable(bool) {
return false; // TODO
}
bool wayland_window::set_fullscreen_mode(fullscreen_mode) {
return false; // TODO
}
bool wayland_window::grab_keyboard(bool) {
return false; // TODO
}
bool wayland_window::grab_mouse(bool) {
return false; // TODO
}
bool wayland_window::block_screensaver(bool) {
return false; // TODO
}
wayland_window::wayland_window(wayland_display* display, wayland_window* parent)
: window(display, parent, this)
, _handle()
, _shell()
, _nfs_width(0), _nfs_height(0) {
}
wayland_window::~wayland_window() {
wayland_window::shutdown();
}
}

View File

@@ -21,6 +21,7 @@
#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 <fennec/platform/opengl/egl/surface.h>
#include <GL/gl.h> #include <GL/gl.h>
@@ -40,7 +41,10 @@ STATIC_CONSTRUCTOR(_egl_init) {
} }
eglcontext::eglcontext(display* display) eglcontext::eglcontext(display* display)
: gfxcontext(display, "EGL", this) { : gfxcontext(display, "EGL", this)
, _egldisplay(nullptr), _eglcontext(nullptr)
, _eglconfig(), _eglvmajor(0), _eglvminor(0)
, _eglctype(0), _extensions(nullptr) {
// Get the display format // Get the display format
const display::pixel_format& fmt = _display->get_color_format(); const display::pixel_format& fmt = _display->get_color_format();
@@ -121,7 +125,7 @@ bool eglcontext::connected() {
return _eglcontext != nullptr; return _eglcontext != nullptr;
} }
const cstring& eglcontext::get_context_name() { const cstring& eglcontext::get_name() {
static constexpr cstring opengl = "OpenGL"; static constexpr cstring opengl = "OpenGL";
static constexpr cstring gles = "GLES"; static constexpr cstring gles = "GLES";
static constexpr cstring openvg = "OpenVG"; // this should never be used static constexpr cstring openvg = "OpenVG"; // this should never be used
@@ -137,8 +141,13 @@ bool eglcontext::check_extension(const cstring& ext) {
return _extensions.find(ext) != _extensions.size(); return _extensions.find(ext) != _extensions.size();
} }
void eglcontext::make_current(gfxsurface*) { gfxsurface* eglcontext::create_surface(window* window) {
return new eglsurface(this, window);
}
void eglcontext::make_current(gfxsurface* surface) {
eglsurface* eglsurface = static_cast<fennec::eglsurface*>(surface);
eglMakeCurrent(_egldisplay, eglsurface->get_egl_surface(), eglsurface->get_egl_surface(), _eglcontext);
} }
void eglcontext::cleanup() { void eglcontext::cleanup() {

View File

@@ -0,0 +1,66 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
#include <fennec/platform/opengl/egl/surface.h>
#include <fennec/platform/linux/wayland/lib/wayland.h>
namespace fennec
{
eglsurface::~eglsurface() {
if (_window->is_type<wayland_window>()) {
wl_egl_window_destroy(static_cast<wl_egl_window*>(_handle));
}
}
void eglsurface::resize(size_t width, size_t height) {
gfxsurface::resize(width, height);
if (_window->is_type<wayland_window>()) {
wl_egl_window_resize(static_cast<wl_egl_window*>(_handle), width, height, 0, 0);
}
}
eglsurface::eglsurface(eglcontext* context, window* window)
: gfxsurface(context, window, this)
, _handle(nullptr)
, _surface(nullptr) {
const window::config& config = window->get_config();
if (window->is_type<wayland_window>()) {
_handle = wl_egl_window_create(window->get_native_handle(), config.width, config.height);
}
assert(
_handle != nullptr,
"Failed to create egl window!"
);
eglCreateWindowSurface(
context->get_egl_display(),
context->get_egl_config(),
reinterpret_cast<EGLNativeWindowType>(_handle),
nullptr
);
assert(
EGL_TRUE == eglMakeCurrent(context->get_egl_display(), _surface, _surface, context->get_egl_context()),
"Failed to create egl window!"
);
}
}

View File

@@ -34,13 +34,33 @@ inline void fennec_test_platform() {
platform* instance = platform::instance(); platform* instance = platform::instance();
instance->initialize(); instance->initialize();
fennec_test_run(instance->get_display() != nullptr, true); display* display = instance->get_display();
fennec_test_run(instance->get_display()->get_context() != nullptr, true);
std::cout << instance->get_display()->get_context()->get_context_name() << " "; fennec_test_run(display != nullptr, true);
std::cout << instance->get_display()->get_context()->get_version_major() << "."; fennec_test_run(display->get_context() != nullptr, true);
std::cout << instance->get_display()->get_context()->get_version_minor() << std::endl;
gfxcontext* gfxcontext = display->get_context();
std::cout << gfxcontext->get_name() << " ";
std::cout << gfxcontext->get_version_major() << ".";
std::cout << gfxcontext->get_version_minor() << std::endl;
window::config winconfig = {
string{"fennec_test_platform"},
window::flags_none,
1280, 720,
window::fullscreen_mode::windowed
};
window* window = display->create_window(nullptr);
fennec_test_run(window != nullptr, true);
window->configure(winconfig);
window->initialize(false);
fennec_test_run(window->running(), true);
delete window;
instance->shutdown(); instance->shutdown();
} }