Compare commits
6 Commits
custom_pla
...
f2a45aa913
| Author | SHA1 | Date | |
|---|---|---|---|
| f2a45aa913 | |||
| 3565bbbc52 | |||
| 375492ef7b | |||
| dbcb50349d | |||
| 992a02db3e | |||
| e1eaf97961 |
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
|||||||
[submodule "external/cpptrace"]
|
[submodule "external/cpptrace"]
|
||||||
path = external/cpptrace
|
path = external/cpptrace
|
||||||
url = https://github.com/jeremy-rifkin/cpptrace.git
|
url = https://github.com/jeremy-rifkin/cpptrace.git
|
||||||
|
[submodule "external/SDL"]
|
||||||
|
path = external/SDL
|
||||||
|
url = https://github.com/libsdl-org/SDL
|
||||||
|
|||||||
@@ -17,20 +17,10 @@
|
|||||||
# ======================================================================================================================
|
# ======================================================================================================================
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.30)
|
cmake_minimum_required(VERSION 3.30)
|
||||||
|
|
||||||
project(fennec)
|
project(fennec)
|
||||||
|
|
||||||
# External dependencies should be loaded here
|
|
||||||
add_subdirectory(external/cpptrace)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_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)
|
macro(fennec_add_sources)
|
||||||
list(APPEND FENNEC_EXTRA_SOURCES ${ARGN})
|
list(APPEND FENNEC_EXTRA_SOURCES ${ARGN})
|
||||||
endmacro()
|
endmacro()
|
||||||
@@ -43,6 +33,26 @@ macro(fennec_add_link_libraries)
|
|||||||
list(APPEND FENNEC_LINK_LIBRARIES ${ARGN})
|
list(APPEND FENNEC_LINK_LIBRARIES ${ARGN})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro(fennec_add_shared_libraries)
|
||||||
|
list(APPEND FENNEC_SHARED_LIBRARIES ${ARGN})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(fennec_add_link_options)
|
||||||
|
list(APPEND FENNEC_PRIVATE_LINK_OPTIONS ${ARGN})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# External dependencies should be loaded here
|
||||||
|
add_subdirectory(external/cpptrace)
|
||||||
|
include("${FENNEC_SOURCE_DIR}/cmake/sdl.cmake")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_C_STANDARD 23)
|
||||||
|
|
||||||
|
add_custom_target(fennec-dependencies
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "Running dependencies."
|
||||||
|
COMMENT "Running dependencies."
|
||||||
|
)
|
||||||
|
|
||||||
# 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")
|
||||||
@@ -62,7 +72,7 @@ include_directories(${FENNEC_SOURCE_DIR}/include)
|
|||||||
# Metaprogramming is a dependency for generating various type info before compilation of the engine.
|
# Metaprogramming is a dependency for generating various type info before compilation of the engine.
|
||||||
add_subdirectory(metaprogramming)
|
add_subdirectory(metaprogramming)
|
||||||
|
|
||||||
|
# Specify where to send libraries and executables
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME})
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${FENNEC_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME})
|
||||||
@@ -84,10 +94,18 @@ add_library(fennec STATIC
|
|||||||
include/fennec/scene/component.h
|
include/fennec/scene/component.h
|
||||||
|
|
||||||
|
|
||||||
|
# Renderers ============================================================================================================
|
||||||
|
include/fennec/renderers/interface/forward.h
|
||||||
|
|
||||||
|
include/fennec/renderers/interface/gfxcontext.h
|
||||||
|
include/fennec/renderers/interface/gfxsubpass.h
|
||||||
|
|
||||||
|
|
||||||
# CONTAINERS ===========================================================================================================
|
# CONTAINERS ===========================================================================================================
|
||||||
include/fennec/containers/containers.h
|
include/fennec/containers/containers.h
|
||||||
|
|
||||||
include/fennec/containers/array.h
|
include/fennec/containers/array.h
|
||||||
|
include/fennec/containers/bintree.h
|
||||||
include/fennec/containers/deque.h
|
include/fennec/containers/deque.h
|
||||||
include/fennec/containers/dynarray.h
|
include/fennec/containers/dynarray.h
|
||||||
include/fennec/containers/graph.h
|
include/fennec/containers/graph.h
|
||||||
@@ -97,6 +115,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/containers/optional.h
|
include/fennec/containers/optional.h
|
||||||
include/fennec/containers/pair.h
|
include/fennec/containers/pair.h
|
||||||
include/fennec/containers/rdtree.h
|
include/fennec/containers/rdtree.h
|
||||||
|
include/fennec/containers/sequence.h
|
||||||
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
|
||||||
@@ -124,7 +143,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/lang/type_sequences.h
|
include/fennec/lang/type_sequences.h
|
||||||
include/fennec/lang/type_traits.h
|
include/fennec/lang/type_traits.h
|
||||||
include/fennec/lang/type_transforms.h
|
include/fennec/lang/type_transforms.h
|
||||||
include/fennec/lang/typeuuid.h
|
include/fennec/lang/typed.h
|
||||||
include/fennec/lang/types.h
|
include/fennec/lang/types.h
|
||||||
include/fennec/lang/utility.h
|
include/fennec/lang/utility.h
|
||||||
include/fennec/lang/integer.h
|
include/fennec/lang/integer.h
|
||||||
@@ -212,14 +231,15 @@ add_library(fennec STATIC
|
|||||||
|
|
||||||
include/fennec/platform/interface/fwd.h
|
include/fennec/platform/interface/fwd.h
|
||||||
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/window.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/renderers/interface/gfxresourcepool.h
|
||||||
|
include/fennec/langproc/format/tokenizer.h
|
||||||
|
include/fennec/containers/priority_queue.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(fennec metaprogramming fennec-dependencies)
|
add_dependencies(fennec metaprogramming fennec-dependencies)
|
||||||
@@ -235,10 +255,16 @@ target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS}) # Do not comp
|
|||||||
|
|
||||||
target_link_libraries(fennec PRIVATE
|
target_link_libraries(fennec PRIVATE
|
||||||
${FENNEC_LINK_LIBRARIES}
|
${FENNEC_LINK_LIBRARIES}
|
||||||
|
${FENNEC_SHARED_LIBRARIES}
|
||||||
|
|
||||||
cpptrace::cpptrace
|
cpptrace::cpptrace
|
||||||
)
|
)
|
||||||
|
|
||||||
|
foreach (_LIB IN ITEMS ${FENNEC_SHARED_LIBRARIES})
|
||||||
|
add_custom_command(TARGET fennec POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_LINKER_FILE:${_LIB}> ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||||
|
)
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
|
||||||
# DOXYGEN ==============================================================================================================
|
# DOXYGEN ==============================================================================================================
|
||||||
|
|||||||
@@ -20,6 +20,6 @@
|
|||||||
|
|
||||||
add_compile_options("-mxsave" "-Wall" "-Wextra" "-pedantic" "-Werror")
|
add_compile_options("-mxsave" "-Wall" "-Wextra" "-pedantic" "-Werror")
|
||||||
|
|
||||||
set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
|
fennec_add_link_options("-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
|
||||||
|
|
||||||
list(APPEND FENNEC_COMPILE_DEFINITIONS _GLIBCXX_INCLUDE_NEXT_C_HEADERS=1 FENNEC_COMPILER_GCC=1 FENNEC_NO_INLINE=[[gnu::noinline]])
|
fennec_add_definitions(_GLIBCXX_INCLUDE_NEXT_C_HEADERS=1 FENNEC_COMPILER_GCC=1 FENNEC_NO_INLINE=[[gnu::noinline]])
|
||||||
@@ -34,9 +34,6 @@ macro(fennec_check_platform)
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(FENNEC_USER_CLIENT)
|
if(FENNEC_USER_CLIENT)
|
||||||
include("${FENNEC_SOURCE_DIR}/cmake/wayland.cmake")
|
|
||||||
|
|
||||||
fennec_check_wayland()
|
|
||||||
fennec_init_graphics()
|
fennec_init_graphics()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -32,26 +32,3 @@ if(TARGET OpenGL::GL AND TARGET GLEW::GLEW)
|
|||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "No Suitable OpenGL implementation found.")
|
message(FATAL_ERROR "No Suitable OpenGL implementation found.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FENNEC_GRAPHICS_WANT_EGL)
|
|
||||||
if(NOT TARGET OpenGL::EGL)
|
|
||||||
message(FATAL_ERROR "EGL Library not found.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "Found EGL: ${OPENGL_egl_LIBRARY}")
|
|
||||||
|
|
||||||
fennec_add_link_libraries(OpenGL::EGL)
|
|
||||||
fennec_add_definitions(FENNEC_GRAPHICS_EGL=1)
|
|
||||||
|
|
||||||
fennec_add_sources(
|
|
||||||
include/fennec/platform/opengl/lib/fwd.h
|
|
||||||
include/fennec/platform/opengl/lib/enum.h
|
|
||||||
include/fennec/platform/opengl/lib/buffer.h
|
|
||||||
include/fennec/platform/opengl/lib/texture.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/surface.h source/platform/opengl/egl/surface.cpp
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
30
cmake/sdl.cmake
Normal file
30
cmake/sdl.cmake
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# ======================================================================================================================
|
||||||
|
# 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/>.
|
||||||
|
# ======================================================================================================================
|
||||||
|
|
||||||
|
set(SDL_AUDIO OFF)
|
||||||
|
set(SDL_RENDER OFF)
|
||||||
|
add_subdirectory(${FENNEC_SOURCE_DIR}/external/SDL)
|
||||||
|
|
||||||
|
fennec_add_sources(
|
||||||
|
include/fennec/platform/sdl/sdlwindow.h
|
||||||
|
)
|
||||||
|
|
||||||
|
fennec_add_shared_libraries(
|
||||||
|
SDL3::SDL3-shared
|
||||||
|
)
|
||||||
|
|
||||||
@@ -1,122 +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/>.
|
|
||||||
# ======================================================================================================================
|
|
||||||
|
|
||||||
# https://gist.github.com/mariobadr/acc3c8adf4b4e722705be38c3deac59a
|
|
||||||
# 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")
|
|
||||||
set(_WAYLAND_PROT_C_CODE "${WAYLAND_SOURCES_DIR}/${_FILE}-client.c")
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${_SCANNER} client-header "${_XML}" "${_WAYLAND_PROT_H_CODE}"
|
|
||||||
)
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${_SCANNER} private-code "${_XML}" "${_WAYLAND_PROT_C_CODE}"
|
|
||||||
)
|
|
||||||
|
|
||||||
fennec_add_sources(${_WAYLAND_PROT_C_CODE} ${_WAYLAND_PROT_H_CODE})
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
macro(fennec_check_wayland)
|
|
||||||
set(WAYLAND_CLIENT_FOUND 0)
|
|
||||||
|
|
||||||
find_path(
|
|
||||||
WAYLAND_CLIENT_INCLUDE_DIR
|
|
||||||
NAMES wayland-client.h
|
|
||||||
)
|
|
||||||
find_library(
|
|
||||||
WAYLAND_CLIENT_LIBRARY
|
|
||||||
NAMES wayland-client libwayland-client
|
|
||||||
)
|
|
||||||
find_program(WAYLAND_SCANNER NAMES wayland-scanner)
|
|
||||||
|
|
||||||
# EGL is required
|
|
||||||
find_path(
|
|
||||||
WAYLAND_EGL_INCLUDE_DIR
|
|
||||||
NAMES wayland-egl.h
|
|
||||||
)
|
|
||||||
find_library(
|
|
||||||
WAYLAND_EGL_LIBRARY
|
|
||||||
NAMES wayland-egl libwayland-egl
|
|
||||||
)
|
|
||||||
|
|
||||||
if( (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY AND WAYLAND_SCANNER)
|
|
||||||
AND (WAYLAND_EGL_INCLUDE_DIR AND WAYLAND_EGL_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)
|
|
||||||
set(WAYLAND_SOURCES_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/sources)
|
|
||||||
|
|
||||||
# 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})
|
|
||||||
|
|
||||||
# search for xdg protocols
|
|
||||||
find_file(XDG_SHELL_PROTOCOL NAMES xdg-shell.xml PATHS /usr/share/wayland-protocols/stable/xdg-shell)
|
|
||||||
file(COPY ${XDG_SHELL_PROTOCOL} DESTINATION ${WAYLAND_PROTOCOLS_DIR})
|
|
||||||
|
|
||||||
# include sub-dependencies
|
|
||||||
include("${FENNEC_SOURCE_DIR}/cmake/xkb.cmake")
|
|
||||||
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(
|
|
||||||
WAYLAND_CLIENT_LIBRARY
|
|
||||||
${WAYLAND_CLIENT_LIBRARY}
|
|
||||||
NAME
|
|
||||||
)
|
|
||||||
get_filename_component(
|
|
||||||
WAYLAND_EGL_LIBRARY
|
|
||||||
${WAYLAND_EGL_LIBRARY}
|
|
||||||
NAME
|
|
||||||
)
|
|
||||||
|
|
||||||
set(WAYLAND_CLIENT_FOUND 1)
|
|
||||||
set(WAYLAND_EGL_FOUND 1)
|
|
||||||
set(FENNEC_GRAPHICS_WANT_EGL 1)
|
|
||||||
|
|
||||||
fennec_add_sources(
|
|
||||||
# Dynamic Library Files
|
|
||||||
include/fennec/platform/linux/wayland/lib/sym.h
|
|
||||||
include/fennec/platform/linux/wayland/lib/wayland.h
|
|
||||||
include/fennec/platform/linux/wayland/lib/loader.h source/platform/linux/wayland/lib/loader.cpp
|
|
||||||
|
|
||||||
# Fennec Files
|
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
fennec_add_definitions(
|
|
||||||
FENNEC_HAS_WAYLAND=1
|
|
||||||
FENNEC_LIB_WAYLAND="${WAYLAND_CLIENT_LIBRARY}"
|
|
||||||
FENNEC_LIB_WAYLAND_EGL="${WAYLAND_EGL_LIBRARY}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
@@ -1,58 +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/>.
|
|
||||||
# ======================================================================================================================
|
|
||||||
|
|
||||||
# this script finds libxkbcommon and dependencies
|
|
||||||
|
|
||||||
macro(fennec_check_xkb)
|
|
||||||
set(XKB_FOUND 0)
|
|
||||||
|
|
||||||
find_path(
|
|
||||||
XKB_INCLUDE_DIR
|
|
||||||
NAMES xkbcommon/xkbcommon.h
|
|
||||||
)
|
|
||||||
find_library(
|
|
||||||
XKB_LIBRARY
|
|
||||||
NAMES xkbcommon libxkbcommon
|
|
||||||
)
|
|
||||||
|
|
||||||
if(XKB_INCLUDE_DIR AND XKB_LIBRARY)
|
|
||||||
message(STATUS "Found XKB: ${XKB_LIBRARY}")
|
|
||||||
|
|
||||||
get_filename_component(
|
|
||||||
XKB_LIBRARY
|
|
||||||
${XKB_LIBRARY}
|
|
||||||
NAME
|
|
||||||
)
|
|
||||||
|
|
||||||
set(XKB_FOUND 1)
|
|
||||||
|
|
||||||
fennec_add_sources(
|
|
||||||
# Dynamic Library Files
|
|
||||||
include/fennec/platform/linux/xkb/lib/sym.h
|
|
||||||
include/fennec/platform/linux/xkb/lib/xkb.h
|
|
||||||
include/fennec/platform/linux/xkb/lib/loader.h source/platform/linux/xkb/lib/loader.cpp
|
|
||||||
|
|
||||||
# Fennec files
|
|
||||||
)
|
|
||||||
|
|
||||||
fennec_add_definitions(
|
|
||||||
FENNEC_HAS_XKB=1
|
|
||||||
FENNEC_LIB_XKB="${XKB_LIBRARY}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
1
external/SDL
vendored
Submodule
1
external/SDL
vendored
Submodule
Submodule external/SDL added at dee2414ee7
@@ -371,7 +371,7 @@ class RDTreePrinter:
|
|||||||
index += '└'
|
index += '└'
|
||||||
|
|
||||||
index += '─'
|
index += '─'
|
||||||
index += '[{}, {}]'.format(node, i)
|
index += '[{}]'.format(node)
|
||||||
return index, value
|
return index, value
|
||||||
|
|
||||||
|
|
||||||
@@ -389,6 +389,66 @@ class RDTreePrinter:
|
|||||||
return self.Iterator(self.tree, 0, self.capacity)
|
return self.Iterator(self.tree, 0, self.capacity)
|
||||||
|
|
||||||
|
|
||||||
|
# BINTREE ==============================================================================================================
|
||||||
|
|
||||||
|
class BinTreePrinter:
|
||||||
|
"""Print a fennec::bintree"""
|
||||||
|
|
||||||
|
class Iterator:
|
||||||
|
def __init__(self, tree, node, capacity):
|
||||||
|
self.tree = tree
|
||||||
|
self.capacity = capacity
|
||||||
|
self.visit = deque()
|
||||||
|
|
||||||
|
self.visit.append((node, 0, 0))
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if len(self.visit) == 0:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
node = self.visit[0][0]
|
||||||
|
i = self.visit[0][1]
|
||||||
|
depth = self.visit[0][2]
|
||||||
|
self.visit.popleft()
|
||||||
|
|
||||||
|
value = self.tree[node]['value']
|
||||||
|
left = self.tree[node]['left']
|
||||||
|
right = self.tree[node]['right']
|
||||||
|
|
||||||
|
if right < self.capacity:
|
||||||
|
self.visit.appendleft((right, 1, depth + 1))
|
||||||
|
if left < self.capacity:
|
||||||
|
self.visit.appendleft((left, 0, depth + 1))
|
||||||
|
|
||||||
|
index = '⠀' * depth * 2 # Uses Braille Space, otherwise it would get eaten as whitespace by parsers
|
||||||
|
if i == 0:
|
||||||
|
index += '├'
|
||||||
|
else:
|
||||||
|
index += '└'
|
||||||
|
|
||||||
|
index += '─'
|
||||||
|
index += '[{}]'.format(node)
|
||||||
|
return index, value
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.tree = val['_table']['_data']
|
||||||
|
self.size = val['_size']
|
||||||
|
self.root = val['_root']
|
||||||
|
self.capacity = val['_table']['_capacity']
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
if self.size == 0:
|
||||||
|
return "{ empty }"
|
||||||
|
return "{ size = " + str(self.size) + " }"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
return self.Iterator(self.tree, self.root, self.capacity)
|
||||||
|
|
||||||
|
|
||||||
# Graph ================================================================================================================
|
# Graph ================================================================================================================
|
||||||
|
|
||||||
class GraphPrinter:
|
class GraphPrinter:
|
||||||
@@ -475,6 +535,8 @@ def register_printers():
|
|||||||
pp.add_printer('fennec::pair', '^fennec::pair<.*>$', PairPrinter)
|
pp.add_printer('fennec::pair', '^fennec::pair<.*>$', PairPrinter)
|
||||||
pp.add_printer('fennec::set', '^fennec::set<.*>$', SetPrinter)
|
pp.add_printer('fennec::set', '^fennec::set<.*>$', SetPrinter)
|
||||||
pp.add_printer('fennec::rdtree', '^fennec::rdtree<.*>$', RDTreePrinter)
|
pp.add_printer('fennec::rdtree', '^fennec::rdtree<.*>$', RDTreePrinter)
|
||||||
|
pp.add_printer('fennec::bintree', '^fennec::bintree<.*>$', BinTreePrinter)
|
||||||
|
pp.add_printer('fennec::sequence', '^fennec::sequence<.*>$', BinTreePrinter)
|
||||||
pp.add_printer('fennec::tuple', '^fennec::tuple<.*>$', TuplePrinter)
|
pp.add_printer('fennec::tuple', '^fennec::tuple<.*>$', TuplePrinter)
|
||||||
return pp
|
return pp
|
||||||
|
|
||||||
|
|||||||
827
include/fennec/containers/bintree.h
Normal file
827
include/fennec/containers/bintree.h
Normal file
@@ -0,0 +1,827 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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 bintree.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_BINTREE_H
|
||||||
|
#define FENNEC_CONTAINERS_BINTREE_H
|
||||||
|
|
||||||
|
#include <fennec/containers/dynarray.h>
|
||||||
|
#include <fennec/containers/list.h>
|
||||||
|
#include <fennec/containers/optional.h>
|
||||||
|
#include <fennec/containers/traversal.h>
|
||||||
|
#include <fennec/math/exponential.h>
|
||||||
|
#include <fennec/memory/allocator.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Structure defining a binary tree
|
||||||
|
/// \tparam TypeT The data type
|
||||||
|
/// \tparam AllocT An allocator class
|
||||||
|
template<typename TypeT, class AllocT = allocator<TypeT>>
|
||||||
|
struct bintree {
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
protected:
|
||||||
|
struct node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_t = TypeT;
|
||||||
|
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
|
||||||
|
static constexpr size_t npos = -1;
|
||||||
|
inline static size_t sink = npos;
|
||||||
|
|
||||||
|
friend class iterator;
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct node {
|
||||||
|
value_t value;
|
||||||
|
size_t parent, left, right;
|
||||||
|
size_t depth;
|
||||||
|
|
||||||
|
constexpr node()
|
||||||
|
: value(nullopt)
|
||||||
|
, parent(npos), left(npos), right(npos)
|
||||||
|
, depth(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr node(size_t p, size_t l, size_t r, size_t d, ArgsT&&...args)
|
||||||
|
: value(fennec::forward<ArgsT>(args)...)
|
||||||
|
, parent(p), left(l), right(r)
|
||||||
|
, depth(d) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ~node() {
|
||||||
|
parent = npos;
|
||||||
|
left = npos;
|
||||||
|
right = npos;
|
||||||
|
depth = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t& operator[](bool d) {
|
||||||
|
return d ? right : left;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using table_t = allocation<node, alloc_t>;
|
||||||
|
using freed_t = list<size_t, alloc_t>;
|
||||||
|
|
||||||
|
// Constructors & Destructor ===========================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Constructors & Destructor
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor, initializes an empty tree
|
||||||
|
constexpr bintree()
|
||||||
|
: _table()
|
||||||
|
, _freed()
|
||||||
|
, _root(npos)
|
||||||
|
, _size(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor, takes ownership of a tree
|
||||||
|
/// \param tree The tree to take ownership of
|
||||||
|
constexpr bintree(bintree&& tree) noexcept
|
||||||
|
: _table(fennec::move(tree._table))
|
||||||
|
, _freed(fennec::move(tree._freed))
|
||||||
|
, _root(tree._root)
|
||||||
|
, _size(tree._size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor, copies a tree
|
||||||
|
/// \param tree The tree to copy
|
||||||
|
constexpr bintree(const bintree& tree)
|
||||||
|
: _table(tree._table)
|
||||||
|
, _freed(tree._freed)
|
||||||
|
, _root(tree._root)
|
||||||
|
, _size(tree._size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructor, clears the tree
|
||||||
|
constexpr ~bintree() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties ==========================================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The number of elements in the tree
|
||||||
|
constexpr size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns `true` when there are no elements in the tree, `false` otherwise.
|
||||||
|
constexpr bool empty() const {
|
||||||
|
return _size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The capacity of the underlying allocation
|
||||||
|
constexpr size_t capacity() const {
|
||||||
|
return _table.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The next id to be returned by `insert` or `emplace`.
|
||||||
|
constexpr size_t next_id() const {
|
||||||
|
size_t i = _size;
|
||||||
|
if (not _freed.empty()) {
|
||||||
|
i = _freed.front();
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The next id to be returned by `insert` or `emplace`.
|
||||||
|
constexpr size_t root() const {
|
||||||
|
return _root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Navigation ==========================================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Navigation
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The parent of node `i`
|
||||||
|
constexpr size_t parent(size_t i) const {
|
||||||
|
return i >= _table.size() ? npos : _table[i].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The grandparent of node `i`
|
||||||
|
constexpr size_t grandparent(size_t i) const {
|
||||||
|
return parent(parent(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The left child of node `i`
|
||||||
|
constexpr size_t left(size_t i) const {
|
||||||
|
return i >= _table.size() ? npos : _table[i].left;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The right child of node `i`
|
||||||
|
constexpr size_t right(size_t i) const {
|
||||||
|
return i >= _table.size() ? npos : _table[i].right;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \param dir The direction to go `true` for right, `false` for left
|
||||||
|
/// \returns The child in the direction specified by `dir`
|
||||||
|
constexpr size_t child(size_t i, bool dir) const {
|
||||||
|
return dir ? right(i) : left(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns `true` if `i` is the right node of `parent(i)`, `false` otherwise
|
||||||
|
constexpr bool direction(size_t i) const {
|
||||||
|
size_t p = parent(i);
|
||||||
|
if (p >= _table.capacity()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return i == right(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief \f$O(1)\f$
|
||||||
|
/// \param i The id of the node
|
||||||
|
/// \returns The id of the sibling of `i`
|
||||||
|
constexpr size_t sibling(size_t i) const {
|
||||||
|
size_t p = parent(i);
|
||||||
|
size_t l = left(p);
|
||||||
|
size_t r = right(p);
|
||||||
|
return i == l ? l : r;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Short for "Parent Sibling," \f$O(1)\f$
|
||||||
|
/// \param i The id of the node
|
||||||
|
/// \returns The id of the parents' sibling of `i`
|
||||||
|
constexpr size_t parsib(size_t i) const {
|
||||||
|
return sibling(parent(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(\log n)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The depth of node `i`
|
||||||
|
constexpr size_t depth(size_t i) const {
|
||||||
|
return i >= _table.size() ? npos : _table[i].depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief \f$O(\log n)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The id of the left-most node of `i`
|
||||||
|
constexpr size_t left_most(size_t i) const {
|
||||||
|
if (i >= _table.size()) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
while (_table[i].left != npos) {
|
||||||
|
i = _table[i].left;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief \f$O(\log n)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns The id of the right-most node of `i`
|
||||||
|
constexpr size_t right_most(size_t i) const {
|
||||||
|
if (i >= _table.size()) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
while (_table[i].right != npos) {
|
||||||
|
i = _table[i].right;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Access ==============================================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Access
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns `nullptr` if node `i` does not exist, otherwise, a pointer to the value of node `i`
|
||||||
|
constexpr value_t* operator[](size_t i) {
|
||||||
|
if (i >= _table.size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return _table[i] ? &*_table[i] : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details Const Access, \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \returns `nullptr` if node `i` does not exist, otherwise, a pointer to the value of node `i`
|
||||||
|
constexpr const value_t* operator[](size_t i) const {
|
||||||
|
if (i >= _table.size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return _table[i] ? &*_table[i] : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
|
/// \name Modifiers
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Left Insertion, constructs a new node as the left child of `p`
|
||||||
|
/// \details If the left node of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param val The object to move into the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert_left(size_t p, value_t&& val) {
|
||||||
|
return this->_insert_left(p, fennec::forward<value_t>(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Left Insertion, constructs a new node as the left child of `p`
|
||||||
|
/// \details If the left node of `p` already exists, the copy assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param val The object to copy to the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert_left(size_t p, const value_t& val) {
|
||||||
|
return this->_insert_left(p, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Left Insertion, constructs a new node as the left child of `p`
|
||||||
|
/// \details If the left node of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param args The arguments to construct the new node with
|
||||||
|
/// \returns The id of the new node
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t emplace_left(size_t p, ArgsT&&...args) {
|
||||||
|
return this->_insert_left(p, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Right Insertion, constructs a new node as the right child of `p`
|
||||||
|
/// \details If the right node of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param val The object to move into the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert_right(size_t p, value_t&& val) {
|
||||||
|
return this->_insert_right(p, fennec::forward<value_t>(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Right Insertion, constructs a new node as the right child of `p`
|
||||||
|
/// \details If the right node of `p` already exists, the copy assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param val The object to copy to the new node
|
||||||
|
/// \returns The id of the new node
|
||||||
|
constexpr size_t insert_right(size_t p, const value_t& val) {
|
||||||
|
return this->_insert_right(p, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Right Insertion, constructs a new node as the right child of `p`
|
||||||
|
/// \details If the right node of `p` already exists, the move assignment operator is used instead
|
||||||
|
/// \param p The parent node
|
||||||
|
/// \param args The arguments to construct the new node with
|
||||||
|
/// \returns The id of the new node
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t emplace_right(size_t p, ArgsT&&...args) {
|
||||||
|
return this->_insert_right(p, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Perform a Left Tree Rotation at `i`
|
||||||
|
/// \param i The root node for the rotation
|
||||||
|
constexpr void rotate_left(size_t i) {
|
||||||
|
if (i >=_table.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t l = i;
|
||||||
|
size_t p = parent(l);
|
||||||
|
size_t r = right(l);
|
||||||
|
|
||||||
|
if (p == npos) {
|
||||||
|
_root = r;
|
||||||
|
} else if (l == _table[p].left) {
|
||||||
|
_table[p].left = r;
|
||||||
|
} else {
|
||||||
|
_table[p].right = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
_table[l].parent = r;
|
||||||
|
_table[l].right = _table[r].left;
|
||||||
|
|
||||||
|
_table[r].parent = p;
|
||||||
|
_table[r].left = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Perform a Right Tree Rotation at `i`
|
||||||
|
/// \param i The root node for the rotation
|
||||||
|
constexpr void rotate_right(size_t i) {
|
||||||
|
if (i >=_table.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t r = i;
|
||||||
|
size_t p = parent(r);
|
||||||
|
size_t l = left(r);
|
||||||
|
|
||||||
|
if (p == npos) {
|
||||||
|
_root = l;
|
||||||
|
} else if (r == _table[p].left) {
|
||||||
|
_table[p].left = l;
|
||||||
|
} else {
|
||||||
|
_table[p].right = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
_table[r].parent = l;
|
||||||
|
_table[r].left = _table[l].right;
|
||||||
|
|
||||||
|
_table[l].parent = p;
|
||||||
|
_table[l].right = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Perform a Tree Rotation at `i` in the specified direction
|
||||||
|
/// \param i The root node for the rotation
|
||||||
|
/// \param dir The direction to rotate, `true` for right, `false` for left
|
||||||
|
constexpr size_t rotate(size_t sub, bool dir) {
|
||||||
|
if (sub >=_table.size()) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
size_t sub_parent = parent(sub);
|
||||||
|
size_t new_root = child(sub, not dir);
|
||||||
|
size_t new_child = child(new_root, dir);
|
||||||
|
|
||||||
|
child(sub, not dir) = new_child;
|
||||||
|
parent(new_child) = sub;
|
||||||
|
child(new_root, dir) = sub;
|
||||||
|
|
||||||
|
parent(new_root) = sub_parent;
|
||||||
|
parent(sub) = new_root;
|
||||||
|
if (sub_parent != npos) {
|
||||||
|
child(sub_parent, sub == right(sub_parent)) = new_root;
|
||||||
|
} else {
|
||||||
|
_root = new_root;
|
||||||
|
}
|
||||||
|
return new_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Clears the tree, destroying all elements
|
||||||
|
constexpr void clear() {
|
||||||
|
list<size_t> queue;
|
||||||
|
|
||||||
|
if (_root != npos) {
|
||||||
|
queue.push_back(_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (not queue.empty()) {
|
||||||
|
size_t i = queue.front();
|
||||||
|
queue.pop_front();
|
||||||
|
|
||||||
|
if (_table[i].left != npos) {
|
||||||
|
queue.push_front(_table[i].left);
|
||||||
|
}
|
||||||
|
if (_table[i].right != npos) {
|
||||||
|
queue.push_front(_table[i].right);
|
||||||
|
}
|
||||||
|
|
||||||
|
fennec::destruct(&_table[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_size = 0;
|
||||||
|
_root = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Traversal ===========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverse the tree using a specified order and visiting functor
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// The visitor should accept a reference to a value of type `TypeT` and a `size_t` which contains the node's id.
|
||||||
|
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||||
|
///
|
||||||
|
/// \tparam OrderT The order with which to traverse the tree.
|
||||||
|
/// \tparam VisitorT The visitor, should fulfill the signature `uint8_t visit(TypeT&, size_t)`
|
||||||
|
/// \param visit The visiting object
|
||||||
|
/// \param i The node to start at
|
||||||
|
template<typename OrderT, typename VisitorT>
|
||||||
|
constexpr void traverse(VisitorT&& visit, size_t i = root) {
|
||||||
|
OrderT order;
|
||||||
|
i = order(*this, i);
|
||||||
|
while (i != npos) {
|
||||||
|
uint8_t mode = traversal_control_continue;
|
||||||
|
if (_table[i].value) {
|
||||||
|
mode = visit(*_table[i].value, i);
|
||||||
|
}
|
||||||
|
if (mode == traversal_control_break) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i = order[*this, i, mode];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct breadth_first {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
size_t operator()(const bintree&, size_t start) {
|
||||||
|
return head = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t operator[](const bintree& tree, size_t node, uint8_t mode) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t lft = tree.left(tree.parent(node));
|
||||||
|
size_t nxt = lft == node ? tree.right(tree.parent(node)) : npos;
|
||||||
|
size_t chd = tree.left(node);
|
||||||
|
|
||||||
|
if (nxt != npos && node != head) {
|
||||||
|
visit.push_front(nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chd != npos && mode != traversal_control_jump_over) {
|
||||||
|
visit.push_back(chd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pre_order {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t operator()(const bintree&, size_t start) {
|
||||||
|
head = start;
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t mode) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nxt = tree.sibling(node);
|
||||||
|
size_t chd = tree.left(node);
|
||||||
|
nxt = node == nxt ? npos : nxt;
|
||||||
|
|
||||||
|
if (nxt != npos && node != head) {
|
||||||
|
visit.push_front(nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chd != npos && mode != traversal_control_jump_over) {
|
||||||
|
visit.push_front(chd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct in_order {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t operator()(const bintree& tree, size_t start) {
|
||||||
|
head = start;
|
||||||
|
return tree.left_most(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t prnt = tree.parent(node);
|
||||||
|
size_t next = tree.sibling(node);
|
||||||
|
next = node == next ? npos : next;
|
||||||
|
|
||||||
|
if (node != head) {
|
||||||
|
if (tree.left(prnt) == node) {
|
||||||
|
visit.push_back(prnt);
|
||||||
|
if (next != npos) {
|
||||||
|
visit.push_back(tree.left_most(next));
|
||||||
|
}
|
||||||
|
} else if (next != npos) {
|
||||||
|
visit.push_front(tree.left_most(next));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct post_order {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t operator()(const bintree& tree, size_t start) {
|
||||||
|
head = start;
|
||||||
|
return tree.left_most(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t prnt = tree.parent(node);
|
||||||
|
size_t next = tree.sibling(node);
|
||||||
|
next = node == next ? npos : next;
|
||||||
|
|
||||||
|
if (node != head) {
|
||||||
|
if (next != npos) {
|
||||||
|
visit.push_front(tree.left_most(next));
|
||||||
|
} else {
|
||||||
|
visit.push_front(prnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
protected:
|
||||||
|
bintree* _tree;
|
||||||
|
in_order _order;
|
||||||
|
size_t _n;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr iterator(bintree* tree, size_t root, size_t node)
|
||||||
|
: _tree(tree)
|
||||||
|
, _order()
|
||||||
|
, _n(node) {
|
||||||
|
_order(*tree, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t index() const {
|
||||||
|
return _n;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator& operator++() {
|
||||||
|
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t& operator*() {
|
||||||
|
return _tree[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t* operator->() {
|
||||||
|
return &_tree[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t& operator*() const {
|
||||||
|
return _tree[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t* operator->() const {
|
||||||
|
return &_tree[_n];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const iterator& it) {
|
||||||
|
return _tree == it._tree and _n == it._n;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const iterator& it) {
|
||||||
|
return _tree != it._tree or _n != it._n;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fields ==============================================================================================================
|
||||||
|
protected:
|
||||||
|
table_t _table;
|
||||||
|
freed_t _freed;
|
||||||
|
size_t _root, _size;
|
||||||
|
|
||||||
|
// Helpers =============================================================================================================
|
||||||
|
|
||||||
|
constexpr size_t _next_free() {
|
||||||
|
size_t i = _size;
|
||||||
|
if (not _freed.empty()) {
|
||||||
|
i = _freed.front();
|
||||||
|
_freed.pop_front();
|
||||||
|
}
|
||||||
|
if (i >= _table.capacity()) {
|
||||||
|
_table.creallocate(2 * fennec::max(_table.capacity(), size_t(4)));
|
||||||
|
}
|
||||||
|
++_size;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t _insert_left(size_t p, ArgsT&&...args) {
|
||||||
|
size_t i = p == npos ? _root : left(p);
|
||||||
|
if (i != npos) {
|
||||||
|
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
|
||||||
|
} else {
|
||||||
|
size_t d = 1;
|
||||||
|
i = _next_free();
|
||||||
|
if (p != npos) {
|
||||||
|
d = depth(p) + 1;
|
||||||
|
_table[p].left = i;
|
||||||
|
}
|
||||||
|
fennec::construct(&_table[i], p, npos, npos, d, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t _insert_right(size_t p, ArgsT&&...args) {
|
||||||
|
size_t i = p == npos ? _root : right(p);
|
||||||
|
if (i != npos) {
|
||||||
|
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
|
||||||
|
if (p == npos || _root == npos) {
|
||||||
|
_root = i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t d = 1;
|
||||||
|
i = _next_free();
|
||||||
|
if (p != npos) {
|
||||||
|
d = depth(p) + 1;
|
||||||
|
_table[p].right = i;
|
||||||
|
}
|
||||||
|
fennec::construct(&_table[i], p, npos, npos, d, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr size_t& parent(size_t i) {
|
||||||
|
return i >= _table.size() ? sink : _table[i].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& grandparent(size_t i) {
|
||||||
|
return parent(parent(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& left(size_t i) {
|
||||||
|
return i >= _table.size() ? sink : _table[i].left;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& right(size_t i) {
|
||||||
|
return i >= _table.size() ? sink : _table[i].right;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& child(size_t i, bool dir) {
|
||||||
|
return dir ? right(i) : left(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& sibling(size_t i) {
|
||||||
|
size_t p = parent(i);
|
||||||
|
size_t& l = left(p);
|
||||||
|
size_t& r = right(p);
|
||||||
|
return i == l ? l : r;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t& parsib(size_t i) {
|
||||||
|
return sibling(parent(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_BINTREE_H
|
||||||
@@ -25,7 +25,7 @@ namespace fennec::detail
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
template <std::size_t I, typename T>
|
template <size_t I, typename T>
|
||||||
struct _tuple_leaf
|
struct _tuple_leaf
|
||||||
{
|
{
|
||||||
template <typename ArgT>
|
template <typename ArgT>
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ public:
|
|||||||
for (const value_t& it : l) {
|
for (const value_t& it : l) {
|
||||||
this->push_back(it);
|
this->push_back(it);
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -152,6 +153,7 @@ public:
|
|||||||
_freed = fennec::move(l._freed);
|
_freed = fennec::move(l._freed);
|
||||||
_root = l._root; _last = l._last;
|
_root = l._root; _last = l._last;
|
||||||
_size = l._size;
|
_size = l._size;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@@ -164,15 +166,21 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The size of the list in elements.
|
/// \returns The size of the list in elements.
|
||||||
constexpr size_t size() const { return _size; }
|
constexpr size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The capacity of the list in elements.
|
/// \returns The capacity of the list in elements.
|
||||||
constexpr size_t capacity() const { return _table.capacity(); }
|
constexpr size_t capacity() const {
|
||||||
|
return _table.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when the list is empty, `false` otherwise.
|
/// \returns `true` when the list is empty, `false` otherwise.
|
||||||
constexpr bool empty() const { return _root == npos; }
|
constexpr bool empty() const {
|
||||||
|
return _root == npos;
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|||||||
@@ -1,586 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \file multiset.h
|
|
||||||
/// \brief A header containing the definition for a set of repeating values
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// \details
|
|
||||||
/// \author Medusa Slockbower
|
|
||||||
///
|
|
||||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
|
||||||
///
|
|
||||||
///
|
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_MULTISET_H
|
|
||||||
#define FENNEC_CONTAINERS_MULTISET_H
|
|
||||||
|
|
||||||
// https://programming.guide/robin-hood-hashing.html
|
|
||||||
|
|
||||||
#include <fennec/containers/optional.h>
|
|
||||||
#include <fennec/containers/multiset.h>
|
|
||||||
#include <fennec/lang/compare.h>
|
|
||||||
#include <fennec/math/ext/primes.h>
|
|
||||||
#include <fennec/memory/allocator.h>
|
|
||||||
#include <fennec/lang/hashing.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// \brief A Data Structure that defines a set of elements that may repeat
|
|
||||||
/// \details
|
|
||||||
/// | Property | Value |
|
|
||||||
/// |:----------:|:----------:|
|
|
||||||
/// | stable | ⛔ |
|
|
||||||
/// | dynamic | ✅ |
|
|
||||||
/// | homogenous | ✅ |
|
|
||||||
/// | distinct | ⛔ |
|
|
||||||
/// | ordered | ⛔ |
|
|
||||||
/// | space | \f$O(N)\f$ |
|
|
||||||
/// | linear | ✅ |
|
|
||||||
/// | access | \f$O(1)\f$ |
|
|
||||||
/// | find | \f$O(1)\f$ |
|
|
||||||
/// | insertion | \f$O(1)\f$ |
|
|
||||||
/// | deletion | \f$O(1)\f$ |
|
|
||||||
///
|
|
||||||
/// \tparam TypeT The type to contain
|
|
||||||
template<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>>
|
|
||||||
struct multiset {
|
|
||||||
|
|
||||||
// Definitions =========================================================================================================
|
|
||||||
public:
|
|
||||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>;
|
|
||||||
using hash_t = Hash;
|
|
||||||
using equal_t = Equals;
|
|
||||||
using elem_t = TypeT;
|
|
||||||
|
|
||||||
class iterator;
|
|
||||||
class value_iterator;
|
|
||||||
static constexpr size_t npos = -1;
|
|
||||||
static constexpr double default_load = 0.8;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct node {
|
|
||||||
optional<elem_t> value;
|
|
||||||
int psl;
|
|
||||||
|
|
||||||
constexpr node() = default;
|
|
||||||
constexpr ~node() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// \name Constructors & Destructor
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Default Constructor, initializes empty multiset
|
|
||||||
constexpr multiset()
|
|
||||||
: _alloc()
|
|
||||||
, _hash()
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Copy Constructor, initializes empty multiset with a hash
|
|
||||||
constexpr multiset(const hash_t& hash)
|
|
||||||
: _alloc()
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Constructor, initializes empty multiset with a hash
|
|
||||||
constexpr multiset(hash_t&& hash) noexcept
|
|
||||||
: _alloc()
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Alloc Copy Constructor, initializes empty multiset with an allocator
|
|
||||||
constexpr multiset(const alloc_t& alloc)
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash()
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Alloc Move Constructor, initializes empty multiset with an allocator
|
|
||||||
constexpr multiset(alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash()
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Alloc Copy Constructor, initializes empty multiset with a hash and allocator
|
|
||||||
constexpr multiset(const hash_t& hash, const alloc_t& alloc)
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Copy Alloc Move Constructor, initializes empty multiset with a hash and allocator
|
|
||||||
constexpr multiset(const hash_t& hash, alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Alloc Move Constructor, initializes empty multiset with a hash and allocator
|
|
||||||
constexpr multiset(hash_t&& hash, alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Alloc Copy Constructor, initializes empty multiset with a hash and allocator
|
|
||||||
constexpr multiset(hash_t&& hash, const alloc_t& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Set Copy Constructor
|
|
||||||
/// \param multiset Set to copy
|
|
||||||
constexpr multiset(const multiset& multiset)
|
|
||||||
: _alloc( multiset._alloc)
|
|
||||||
, _hash( multiset._hash)
|
|
||||||
, _size( multiset._size)
|
|
||||||
, _sumpsl( multiset._sumpsl)
|
|
||||||
, _load( multiset._load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Set Move Constructor
|
|
||||||
/// \param multiset Set to move
|
|
||||||
constexpr multiset(multiset&& multiset) noexcept
|
|
||||||
: _alloc(fennec::move( multiset._alloc))
|
|
||||||
, _hash(fennec::move( multiset._hash))
|
|
||||||
, _size(fennec::move( multiset._size))
|
|
||||||
, _sumpsl( multiset._sumpsl)
|
|
||||||
, _load( multiset._load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Destructor, destructs all elements and releases the allocation
|
|
||||||
constexpr ~multiset() {
|
|
||||||
for (size_t i = 0; i < capacity(); ++i) {
|
|
||||||
_alloc[i].value = nullopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// Properties ==========================================================================================================
|
|
||||||
|
|
||||||
/// \name Properties
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns Size of the multiset in elements
|
|
||||||
constexpr size_t size() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns `true` when the set is empty, `false` otherwise
|
|
||||||
constexpr bool empty() const {
|
|
||||||
return _size == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns Capacity of the multiset in elements
|
|
||||||
constexpr size_t capacity() const {
|
|
||||||
return _alloc.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// Access ==============================================================================================================
|
|
||||||
|
|
||||||
/// \name Access
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Find an Element
|
|
||||||
/// \param val Value to find
|
|
||||||
/// \returns An iterator at the location of the first instance of `value`
|
|
||||||
constexpr iterator find(const elem_t& val, size_t c = 0) const {
|
|
||||||
if (capacity() == 0) {
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
size_t s = _hash(val) % capacity(); // Initial search index
|
|
||||||
int psl = (_size != 0) ? _sumpsl / _size : 0; // Initial psl
|
|
||||||
size_t i = (s + psl) % capacity(); // Median search
|
|
||||||
size_t n = 0;
|
|
||||||
|
|
||||||
// Check the first element;
|
|
||||||
if (_alloc[i].psl >= psl && _alloc[i].value) {
|
|
||||||
if (*_alloc[i].value == val) {
|
|
||||||
return iterator(this, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop while there is a value and its psl is greater than our probe
|
|
||||||
while (c > 0) {
|
|
||||||
++n;
|
|
||||||
size_t i0 = (i + capacity() - n) % capacity(); // Prevent index underflow
|
|
||||||
size_t i1 = (i + n) % capacity();
|
|
||||||
int p0 = psl - n, p1 = psl + n;
|
|
||||||
bool c0 = p0 >= 0 && _alloc[i0].psl >= p0, c1 = _alloc[i1].psl >= p1; // Check that we are in range
|
|
||||||
|
|
||||||
if (c0 && _alloc[i0].value) {
|
|
||||||
if (*_alloc[i0].value == val) {
|
|
||||||
if (c-- == 0) {
|
|
||||||
return iterator(this, i0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c1 && _alloc[i1].value) {
|
|
||||||
if (*_alloc[i1].value == val) {
|
|
||||||
if (c-- == 0) {
|
|
||||||
return iterator(this, i1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (not(c0 or c1)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return iterator(this, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Check if a multiset contains a value
|
|
||||||
/// \param val Value to check
|
|
||||||
/// \returns `true` if `val` can be found, `false` otherwise
|
|
||||||
constexpr bool contains(const elem_t& val) const {
|
|
||||||
return this->find(val) != end();
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Iterator Access
|
|
||||||
/// \param it Location to access
|
|
||||||
/// \returns A pointer to the element, `nullptr` if not found.
|
|
||||||
/// The value should not be changed in a manner that will change the hash of the element.
|
|
||||||
constexpr elem_t* at(const iterator& it) {
|
|
||||||
if (it == end()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (not _alloc[it._i].value) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return &*_alloc[it._i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Iterator Const Access
|
|
||||||
/// \param it Location to access
|
|
||||||
/// \returns A const-qualified pointer to the element, `nullptr` if not found.
|
|
||||||
constexpr const elem_t* at(const iterator& it) const {
|
|
||||||
if (not _alloc[it._i].value) return nullptr;
|
|
||||||
return &*_alloc[it._i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
// Modifiers ===========================================================================================================
|
|
||||||
|
|
||||||
/// \name Modifiers
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Move Insertion
|
|
||||||
/// \param val Value to insert
|
|
||||||
constexpr void insert(elem_t&& val) {
|
|
||||||
this->_insert(fennec::forward<elem_t>(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Copy Insertion
|
|
||||||
/// \param val Value to insert
|
|
||||||
constexpr void insert(const elem_t& val) {
|
|
||||||
this->_insert(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Emplace Insertion
|
|
||||||
/// \tparam ArgsT Argument types
|
|
||||||
/// \param args Arguments to construct with
|
|
||||||
template<typename...ArgsT>
|
|
||||||
constexpr void emplace(ArgsT&&...args) {
|
|
||||||
this->_insert(fennec::forward<ArgsT>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Element Erase
|
|
||||||
/// \param it Location to erase
|
|
||||||
constexpr void erase(iterator it) {
|
|
||||||
size_t i = it._i;
|
|
||||||
if (i >= capacity()) {
|
|
||||||
return;
|
|
||||||
} // These are separated due to compilers being inconsistent
|
|
||||||
if (not _alloc[i].value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_alloc[i].value = nullopt;
|
|
||||||
_sumpsl -= _alloc[i].psl;
|
|
||||||
--_size;
|
|
||||||
size_t p = i;
|
|
||||||
while (_alloc[i = (i + 1) % capacity()].value) {
|
|
||||||
if (_alloc[i].psl == 0) break;
|
|
||||||
|
|
||||||
fennec::swap(_alloc[i - 1].value, _alloc[i].value);
|
|
||||||
--_alloc[p].psl, --_sumpsl;
|
|
||||||
p = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Element Erase
|
|
||||||
/// \param val Value to erase
|
|
||||||
constexpr void erase(const elem_t& val) {
|
|
||||||
this->erase(this->find(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// ITERATOR ============================================================================================================
|
|
||||||
|
|
||||||
/// \name Iteration
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief C++ Iterator Specification `begin()`
|
|
||||||
/// \returns An iterator for all elements of the set in no particular order
|
|
||||||
constexpr iterator begin() const {
|
|
||||||
iterator it(this, 0);
|
|
||||||
if (not _alloc[it._i].value) {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief C++ Iterator Specification `end()`
|
|
||||||
/// \returns An iterator representing the end of the set
|
|
||||||
constexpr iterator end() const {
|
|
||||||
return iterator(this, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Class for Iterating the Set
|
|
||||||
class iterator {
|
|
||||||
public:
|
|
||||||
constexpr ~iterator() {
|
|
||||||
_set = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefix operator
|
|
||||||
constexpr iterator& operator++() {
|
|
||||||
while (++_i < _set->capacity()) {
|
|
||||||
if (_set->_alloc[_i].value) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_i = npos;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr iterator operator++(int) {
|
|
||||||
iterator prev = *this;
|
|
||||||
this->operator++();
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const elem_t& operator*() const {
|
|
||||||
return *_set->_alloc[_i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const elem_t* operator->() const {
|
|
||||||
if (not _set->_alloc[_i].value) return nullptr;
|
|
||||||
return &*_set->_alloc[_i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator==(const iterator& it) const {
|
|
||||||
return _set == it._set and _i == it._i;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator!=(const iterator& it) const {
|
|
||||||
return _set != it._set or _i != it._i;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const multiset* _set;
|
|
||||||
size_t _i;
|
|
||||||
friend multiset;
|
|
||||||
|
|
||||||
constexpr iterator(const multiset* multiset, size_t i)
|
|
||||||
: _set(multiset)
|
|
||||||
, _i(i) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class value_iterator {
|
|
||||||
public:
|
|
||||||
constexpr ~value_iterator() {
|
|
||||||
_set = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefix operator
|
|
||||||
constexpr value_iterator& operator++() {
|
|
||||||
while (_psl <= _set->_alloc[_i].psl) {
|
|
||||||
if (not _set->_alloc[_i].value) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_i = npos;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr value_iterator operator++(int) {
|
|
||||||
value_iterator prev = *this;
|
|
||||||
this->operator++();
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const elem_t& operator*() const {
|
|
||||||
return *_set->_alloc[_i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const elem_t* operator->() const {
|
|
||||||
if (not _set->_alloc[_i].value) return nullptr;
|
|
||||||
return &*_set->_alloc[_i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator==(const iterator& it) const {
|
|
||||||
return _set == it._set and _i == it._i;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator!=(const iterator& it) const {
|
|
||||||
return _set != it._set or _i != it._i;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const multiset* _set;
|
|
||||||
size_t _i;
|
|
||||||
int _psl;
|
|
||||||
elem_t _value;
|
|
||||||
friend multiset;
|
|
||||||
|
|
||||||
constexpr value_iterator(const multiset* multiset, size_t i, int psl, const elem_t& value)
|
|
||||||
: _set(multiset)
|
|
||||||
, _i(i)
|
|
||||||
, _value(value) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// PRIVATE =============================================================================================================
|
|
||||||
|
|
||||||
private:
|
|
||||||
constexpr void _expand() {
|
|
||||||
multiset cpy; // Create a new multiset
|
|
||||||
cpy._alloc.callocate(
|
|
||||||
fennec::next_prime2(_alloc.capacity())
|
|
||||||
);
|
|
||||||
|
|
||||||
// rehash
|
|
||||||
for (size_t i = 0; i < capacity(); ++i) {
|
|
||||||
if (_alloc[i].value) {
|
|
||||||
cpy.insert(fennec::move(*_alloc[i].value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap buffers
|
|
||||||
fennec::swap(_alloc, cpy._alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename...ArgsT>
|
|
||||||
constexpr void _insert(ArgsT&&...args) {
|
|
||||||
if (_size == 0 or static_cast<float>(_size) / capacity() >= _load) { // expand when full
|
|
||||||
_expand();
|
|
||||||
}
|
|
||||||
|
|
||||||
elem_t value(fennec::forward<ArgsT>(args)...);
|
|
||||||
size_t i = _hash(value) % capacity(); // Initial search index
|
|
||||||
int psl = 0;
|
|
||||||
while (_alloc[i].value) { // Search for empty cell
|
|
||||||
if (_equal(*_alloc[i].value, value)) { // Check to see if this element is already inserted
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (psl > _alloc[i].psl) { // When psl is higher, swap
|
|
||||||
_sumpsl += psl - _alloc[i].psl;
|
|
||||||
fennec::swap(_alloc[i].psl, psl);
|
|
||||||
fennec::swap(*_alloc[i].value, value);
|
|
||||||
}
|
|
||||||
i = (i + 1) % capacity(); ++psl;
|
|
||||||
}
|
|
||||||
_alloc[i].value = fennec::move(value);
|
|
||||||
_sumpsl += (_alloc[i].psl = psl);
|
|
||||||
++_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
allocation<node, alloc_t> _alloc;
|
|
||||||
hash_t _hash;
|
|
||||||
equal_t _equal;
|
|
||||||
size_t _size;
|
|
||||||
size_t _sumpsl;
|
|
||||||
float _load;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FENNEC_CONTAINERS_SET_H
|
|
||||||
@@ -294,9 +294,35 @@ public:
|
|||||||
/// \name Modifiers
|
/// \name Modifiers
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Assignment, Move overload
|
||||||
|
/// \param val The object to take ownership of
|
||||||
|
constexpr T& emplace(T&& val) {
|
||||||
|
if (_set) {
|
||||||
|
_val = fennec::forward<T>(val);
|
||||||
|
} else {
|
||||||
|
fennec::construct(&_val, fennec::forward<T>(val));
|
||||||
|
_set = true;
|
||||||
|
}
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Assignment, Copy overload
|
||||||
|
/// \param val The object to copy
|
||||||
|
constexpr T& emplace(const T& val) {
|
||||||
|
if (_set) {
|
||||||
|
_val = val;
|
||||||
|
} else {
|
||||||
|
fennec::construct(&_val, val);
|
||||||
|
_set = true;
|
||||||
|
}
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Emplace Assignment
|
/// \brief Emplace Assignment
|
||||||
/// \val The optional to move
|
/// \param args The arguments to construct with
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr T& emplace(ArgsT&&...args) {
|
constexpr T& emplace(ArgsT&&...args) {
|
||||||
if (_set) {
|
if (_set) {
|
||||||
|
|||||||
@@ -95,19 +95,33 @@ struct pair {
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Constructor, copies both elements
|
/// \brief Copy Constructor, copies both elements
|
||||||
constexpr pair(const pair&) = default;
|
constexpr pair(const pair& pair)
|
||||||
|
: first(fennec::copy(pair.first))
|
||||||
|
, second(fennec::copy(pair.second)) {
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Constructor, moves both elements
|
/// \brief Move Constructor, moves both elements
|
||||||
constexpr pair(pair&&) noexcept = default;
|
constexpr pair(pair&& pair) noexcept
|
||||||
|
: first(fennec::move(pair.first))
|
||||||
|
, second(fennec::move(pair.second)) {
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Assignment, copies both elements
|
/// \brief Copy Assignment, copies both elements
|
||||||
constexpr pair& operator=(const pair&) = default;
|
constexpr pair& operator=(const pair& pair) {
|
||||||
|
first = fennec::copy(pair.first);
|
||||||
|
second = fennec::copy(pair.second);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Assignment, moves both elements
|
/// \brief Move Assignment, moves both elements
|
||||||
constexpr pair& operator=(pair&&) noexcept = default;
|
constexpr pair& operator=(pair&& pair) {
|
||||||
|
first = fennec::move(pair.first);
|
||||||
|
second = fennec::move(pair.second);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|||||||
@@ -16,22 +16,51 @@
|
|||||||
// 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_PLATFORM_LINUX_XKB_DYN_H
|
///
|
||||||
#define FENNEC_PLATFORM_LINUX_XKB_DYN_H
|
/// \file priority_queue.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#include <fennec/platform/interface/platform.h>
|
#ifndef FENNEC_CONTAINERS_PRIORITY_QUEUE_H
|
||||||
|
#define FENNEC_CONTAINERS_PRIORITY_QUEUE_H
|
||||||
|
|
||||||
|
#include <fennec/containers/object_pool.h>
|
||||||
|
#include <fennec/lang/compare.h>
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
#include <fennec/memory/allocator.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace libxkbcommon
|
template<typename ValueT, class CompareT = less<ValueT>, class AllocT = allocator<ValueT>>
|
||||||
{
|
struct priority_queue {
|
||||||
|
public:
|
||||||
|
using value_t = ValueT;
|
||||||
|
using compare_t = CompareT;
|
||||||
|
using alloc_t = AllocT;
|
||||||
|
|
||||||
bool load_symbols(platform* platform);
|
private:
|
||||||
void unload_symbols(platform* platform);
|
struct node {
|
||||||
|
size_t parent, child;
|
||||||
|
size_t left, right;
|
||||||
|
int degree;
|
||||||
|
value_t key;
|
||||||
|
};
|
||||||
|
|
||||||
|
using table_t = object_pool<node>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
table_t _table;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_LINUX_XKB_DYN_H
|
#endif // FENNEC_CONTAINERS_PRIORITY_QUEUE_H
|
||||||
@@ -58,7 +58,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct node {
|
struct node {
|
||||||
optional<TypeT> value;
|
optional<value_t> value;
|
||||||
size_t parent, child, prev, next;
|
size_t parent, child, prev, next;
|
||||||
size_t depth, num_children;
|
size_t depth, num_children;
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ public:
|
|||||||
/// \param visit The visiting object
|
/// \param visit The visiting object
|
||||||
/// \param i The node to start at
|
/// \param i The node to start at
|
||||||
template<typename OrderT, typename VisitorT>
|
template<typename OrderT, typename VisitorT>
|
||||||
void traverse(VisitorT&& visit, size_t i = root) {
|
constexpr void traverse(VisitorT&& visit, size_t i = root) {
|
||||||
OrderT order;
|
OrderT order;
|
||||||
i = order(*this, i);
|
i = order(*this, i);
|
||||||
while (i != npos) {
|
while (i != npos) {
|
||||||
@@ -429,16 +429,52 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pre_order {
|
struct breadth_first {
|
||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
|
|
||||||
size_t operator()(const rdtree&, size_t start) {
|
constexpr size_t operator()(const rdtree&, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
||||||
|
if (node == npos) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nxt = tree.next(node);
|
||||||
|
size_t chd = tree.next(node);
|
||||||
|
|
||||||
|
if (nxt != npos && node != head) {
|
||||||
|
visit.push_front(nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chd != npos && mode != traversal_control_jump_over) {
|
||||||
|
visit.push_back(chd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not visit.empty()) {
|
||||||
|
node = visit.front();
|
||||||
|
visit.pop_front();
|
||||||
|
} else {
|
||||||
|
node = npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pre_order {
|
||||||
|
list<size_t> visit;
|
||||||
|
size_t head;
|
||||||
|
|
||||||
|
constexpr size_t operator()(const rdtree&, size_t start) {
|
||||||
|
head = start;
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t mode) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
@@ -469,12 +505,12 @@ public:
|
|||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
|
|
||||||
size_t operator()(const rdtree& tree, size_t start) {
|
constexpr size_t operator()(const rdtree& tree, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return tree.left_most(start);
|
return tree.left_most(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
@@ -507,12 +543,12 @@ public:
|
|||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
|
|
||||||
size_t operator()(const rdtree& tree, size_t start) {
|
constexpr size_t operator()(const rdtree& tree, size_t start) {
|
||||||
head = start;
|
head = start;
|
||||||
return tree.left_most(start);
|
return tree.left_most(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
constexpr size_t operator[](const rdtree& tree, size_t node, uint8_t) {
|
||||||
if (node == npos) {
|
if (node == npos) {
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
|
|||||||
455
include/fennec/containers/sequence.h
Normal file
455
include/fennec/containers/sequence.h
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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 sequence.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_SEQUENCE_H
|
||||||
|
#define FENNEC_CONTAINERS_SEQUENCE_H
|
||||||
|
#include <fennec/containers/bintree.h>
|
||||||
|
#include <fennec/containers/bintree.h>
|
||||||
|
#include <fennec/containers/pair.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
|
#include <fennec/lang/compare.h>
|
||||||
|
#include <fennec/memory/allocator.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \brief wrapper for ordered sets of elements, called sequences in mathematics
|
||||||
|
/// \details
|
||||||
|
/// This data-structure behaves like an ordered-set, but does not use pointers, instead storing the table in-array
|
||||||
|
///
|
||||||
|
/// | Property | Value |
|
||||||
|
/// |:----------:|:---------------:|
|
||||||
|
/// | stable | ⛔ |
|
||||||
|
/// | dynamic | ✅ |
|
||||||
|
/// | homogenous | ✅ |
|
||||||
|
/// | distinct | ✅ |
|
||||||
|
/// | ordered | ✅ |
|
||||||
|
/// | space | \f$O(N)\f$ |
|
||||||
|
/// | linear | ✅ |
|
||||||
|
/// | access | \f$O(\log N)\f$ |
|
||||||
|
/// | find | \f$O(\log N)\f$ |
|
||||||
|
/// | insertion | \f$O(\log N)\f$ |
|
||||||
|
/// | deletion | \f$O(\log N)\f$ |
|
||||||
|
///
|
||||||
|
/// \tparam TypeT The type to contain
|
||||||
|
/// \tparam CompareT Function for comparing two values
|
||||||
|
/// \tparam AllocT An allocator class
|
||||||
|
template<typename TypeT, typename CompareT = less<TypeT>, class AllocT = allocator<pair<TypeT, bool>>>
|
||||||
|
struct sequence : protected bintree<pair<TypeT, bool>, AllocT> {
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
protected:
|
||||||
|
struct node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_t = TypeT;
|
||||||
|
using node_t = pair<TypeT, bool>;
|
||||||
|
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
|
||||||
|
using base_t = bintree<pair<TypeT, bool>, AllocT>;
|
||||||
|
using compare_t = CompareT;
|
||||||
|
static constexpr size_t npos = -1;
|
||||||
|
|
||||||
|
enum color_ : bool {
|
||||||
|
black = false,
|
||||||
|
red = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
class iterator;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using typename base_t::in_order;
|
||||||
|
|
||||||
|
using base_t::left;
|
||||||
|
using base_t::right;
|
||||||
|
using base_t::child;
|
||||||
|
using base_t::direction;
|
||||||
|
using base_t::parent;
|
||||||
|
using base_t::grandparent;
|
||||||
|
using base_t::sibling;
|
||||||
|
using base_t::parsib;
|
||||||
|
|
||||||
|
using base_t::left_most;
|
||||||
|
using base_t::right_most;
|
||||||
|
|
||||||
|
using base_t::insert_left;
|
||||||
|
using base_t::insert_right;
|
||||||
|
|
||||||
|
using base_t::rotate;
|
||||||
|
using base_t::rotate_left;
|
||||||
|
using base_t::rotate_right;
|
||||||
|
|
||||||
|
using base_t::_table;
|
||||||
|
using base_t::_freed;
|
||||||
|
using base_t::_root;
|
||||||
|
using base_t::_size;
|
||||||
|
|
||||||
|
// Constructors & Destructors ==========================================================================================
|
||||||
|
public:
|
||||||
|
/// \name Constructors & Destructor
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor, initializes an empty sequence
|
||||||
|
constexpr sequence() = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor, takes ownership of a sequence
|
||||||
|
constexpr sequence(sequence&&) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor, copies a sequence
|
||||||
|
constexpr sequence(const sequence&) = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Destructor, destructs elements *in-order*
|
||||||
|
constexpr ~sequence() {
|
||||||
|
this->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Search ==============================================================================================================
|
||||||
|
public:
|
||||||
|
/// \name Search
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Value Find Function, finds the iterator position for `val`, otherwise returns `end()`
|
||||||
|
/// \param val The value to find
|
||||||
|
/// \returns An iterator at the value
|
||||||
|
constexpr iterator find(const value_t& val) {
|
||||||
|
size_t node = _root;
|
||||||
|
while (node != npos) {
|
||||||
|
if (_compare(val, _value(node))) {
|
||||||
|
node = left(node);
|
||||||
|
} else if (_compare(_value(node), val)) {
|
||||||
|
node = right(node);
|
||||||
|
} else {
|
||||||
|
return sequence::iterator(this, _root, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sequence::iterator(this, _root, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Value Contains Function, checks if the sequence contains a value
|
||||||
|
/// \param val The value to find
|
||||||
|
/// \returns `true` if `val` is in the sequence, `false` otherwise
|
||||||
|
bool contains(const value_t& val) {
|
||||||
|
return find(val) != end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties ==========================================================================================================
|
||||||
|
public:
|
||||||
|
/// \name Properties
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The number of elements in the sequence
|
||||||
|
using base_t::size;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The capacity of the underlying allocation
|
||||||
|
using base_t::capacity;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns `true` when there are no elements in the sequence, `false` otherwise.
|
||||||
|
using base_t::empty;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
public:
|
||||||
|
/// \name Modifiers
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Insertion, moves `val` into the sequence
|
||||||
|
/// \param val The value to insert
|
||||||
|
constexpr void insert(value_t&& val) {
|
||||||
|
size_t i = _insert_bst(fennec::forward<value_t>(val));
|
||||||
|
_fix_insert(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Insertion, inserts a copy of `val` into the sequence
|
||||||
|
/// \param val The value to insert
|
||||||
|
constexpr void insert(const value_t& val) {
|
||||||
|
size_t i = _insert_bst(val);
|
||||||
|
_fix_insert(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplacement, constructs and adds a value into the sequence
|
||||||
|
/// \tparam ArgsT The argument types
|
||||||
|
/// \param args The arguments to construct with
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr void emplace(ArgsT&&...args) {
|
||||||
|
size_t i = _insert_bst(fennec::forward<ArgsT>(args)...);
|
||||||
|
_fix_insert(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void erase(const value_t& val) {
|
||||||
|
_erase_bst(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructs all elements, *in-order*, contained in the sequence
|
||||||
|
constexpr void clear() {
|
||||||
|
in_order order;
|
||||||
|
size_t node = order(*this, _root);
|
||||||
|
while (node != npos) {
|
||||||
|
size_t erase = node;
|
||||||
|
node = order[*this, node, traversal_control_continue];
|
||||||
|
fennec::destruct(&_table[erase]);
|
||||||
|
}
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Iterator ============================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns An iterator at the smallest element in the sequence
|
||||||
|
constexpr sequence::iterator begin() {
|
||||||
|
return sequence::iterator(this, _root, _root);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns An iterator after the largest element in the sequence
|
||||||
|
constexpr sequence::iterator end() {
|
||||||
|
return sequence::iterator(this, _root, npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
class iterator : public base_t::iterator {
|
||||||
|
protected:
|
||||||
|
using base_t::iterator::_n;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
using base_t::iterator::iterator;
|
||||||
|
|
||||||
|
value_t& operator*() {
|
||||||
|
return _table[_n].value.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t& operator*() const {
|
||||||
|
return _table[_n].value.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_t* operator->() {
|
||||||
|
return &_table[_n].value.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_t* operator->() const {
|
||||||
|
return &_table[_n].value.second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Fields ==============================================================================================================
|
||||||
|
protected:
|
||||||
|
compare_t _compare;
|
||||||
|
inline static bool color_sink = red;
|
||||||
|
inline static value_t value_sink;
|
||||||
|
|
||||||
|
// Helpers =============================================================================================================
|
||||||
|
protected:
|
||||||
|
constexpr value_t& _value(size_t i) {
|
||||||
|
return i >= _table.capacity() ? value_sink : _table[i].value.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const value_t& _value(size_t i) const {
|
||||||
|
return i >= _table.capacity() ? value_sink : _table[i].value.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool& _color(size_t i) {
|
||||||
|
return i >= _table.capacity() ? color_sink = false : _table[i].value.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool _color(size_t i) const {
|
||||||
|
return i >= _table.capacity() ? color_sink = false : _table[i].value.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename...ArgsT>
|
||||||
|
constexpr size_t _insert_bst(ArgsT&&...args) {
|
||||||
|
value_t val(fennec::forward<ArgsT>(args)...);
|
||||||
|
|
||||||
|
size_t i = _root;
|
||||||
|
size_t p = npos;
|
||||||
|
while (i != npos) {
|
||||||
|
p = i;
|
||||||
|
|
||||||
|
if (_compare(val, _value(i))) {
|
||||||
|
i = left(i);
|
||||||
|
} else if (_compare(_value(i), val)) {
|
||||||
|
i = right(i);
|
||||||
|
} else {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_root == npos) {
|
||||||
|
return _root = insert_left(npos, node_t(fennec::move(val), red));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_compare(val, _value(p))) {
|
||||||
|
return insert_left(p, node_t(fennec::move(val), red));
|
||||||
|
} else {
|
||||||
|
return insert_right(p, node_t(fennec::move(val), red));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _fix_insert(size_t x) {
|
||||||
|
while (x != _root && _color(parent(x)) == red) {
|
||||||
|
if (_color(parsib(x)) == red) {
|
||||||
|
_color(parent(x)) = black;
|
||||||
|
_color(parsib(x)) = black;
|
||||||
|
_color(grandparent(x)) = red;
|
||||||
|
x = grandparent(x);
|
||||||
|
} else if (parent(x) == left(grandparent(x))) {
|
||||||
|
if (x == right(parent(x))) {
|
||||||
|
x = parent(x);
|
||||||
|
rotate_left(x);
|
||||||
|
}
|
||||||
|
_color(parent(x)) = black;
|
||||||
|
_color(grandparent(x)) = red;
|
||||||
|
rotate_right(grandparent(x));
|
||||||
|
} else {
|
||||||
|
if (x == left(parent(x))) {
|
||||||
|
x = parent(x);
|
||||||
|
rotate_right(x);
|
||||||
|
}
|
||||||
|
_color(parent(x)) = black;
|
||||||
|
_color(grandparent(x)) = red;
|
||||||
|
rotate_left(grandparent(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_color(_root) = black;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _shift(size_t u, size_t v) {
|
||||||
|
if (parent(u) == npos) {
|
||||||
|
_root = v;
|
||||||
|
} else {
|
||||||
|
child(parent(u), direction(u)) = v;
|
||||||
|
}
|
||||||
|
if (v != npos) {
|
||||||
|
parent(v) = parent(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _erase_bst(const value_t& val) {
|
||||||
|
size_t z = find(val).index();
|
||||||
|
size_t y = z;
|
||||||
|
size_t x = npos;
|
||||||
|
bool c = _color(y);
|
||||||
|
size_t p = npos;
|
||||||
|
|
||||||
|
if (left(z) == npos) {
|
||||||
|
x = right(z);
|
||||||
|
p = parent(z);
|
||||||
|
_shift(z, x);
|
||||||
|
} else if (right(z) == npos) {
|
||||||
|
x = left(z);
|
||||||
|
p = parent(z);
|
||||||
|
_shift(z, x);
|
||||||
|
} else {
|
||||||
|
y = left_most(right(z));
|
||||||
|
c = _color(y);
|
||||||
|
x = right(y);
|
||||||
|
p = (parent(y) == z) ? y : parent(y);
|
||||||
|
if (parent(y) != z) {
|
||||||
|
_shift(y, right(y));
|
||||||
|
right(y) = right(z);
|
||||||
|
parent(right(y)) = y;
|
||||||
|
}
|
||||||
|
_shift(z, y);
|
||||||
|
left(y) = left(z);
|
||||||
|
if (left(y))
|
||||||
|
parent(left(y)) = y;
|
||||||
|
_color(y) = _color(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
fennec::destruct(&_table[z]);
|
||||||
|
--_size;
|
||||||
|
|
||||||
|
if (c == black) {
|
||||||
|
_fix_erase(x, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _fix_erase(size_t x, size_t p) {
|
||||||
|
while (x != _root && _color(x) == black) {
|
||||||
|
bool dir = direction(x);
|
||||||
|
size_t w = child(p, not dir);
|
||||||
|
|
||||||
|
if (_color(w) == red) {
|
||||||
|
_color(w) = black;
|
||||||
|
_color(p) = red;
|
||||||
|
w = rotate(p, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w == npos || (_color(left(w)) == black && _color(right(w)) == black)) {
|
||||||
|
_color(w) = red;
|
||||||
|
x = p;
|
||||||
|
p = parent(x);
|
||||||
|
} else {
|
||||||
|
if (_color(child(w, not dir)) == black) {
|
||||||
|
_color(child(w, dir)) = black;
|
||||||
|
_color(w) = red;
|
||||||
|
rotate(w, not dir);
|
||||||
|
w = child(p, not dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
_color(w) = _color(p);
|
||||||
|
_color(p) = black;
|
||||||
|
_color(child(w, not dir)) = black;
|
||||||
|
rotate(p, dir);
|
||||||
|
x = _root;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_color(x) = black;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_SEQUENCE_H
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#define FENNEC_CORE_EVENT_H
|
#define FENNEC_CORE_EVENT_H
|
||||||
|
|
||||||
#include <fennec/lang/types.h>
|
#include <fennec/lang/types.h>
|
||||||
#include <fennec/lang/typeuuid.h>
|
#include <fennec/lang/typed.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|||||||
96
include/fennec/langproc/compile/tokenizer.h
Normal file
96
include/fennec/langproc/compile/tokenizer.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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 tokenizer.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_LANGPROC_FORMAT_TOKENIZER_H
|
||||||
|
#define FENNEC_LANGPROC_FORMAT_TOKENIZER_H
|
||||||
|
|
||||||
|
#include <fennec/containers/list.h>
|
||||||
|
#include <fennec/langproc/strings/string.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// escape sequences are tricky, sometimes they must be separated by white space,
|
||||||
|
// other times they don't. Requiring a list of all possible escape sequences is unrealistic.
|
||||||
|
// We need to allow the user of this struct to specify rules for escape sequences. Here are some basic rules:
|
||||||
|
//
|
||||||
|
// An escape sequence is marked by an escape character, e.g. %, \, {{
|
||||||
|
// Multiple escape characters may be used in a single tokenizer and will have different rules
|
||||||
|
// Escape characters may also be operators, brackets, or quotes
|
||||||
|
// Escape sequences may contain operators, brackets, or quotes
|
||||||
|
//
|
||||||
|
// Here are a few examples of escape sequences from various formats and languages
|
||||||
|
// C: \\, \n, \0, \u200b
|
||||||
|
// PrintF: %s, %2.2f
|
||||||
|
// Python FMT: {{, }}
|
||||||
|
// SPSS: ''
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
struct escape_sequence {
|
||||||
|
virtual size_t operator[](const std::string& str, size_t i) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tokenizer {
|
||||||
|
using escseq = escape_sequence*;
|
||||||
|
using escmap = map<char, escape_sequence*>;
|
||||||
|
|
||||||
|
string delimiter; // markers that separate tokens
|
||||||
|
string operators; // operators are treated as individual tokens
|
||||||
|
string brackets; // characters that mark brackets
|
||||||
|
string quotes; // characters that mark a string sequence, entire string sequence is treated as one token
|
||||||
|
escmap escapes; // characters that mark the start of an escape sequence and validate them
|
||||||
|
|
||||||
|
enum token_ : uint8_t {
|
||||||
|
token_string = 0,
|
||||||
|
token_newline = 1,
|
||||||
|
token_escaped = 2,
|
||||||
|
token_operator = 3,
|
||||||
|
token_bracket = 4,
|
||||||
|
token_quoted = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
using token = pair<string, uint8_t>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
list<token> operator()(const string& line) {
|
||||||
|
list<token> res;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < )
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_LANGPROC_FORMAT_TOKENIZER_H
|
||||||
@@ -250,9 +250,6 @@ public:
|
|||||||
|
|
||||||
// Binary Read Operations ==============================================================================================
|
// Binary Read Operations ==============================================================================================
|
||||||
|
|
||||||
char getc();
|
|
||||||
wchar_t getwc();
|
|
||||||
|
|
||||||
size_t read(void* data, size_t size, size_t n);
|
size_t read(void* data, size_t size, size_t n);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -265,9 +262,6 @@ public:
|
|||||||
return read(static_cast<void*>(data), sizeof(T), n);
|
return read(static_cast<void*>(data), sizeof(T), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
string getline();
|
|
||||||
wstring getwline();
|
|
||||||
|
|
||||||
|
|
||||||
// Binary Write Operations =============================================================================================
|
// Binary Write Operations =============================================================================================
|
||||||
|
|
||||||
@@ -297,6 +291,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read Operations =====================================================================================================
|
||||||
|
|
||||||
|
char getc();
|
||||||
|
wchar_t getwc();
|
||||||
|
|
||||||
|
string getline();
|
||||||
|
wstring getwline();
|
||||||
|
|
||||||
|
|
||||||
// Printing Operations =================================================================================================
|
// Printing Operations =================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ struct cstring
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1;
|
||||||
|
using char_t = char;
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ struct _string
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1;
|
||||||
|
using char_t = char;
|
||||||
using alloc_t = allocation<char, AllocT>;
|
using alloc_t = allocation<char, AllocT>;
|
||||||
|
|
||||||
|
|
||||||
@@ -197,7 +198,7 @@ public:
|
|||||||
if (i >= size()) { // bounds check
|
if (i >= size()) { // bounds check
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
n = fennec::min(n, fennec::max(_str, str.size()) + 1);
|
n = fennec::min(n, fennec::max(size(), str.size()) + 1);
|
||||||
|
|
||||||
return ::strncmp(_str + i, str, n);
|
return ::strncmp(_str + i, str, n);
|
||||||
}
|
}
|
||||||
@@ -216,10 +217,23 @@ public:
|
|||||||
return ::strncmp(_str + i, str.data(), n);
|
return ::strncmp(_str + i, str.data(), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const cstring& str) const {
|
||||||
|
return compare(str) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool operator==(const _string& str) const {
|
constexpr bool operator==(const _string& str) const {
|
||||||
return compare(str) == 0;
|
return compare(str) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if the string contains a character
|
||||||
|
/// \param c
|
||||||
|
/// \param i
|
||||||
|
/// \return
|
||||||
|
constexpr bool contains(char c, size_t i = 0) const {
|
||||||
|
return find(c, i) != size();
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
/// \brief Finds the index of the first occurrence of `c` in the string
|
||||||
/// \param c the character to find
|
/// \param c the character to find
|
||||||
@@ -242,7 +256,7 @@ public:
|
|||||||
return size();
|
return size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* loc = ::strstr(_str, str);
|
const char* loc = ::strstr(_str, str._str);
|
||||||
return loc ? loc - _str : size();
|
return loc ? loc - _str : size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +339,7 @@ public:
|
|||||||
/// \param n the number of characters
|
/// \param n the number of characters
|
||||||
/// \return
|
/// \return
|
||||||
constexpr _string substring(size_t i, size_t n = npos) const {
|
constexpr _string substring(size_t i, size_t n = npos) const {
|
||||||
if (i >= size()) {
|
if (i >= size() || n == 0) {
|
||||||
return _string("");
|
return _string("");
|
||||||
}
|
}
|
||||||
n = fennec::min(n, size() - i);
|
n = fennec::min(n, size() - i);
|
||||||
@@ -420,6 +434,25 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Iteration ===========================================================================================================
|
||||||
|
|
||||||
|
constexpr char* begin() {
|
||||||
|
return _str.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char* begin() const {
|
||||||
|
return _str.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr char* end() {
|
||||||
|
return _str.data() + _str.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char* end() const {
|
||||||
|
return _str.data() + _str.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
alloc_t _str;
|
alloc_t _str;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ struct wcstring
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1;
|
||||||
|
using char_t = wchar_t;
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ struct _wstring
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1;
|
||||||
|
using char_t = wchar_t;
|
||||||
using alloc_t = allocation<wchar_t, AllocT>;
|
using alloc_t = allocation<wchar_t, AllocT>;
|
||||||
|
|
||||||
|
|
||||||
@@ -216,10 +217,23 @@ public:
|
|||||||
return ::wcsncmp(_str + i, str.data(), n);
|
return ::wcsncmp(_str + i, str.data(), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const wcstring& str) const {
|
||||||
|
return compare(str) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool operator==(const _wstring& str) const {
|
constexpr bool operator==(const _wstring& str) const {
|
||||||
return compare(str) == 0;
|
return compare(str) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if the string contains a character
|
||||||
|
/// \param c
|
||||||
|
/// \param i
|
||||||
|
/// \return
|
||||||
|
constexpr bool contains(char c, size_t i = 0) const {
|
||||||
|
return find(c, i) != size();
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
/// \brief Finds the index of the first occurrence of `c` in the string
|
||||||
/// \param c the wchar_tacter to find
|
/// \param c the wchar_tacter to find
|
||||||
|
|||||||
@@ -306,8 +306,8 @@ public:
|
|||||||
|
|
||||||
// Quaternion Quaternion Arithmetic Operators ==========================================================================
|
// Quaternion Quaternion Arithmetic Operators ==========================================================================
|
||||||
|
|
||||||
constexpr friend quaternion operator+(const quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t operator+(const quat_t& lhs, const quat_t& rhs) {
|
||||||
return quaternion(
|
return quat_t(
|
||||||
lhs.w + rhs.w,
|
lhs.w + rhs.w,
|
||||||
lhs.x + rhs.x,
|
lhs.x + rhs.x,
|
||||||
lhs.y + rhs.y,
|
lhs.y + rhs.y,
|
||||||
@@ -315,8 +315,8 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend quaternion operator-(const quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t operator-(const quat_t& lhs, const quat_t& rhs) {
|
||||||
return quaternion(
|
return quat_t(
|
||||||
lhs.w - rhs.w,
|
lhs.w - rhs.w,
|
||||||
lhs.x - rhs.x,
|
lhs.x - rhs.x,
|
||||||
lhs.y - rhs.y,
|
lhs.y - rhs.y,
|
||||||
@@ -324,8 +324,8 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend quaternion operator*(const quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t operator*(const quat_t& lhs, const quat_t& rhs) {
|
||||||
return quaternion(
|
return quat_t(
|
||||||
lhs.w*rhs.w - lhs.x*rhs.x - lhs.y*rhs.y - lhs.z * rhs.z,
|
lhs.w*rhs.w - lhs.x*rhs.x - lhs.y*rhs.y - lhs.z * rhs.z,
|
||||||
lhs.w*rhs.x + lhs.x*rhs.w + lhs.y*rhs.z - lhs.z * rhs.y,
|
lhs.w*rhs.x + lhs.x*rhs.w + lhs.y*rhs.z - lhs.z * rhs.y,
|
||||||
lhs.w*rhs.y - lhs.x*rhs.z + lhs.y*rhs.w + lhs.z * rhs.x,
|
lhs.w*rhs.y - lhs.x*rhs.z + lhs.y*rhs.w + lhs.z * rhs.x,
|
||||||
@@ -336,7 +336,7 @@ public:
|
|||||||
|
|
||||||
// Quaternion Quaternion Arithmetic Assignment Operators ===============================================================
|
// Quaternion Quaternion Arithmetic Assignment Operators ===============================================================
|
||||||
|
|
||||||
constexpr friend quaternion& operator+=(quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t& operator+=(quat_t& lhs, const quat_t& rhs) {
|
||||||
lhs.w += rhs.w;
|
lhs.w += rhs.w;
|
||||||
lhs.x += rhs.x;
|
lhs.x += rhs.x;
|
||||||
lhs.y += rhs.y;
|
lhs.y += rhs.y;
|
||||||
@@ -344,7 +344,7 @@ public:
|
|||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend quaternion& operator-=(quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t& operator-=(quat_t& lhs, const quat_t& rhs) {
|
||||||
lhs.w -= rhs.w;
|
lhs.w -= rhs.w;
|
||||||
lhs.x -= rhs.x;
|
lhs.x -= rhs.x;
|
||||||
lhs.y -= rhs.y;
|
lhs.y -= rhs.y;
|
||||||
@@ -352,7 +352,7 @@ public:
|
|||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr friend quaternion& operator*=(quaternion& lhs, const quaternion& rhs) {
|
constexpr friend quat_t& operator*=(quat_t& lhs, const quat_t& rhs) {
|
||||||
return lhs = lhs * rhs;
|
return lhs = lhs * rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ public:
|
|||||||
/// \details This simply acts as a proxy for allocating memory. It does not call any constructors or
|
/// \details This simply acts as a proxy for allocating memory. It does not call any constructors or
|
||||||
/// initialize any values as if they were the provided data type. Any operations present work
|
/// initialize any values as if they were the provided data type. Any operations present work
|
||||||
/// only on individual bytes.
|
/// only on individual bytes.
|
||||||
template<typename T, class AllocT>
|
template<typename T, class AllocT = allocator<T>>
|
||||||
struct allocation
|
struct allocation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,83 +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_INTERFACE_DISPLAY_H
|
|
||||||
#define FENNEC_PLATFORM_INTERFACE_DISPLAY_H
|
|
||||||
|
|
||||||
#include <fennec/langproc/strings/string.h>
|
|
||||||
#include <fennec/lang/types.h>
|
|
||||||
#include <fennec/lang/typeuuid.h>
|
|
||||||
#include <fennec/platform/interface/fwd.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
class display : public typed<display>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct pixel_format {
|
|
||||||
uint8_t depth;
|
|
||||||
uint8_t r, g, b;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct config {
|
|
||||||
pixel_format format;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual bool connected() const = 0;
|
|
||||||
virtual ~display();
|
|
||||||
|
|
||||||
virtual window* create_window(window* parent) = 0;
|
|
||||||
|
|
||||||
const pixel_format& get_color_format() const {
|
|
||||||
return _config.format;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void select_context();
|
|
||||||
virtual void* get_native_handle() = 0;
|
|
||||||
|
|
||||||
platform* get_platform() { return _platform; }
|
|
||||||
gfxcontext* get_context() { return _context; }
|
|
||||||
|
|
||||||
const string name;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
platform* _platform;
|
|
||||||
gfxcontext* _context;
|
|
||||||
config _config;
|
|
||||||
|
|
||||||
template<typename DisplayT>
|
|
||||||
explicit display(platform* platform, const cstring& name, DisplayT* type)
|
|
||||||
: typed(type)
|
|
||||||
, name(name)
|
|
||||||
, _platform(platform)
|
|
||||||
, _context(nullptr)
|
|
||||||
, _config {
|
|
||||||
.format = {
|
|
||||||
.depth = 24,
|
|
||||||
.r = 8,
|
|
||||||
.g = 8,
|
|
||||||
.b = 8,
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_INTERFACE_DISPLAY_H
|
|
||||||
@@ -22,12 +22,7 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class platform; // Handles OS level functionality
|
|
||||||
class display; // Handles display protocols
|
|
||||||
class window; // Handles window surfaces of the display protocol
|
class window; // Handles window surfaces of the display protocol
|
||||||
class inputdevice; // Handles input devices
|
|
||||||
class gfxcontext; // Handle Driver Contexts, i.e. EGL, WGL, VkWayland, etc.
|
|
||||||
class gfxsurface; // Handle surface targets for windows
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,12 @@
|
|||||||
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
|
||||||
|
|
||||||
#include <fennec/containers/list.h>
|
#include <fennec/containers/list.h>
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
#include <fennec/langproc/strings/cstring.h>
|
#include <fennec/langproc/strings/cstring.h>
|
||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/langproc/strings/string.h>
|
||||||
#include <fennec/lang/typeuuid.h>
|
#include <fennec/lang/typed.h>
|
||||||
#include <fennec/platform/interface/fwd.h>
|
#include <fennec/platform/interface/fwd.h>
|
||||||
|
#include <fennec/platform/interface/window.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This class should resemble the target platform as a whole. By itself, it will represent the OS, i.e. Linux, Windows,
|
* This class should resemble the target platform as a whole. By itself, it will represent the OS, i.e. Linux, Windows,
|
||||||
@@ -64,9 +66,52 @@ public:
|
|||||||
using shared_object = struct shared_object;
|
using shared_object = struct shared_object;
|
||||||
using symbol = void*;
|
using symbol = void*;
|
||||||
|
|
||||||
|
template<typename ctor>
|
||||||
|
struct driver {
|
||||||
|
int priority;
|
||||||
|
ctor constructor;
|
||||||
|
|
||||||
|
driver()
|
||||||
|
: priority(0)
|
||||||
|
, constructor(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
driver(int priority, ctor constructor)
|
||||||
|
: priority(priority)
|
||||||
|
, constructor(constructor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
driver(const driver& d)
|
||||||
|
: priority(d.priority)
|
||||||
|
, constructor(d.constructor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
driver(driver&& d) noexcept
|
||||||
|
: priority(d.priority)
|
||||||
|
, constructor(d.constructor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
driver& operator=(const driver& d) {
|
||||||
|
priority = d.priority;
|
||||||
|
constructor = d.constructor;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver& operator=(driver&& d) noexcept {
|
||||||
|
priority = fennec::move(d.priority);
|
||||||
|
constructor = fennec::move(d.constructor);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const driver& d) const {
|
||||||
|
return priority > d.priority;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const string name;
|
const string name;
|
||||||
|
|
||||||
virtual ~platform() = default;
|
virtual ~platform() = default;
|
||||||
|
platform(const platform&) = delete;
|
||||||
|
|
||||||
// Dynamically linked objects
|
// Dynamically linked objects
|
||||||
virtual shared_object* load_object(const cstring& file) = 0;
|
virtual shared_object* load_object(const cstring& file) = 0;
|
||||||
@@ -76,64 +121,40 @@ public:
|
|||||||
virtual void initialize(); // Initialize Drivers and Contexts
|
virtual void initialize(); // Initialize Drivers and Contexts
|
||||||
virtual void shutdown(); // Close Drivers and Contexts
|
virtual void shutdown(); // Close Drivers and Contexts
|
||||||
|
|
||||||
display* get_display() { return _display; }
|
// Platform level functions for retrieving driver and protocol contexts ================================================
|
||||||
|
|
||||||
|
// Window Management
|
||||||
|
using window_ctor = window* (*)(platform*, const window::config&);
|
||||||
|
using window_driver = driver<window_ctor>;
|
||||||
|
window* create_window(const window::config& config);
|
||||||
|
static void register_window_driver(window_driver&& driver);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename PlatformT>
|
template<typename PlatformT>
|
||||||
explicit platform(const cstring& name, PlatformT* type)
|
explicit platform(const cstring& name, PlatformT* type)
|
||||||
: typed(type)
|
: typed(type)
|
||||||
, name(name) {
|
, name(name) {
|
||||||
auto& globals = _get_globals();
|
assertf(globals.singleton == nullptr, "Conflicting platform implementations!");
|
||||||
assertf(globals.singleton == nullptr, "Conflicting Platform Definitions.");
|
|
||||||
globals.singleton = this;
|
globals.singleton = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void load_display();
|
|
||||||
|
|
||||||
display* _display;
|
|
||||||
|
|
||||||
private:
|
|
||||||
platform(const platform&) = delete;
|
|
||||||
|
|
||||||
// Static Stuff ========================================================================================================
|
// Static Stuff ========================================================================================================
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using display_ctor = display* (*)(platform*);
|
static platform* instance() {
|
||||||
using input_ctor = inputdevice* (*)(display*);
|
return globals.singleton;
|
||||||
using gfxctx_ctor = gfxcontext* (*)(display*);
|
|
||||||
|
|
||||||
template<typename ctor>
|
|
||||||
struct driver {
|
|
||||||
int priority;
|
|
||||||
ctor constructor;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct global_context {
|
|
||||||
platform* singleton;
|
|
||||||
list<driver<display_ctor>> displays;
|
|
||||||
list<driver<input_ctor>> inputs;
|
|
||||||
list<driver<gfxctx_ctor>> graphics;
|
|
||||||
|
|
||||||
global_context()
|
|
||||||
: singleton(nullptr) {
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
static void add_driver(display_ctor ctor, int priority);
|
|
||||||
static void add_driver(input_ctor ctor, int priority);
|
|
||||||
static void add_driver(gfxctx_ctor ctor, int priority);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static global_context& _get_globals();
|
inline static struct global {
|
||||||
|
platform* singleton;
|
||||||
|
sequence<window_driver> windows;
|
||||||
|
|
||||||
public:
|
global()
|
||||||
static const global_context& get_globals() {
|
: singleton(nullptr)
|
||||||
return _get_globals();
|
, windows() {
|
||||||
}
|
|
||||||
|
|
||||||
static platform* instance() {
|
|
||||||
return _get_globals().singleton;
|
|
||||||
}
|
}
|
||||||
|
} globals = global();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,150 +16,135 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// 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_INTERFACE_WINDOW_H
|
#ifndef FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
||||||
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
|
||||||
|
|
||||||
#include <fennec/containers/optional.h>
|
#include <fennec/lang/types.h>
|
||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/langproc/strings/string.h>
|
||||||
#include <fennec/platform/interface/fwd.h>
|
#include <fennec/renderers/interface/gfxcontext.h>
|
||||||
#include <fennec/platform/linux/wayland/display.h>
|
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
///
|
class window {
|
||||||
/// \brief interface for handling windows
|
|
||||||
/// \details the interface makes no guarantees about the bit-depth and is completely dependent on the implementation.
|
|
||||||
class window : public typed<window> {
|
|
||||||
public:
|
public:
|
||||||
enum class fullscreen_mode {
|
virtual ~window() = default;
|
||||||
windowed = 0,
|
|
||||||
borderless,
|
enum flags : uint8_t {
|
||||||
fullscreen
|
fullscreen = 0x1 << 0,
|
||||||
|
borderless = 0x1 << 1,
|
||||||
|
resizeable = 0x1 << 2,
|
||||||
|
modal = 0x1 << 3, // Treat as modal, blocks interaction with parent windows
|
||||||
|
popup = 0x1 << 4, // Treat as a popup menu
|
||||||
|
tooltip = 0x1 << 5, // Treat as a tooltip, does not receive mouse or keyboard focus
|
||||||
|
utility = 0x1 << 6, // Treat as utility, does not show in taskbar
|
||||||
};
|
};
|
||||||
|
|
||||||
enum flags_ : uint32_t {
|
enum vsync {
|
||||||
flags_none = 0,
|
vsync_off = 0,
|
||||||
flags_child = 0x1 << 0,
|
vsync_on = 1,
|
||||||
flags_modal = 0x1 << 1,
|
adaptive_sync = -1,
|
||||||
flags_grab_mouse = 0x1 << 2,
|
};
|
||||||
flags_grab_keyboard = 0x1 << 3,
|
|
||||||
flags_block_screensaver = 0x1 << 4,
|
struct pixel_format {
|
||||||
|
uint8_t r, g, b, a;
|
||||||
|
bool floating_point;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct display_mode {
|
||||||
|
pixel_format format;
|
||||||
|
float rate;
|
||||||
|
float density;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct config {
|
struct config {
|
||||||
|
uint8_t flags;
|
||||||
|
display_mode mode;
|
||||||
string title;
|
string title;
|
||||||
uint32_t flags;
|
int8_t vsync;
|
||||||
size_t width, height;
|
|
||||||
fullscreen_mode fullscreen;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~window() = default;
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
virtual bool running() = 0;
|
virtual bool running() = 0;
|
||||||
virtual void configure(const config& config) = 0;
|
|
||||||
virtual bool initialize(bool modal) = 0;
|
|
||||||
virtual bool shutdown() = 0;
|
|
||||||
|
|
||||||
virtual bool set_title(const cstring& title) = 0;
|
bool is_fullscreen() const {
|
||||||
virtual bool set_title(const string& title) = 0;
|
return _config.flags & fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool set_width(size_t w) = 0;
|
bool is_borderless() const {
|
||||||
virtual bool set_height(size_t h) = 0;
|
return _config.flags & borderless;
|
||||||
virtual bool resize(size_t w, size_t h) = 0;
|
|
||||||
|
|
||||||
virtual bool set_fullscreen_mode(fullscreen_mode mode) = 0;
|
|
||||||
|
|
||||||
virtual bool set_resizable(bool e) = 0;
|
|
||||||
|
|
||||||
virtual bool grab_keyboard(bool e) = 0;
|
|
||||||
virtual bool grab_mouse(bool e) = 0;
|
|
||||||
virtual bool block_screensaver(bool e) = 0;
|
|
||||||
|
|
||||||
virtual struct wl_surface* get_native_handle() = 0;
|
|
||||||
|
|
||||||
bool is_child() const {
|
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_child;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_modal() const {
|
bool is_modal() const {
|
||||||
if (not _config) return false;
|
return _config.flags & modal;
|
||||||
return _config->flags & flags_modal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
display* get_display() {
|
bool is_resizeable() const {
|
||||||
return _display;
|
return _config.flags & resizeable;
|
||||||
}
|
}
|
||||||
|
|
||||||
const display* get_display() const {
|
const display_mode& get_mode() const {
|
||||||
return _display;
|
return _config.mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pixel_format& get_format() const {
|
||||||
|
return _config.mode.format;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_hdr() const {
|
||||||
|
static constexpr size_t sdr = 255ull * 255ull * 255ull;
|
||||||
|
const pixel_format& fmt = _config.mode.format;
|
||||||
|
return fmt.r * fmt.g * fmt.b > sdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const config& get_config() const {
|
const config& get_config() const {
|
||||||
return *_config;
|
return _config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
const string& get_title() const {
|
virtual void resize(size_t, size_t) = 0;
|
||||||
static const string _null{"null"};
|
virtual void position(size_t, size_t) = 0;
|
||||||
if (not _config) return _null;
|
|
||||||
return _config->title;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
virtual void set_fullscreen(bool) = 0;
|
||||||
|
virtual void set_borderless(bool) = 0;
|
||||||
|
|
||||||
size_t get_width() const {
|
virtual void grab_mouse(bool) = 0;
|
||||||
if (not _config) return false;
|
virtual void grab_keyboard(bool) = 0;
|
||||||
return _config->width;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t get_height() const {
|
virtual void set_title(const cstring&) = 0;
|
||||||
if (not _config) return false;
|
virtual void set_title(const string&) = 0;
|
||||||
return _config->height;
|
virtual void set_progress(bool, float) = 0;
|
||||||
}
|
|
||||||
|
|
||||||
|
virtual void vsync(int8_t) = 0;
|
||||||
|
|
||||||
fullscreen_mode get_fullscreen_mode() const {
|
// Graphics ============================================================================================================
|
||||||
if (not _config) return fullscreen_mode::windowed;
|
|
||||||
return _config->fullscreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
virtual void begin_frame() = 0;
|
||||||
bool is_keyboard_grabbed() const {
|
virtual void end_frame() = 0;
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_grab_keyboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_mouse_grabbed() const {
|
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_grab_mouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_screensaver_blocked() const {
|
|
||||||
if (not _config) return false;
|
|
||||||
return _config->flags & flags_block_screensaver;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class DisplayT>
|
|
||||||
DisplayT* get_display() {
|
|
||||||
return static_cast<DisplayT*>(_display);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename TypeT>
|
|
||||||
window(display* display, window* parent, TypeT* type)
|
|
||||||
: typed(type)
|
|
||||||
, _display(display)
|
|
||||||
, _parent(parent)
|
|
||||||
, _surface(nullptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
display* _display;
|
|
||||||
window* _parent;
|
window* _parent;
|
||||||
optional<config> _config;
|
gfxcontext* _context;
|
||||||
gfxsurface* _surface;
|
config _config;
|
||||||
|
|
||||||
private:
|
window(window* parent, const config& cfg)
|
||||||
|
: _parent(parent)
|
||||||
|
, _config(cfg) {
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,71 +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_DISPLAY_H
|
|
||||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H
|
|
||||||
|
|
||||||
#include <fennec/platform/interface/display.h>
|
|
||||||
#include <fennec/platform/linux/wayland/lib/wayland.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
class wayland_display : public display {
|
|
||||||
public:
|
|
||||||
explicit wayland_display(platform* platform);
|
|
||||||
~wayland_display() override;
|
|
||||||
|
|
||||||
bool connected() const override;
|
|
||||||
void* get_native_handle() override { return _handle; }
|
|
||||||
|
|
||||||
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:
|
|
||||||
wl_display* _handle;
|
|
||||||
wl_registry* _registry;
|
|
||||||
wl_compositor* _compositor;
|
|
||||||
//xdg_wm_base* _shell;
|
|
||||||
wl_seat* _seat;
|
|
||||||
wl_shm* _shm;
|
|
||||||
bool _fifo;
|
|
||||||
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
static void listen_global(void*, wl_registry*, uint32_t, const char*, uint32_t);
|
|
||||||
static void listen_global_remove(void*, wl_registry*, uint32_t);
|
|
||||||
static void listen_seat(void*, wl_seat*, uint32_t);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,526 +0,0 @@
|
|||||||
/* Generated by wayland-scanner 1.23.1 */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2008-2011 Kristian Høgsberg
|
|
||||||
* Copyright © 2010-2011 Intel Corporation
|
|
||||||
* Copyright © 2012-2013 Collabora, Ltd.
|
|
||||||
*
|
|
||||||
* 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 <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "wayland-util.h"
|
|
||||||
|
|
||||||
#ifndef __has_attribute
|
|
||||||
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
|
|
||||||
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
|
|
||||||
#else
|
|
||||||
#define WL_PRIVATE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern const struct wl_interface wl_buffer_interface;
|
|
||||||
extern const struct wl_interface wl_callback_interface;
|
|
||||||
extern const struct wl_interface wl_data_device_interface;
|
|
||||||
extern const struct wl_interface wl_data_offer_interface;
|
|
||||||
extern const struct wl_interface wl_data_source_interface;
|
|
||||||
extern const struct wl_interface wl_keyboard_interface;
|
|
||||||
extern const struct wl_interface wl_output_interface;
|
|
||||||
extern const struct wl_interface wl_pointer_interface;
|
|
||||||
extern const struct wl_interface wl_region_interface;
|
|
||||||
extern const struct wl_interface wl_registry_interface;
|
|
||||||
extern const struct wl_interface wl_seat_interface;
|
|
||||||
extern const struct wl_interface wl_shell_surface_interface;
|
|
||||||
extern const struct wl_interface wl_shm_pool_interface;
|
|
||||||
extern const struct wl_interface wl_subsurface_interface;
|
|
||||||
extern const struct wl_interface wl_surface_interface;
|
|
||||||
extern const struct wl_interface wl_touch_interface;
|
|
||||||
|
|
||||||
static const struct wl_interface *wayland_types[] = {
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_callback_interface,
|
|
||||||
&wl_registry_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
&wl_region_interface,
|
|
||||||
&wl_buffer_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_shm_pool_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_data_source_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
&wl_data_source_interface,
|
|
||||||
NULL,
|
|
||||||
&wl_data_offer_interface,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_data_offer_interface,
|
|
||||||
&wl_data_offer_interface,
|
|
||||||
&wl_data_source_interface,
|
|
||||||
&wl_data_device_interface,
|
|
||||||
&wl_seat_interface,
|
|
||||||
&wl_shell_surface_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
&wl_seat_interface,
|
|
||||||
NULL,
|
|
||||||
&wl_seat_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_output_interface,
|
|
||||||
&wl_seat_interface,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_output_interface,
|
|
||||||
&wl_buffer_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_callback_interface,
|
|
||||||
&wl_region_interface,
|
|
||||||
&wl_region_interface,
|
|
||||||
&wl_output_interface,
|
|
||||||
&wl_output_interface,
|
|
||||||
&wl_pointer_interface,
|
|
||||||
&wl_keyboard_interface,
|
|
||||||
&wl_touch_interface,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_surface_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_subsurface_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_display_requests[] = {
|
|
||||||
{ "sync", "n", wayland_types + 8 },
|
|
||||||
{ "get_registry", "n", wayland_types + 9 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_display_events[] = {
|
|
||||||
{ "error", "ous", wayland_types + 0 },
|
|
||||||
{ "delete_id", "u", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_display_interface = {
|
|
||||||
"wl_display", 1,
|
|
||||||
2, wl_display_requests,
|
|
||||||
2, wl_display_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_registry_requests[] = {
|
|
||||||
{ "bind", "usun", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_registry_events[] = {
|
|
||||||
{ "global", "usu", wayland_types + 0 },
|
|
||||||
{ "global_remove", "u", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_registry_interface = {
|
|
||||||
"wl_registry", 1,
|
|
||||||
1, wl_registry_requests,
|
|
||||||
2, wl_registry_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_callback_events[] = {
|
|
||||||
{ "done", "u", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_callback_interface = {
|
|
||||||
"wl_callback", 1,
|
|
||||||
0, NULL,
|
|
||||||
1, wl_callback_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_compositor_requests[] = {
|
|
||||||
{ "create_surface", "n", wayland_types + 10 },
|
|
||||||
{ "create_region", "n", wayland_types + 11 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_compositor_interface = {
|
|
||||||
"wl_compositor", 6,
|
|
||||||
2, wl_compositor_requests,
|
|
||||||
0, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_shm_pool_requests[] = {
|
|
||||||
{ "create_buffer", "niiiiu", wayland_types + 12 },
|
|
||||||
{ "destroy", "", wayland_types + 0 },
|
|
||||||
{ "resize", "i", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_shm_pool_interface = {
|
|
||||||
"wl_shm_pool", 2,
|
|
||||||
3, wl_shm_pool_requests,
|
|
||||||
0, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_shm_requests[] = {
|
|
||||||
{ "create_pool", "nhi", wayland_types + 18 },
|
|
||||||
{ "release", "2", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_shm_events[] = {
|
|
||||||
{ "format", "u", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_shm_interface = {
|
|
||||||
"wl_shm", 2,
|
|
||||||
2, wl_shm_requests,
|
|
||||||
1, wl_shm_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_buffer_requests[] = {
|
|
||||||
{ "destroy", "", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_buffer_events[] = {
|
|
||||||
{ "release", "", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_buffer_interface = {
|
|
||||||
"wl_buffer", 1,
|
|
||||||
1, wl_buffer_requests,
|
|
||||||
1, wl_buffer_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_data_offer_requests[] = {
|
|
||||||
{ "accept", "u?s", wayland_types + 0 },
|
|
||||||
{ "receive", "sh", wayland_types + 0 },
|
|
||||||
{ "destroy", "", wayland_types + 0 },
|
|
||||||
{ "finish", "3", wayland_types + 0 },
|
|
||||||
{ "set_actions", "3uu", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_data_offer_events[] = {
|
|
||||||
{ "offer", "s", wayland_types + 0 },
|
|
||||||
{ "source_actions", "3u", wayland_types + 0 },
|
|
||||||
{ "action", "3u", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_data_offer_interface = {
|
|
||||||
"wl_data_offer", 3,
|
|
||||||
5, wl_data_offer_requests,
|
|
||||||
3, wl_data_offer_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_data_source_requests[] = {
|
|
||||||
{ "offer", "s", wayland_types + 0 },
|
|
||||||
{ "destroy", "", wayland_types + 0 },
|
|
||||||
{ "set_actions", "3u", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_data_source_events[] = {
|
|
||||||
{ "target", "?s", wayland_types + 0 },
|
|
||||||
{ "send", "sh", wayland_types + 0 },
|
|
||||||
{ "cancelled", "", wayland_types + 0 },
|
|
||||||
{ "dnd_drop_performed", "3", wayland_types + 0 },
|
|
||||||
{ "dnd_finished", "3", wayland_types + 0 },
|
|
||||||
{ "action", "3u", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_data_source_interface = {
|
|
||||||
"wl_data_source", 3,
|
|
||||||
3, wl_data_source_requests,
|
|
||||||
6, wl_data_source_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_data_device_requests[] = {
|
|
||||||
{ "start_drag", "?oo?ou", wayland_types + 21 },
|
|
||||||
{ "set_selection", "?ou", wayland_types + 25 },
|
|
||||||
{ "release", "2", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_data_device_events[] = {
|
|
||||||
{ "data_offer", "n", wayland_types + 27 },
|
|
||||||
{ "enter", "uoff?o", wayland_types + 28 },
|
|
||||||
{ "leave", "", wayland_types + 0 },
|
|
||||||
{ "motion", "uff", wayland_types + 0 },
|
|
||||||
{ "drop", "", wayland_types + 0 },
|
|
||||||
{ "selection", "?o", wayland_types + 33 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_data_device_interface = {
|
|
||||||
"wl_data_device", 3,
|
|
||||||
3, wl_data_device_requests,
|
|
||||||
6, wl_data_device_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_data_device_manager_requests[] = {
|
|
||||||
{ "create_data_source", "n", wayland_types + 34 },
|
|
||||||
{ "get_data_device", "no", wayland_types + 35 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_data_device_manager_interface = {
|
|
||||||
"wl_data_device_manager", 3,
|
|
||||||
2, wl_data_device_manager_requests,
|
|
||||||
0, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_shell_requests[] = {
|
|
||||||
{ "get_shell_surface", "no", wayland_types + 37 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_shell_interface = {
|
|
||||||
"wl_shell", 1,
|
|
||||||
1, wl_shell_requests,
|
|
||||||
0, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_shell_surface_requests[] = {
|
|
||||||
{ "pong", "u", wayland_types + 0 },
|
|
||||||
{ "move", "ou", wayland_types + 39 },
|
|
||||||
{ "resize", "ouu", wayland_types + 41 },
|
|
||||||
{ "set_toplevel", "", wayland_types + 0 },
|
|
||||||
{ "set_transient", "oiiu", wayland_types + 44 },
|
|
||||||
{ "set_fullscreen", "uu?o", wayland_types + 48 },
|
|
||||||
{ "set_popup", "ouoiiu", wayland_types + 51 },
|
|
||||||
{ "set_maximized", "?o", wayland_types + 57 },
|
|
||||||
{ "set_title", "s", wayland_types + 0 },
|
|
||||||
{ "set_class", "s", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_shell_surface_events[] = {
|
|
||||||
{ "ping", "u", wayland_types + 0 },
|
|
||||||
{ "configure", "uii", wayland_types + 0 },
|
|
||||||
{ "popup_done", "", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_shell_surface_interface = {
|
|
||||||
"wl_shell_surface", 1,
|
|
||||||
10, wl_shell_surface_requests,
|
|
||||||
3, wl_shell_surface_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_surface_requests[] = {
|
|
||||||
{ "destroy", "", wayland_types + 0 },
|
|
||||||
{ "attach", "?oii", wayland_types + 58 },
|
|
||||||
{ "damage", "iiii", wayland_types + 0 },
|
|
||||||
{ "frame", "n", wayland_types + 61 },
|
|
||||||
{ "set_opaque_region", "?o", wayland_types + 62 },
|
|
||||||
{ "set_input_region", "?o", wayland_types + 63 },
|
|
||||||
{ "commit", "", wayland_types + 0 },
|
|
||||||
{ "set_buffer_transform", "2i", wayland_types + 0 },
|
|
||||||
{ "set_buffer_scale", "3i", wayland_types + 0 },
|
|
||||||
{ "damage_buffer", "4iiii", wayland_types + 0 },
|
|
||||||
{ "offset", "5ii", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_surface_events[] = {
|
|
||||||
{ "enter", "o", wayland_types + 64 },
|
|
||||||
{ "leave", "o", wayland_types + 65 },
|
|
||||||
{ "preferred_buffer_scale", "6i", wayland_types + 0 },
|
|
||||||
{ "preferred_buffer_transform", "6u", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_surface_interface = {
|
|
||||||
"wl_surface", 6,
|
|
||||||
11, wl_surface_requests,
|
|
||||||
4, wl_surface_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_seat_requests[] = {
|
|
||||||
{ "get_pointer", "n", wayland_types + 66 },
|
|
||||||
{ "get_keyboard", "n", wayland_types + 67 },
|
|
||||||
{ "get_touch", "n", wayland_types + 68 },
|
|
||||||
{ "release", "5", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_seat_events[] = {
|
|
||||||
{ "capabilities", "u", wayland_types + 0 },
|
|
||||||
{ "name", "2s", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_seat_interface = {
|
|
||||||
"wl_seat", 9,
|
|
||||||
4, wl_seat_requests,
|
|
||||||
2, wl_seat_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_pointer_requests[] = {
|
|
||||||
{ "set_cursor", "u?oii", wayland_types + 69 },
|
|
||||||
{ "release", "3", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_pointer_events[] = {
|
|
||||||
{ "enter", "uoff", wayland_types + 73 },
|
|
||||||
{ "leave", "uo", wayland_types + 77 },
|
|
||||||
{ "motion", "uff", wayland_types + 0 },
|
|
||||||
{ "button", "uuuu", wayland_types + 0 },
|
|
||||||
{ "axis", "uuf", wayland_types + 0 },
|
|
||||||
{ "frame", "5", wayland_types + 0 },
|
|
||||||
{ "axis_source", "5u", wayland_types + 0 },
|
|
||||||
{ "axis_stop", "5uu", wayland_types + 0 },
|
|
||||||
{ "axis_discrete", "5ui", wayland_types + 0 },
|
|
||||||
{ "axis_value120", "8ui", wayland_types + 0 },
|
|
||||||
{ "axis_relative_direction", "9uu", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_pointer_interface = {
|
|
||||||
"wl_pointer", 9,
|
|
||||||
2, wl_pointer_requests,
|
|
||||||
11, wl_pointer_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_keyboard_requests[] = {
|
|
||||||
{ "release", "3", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_keyboard_events[] = {
|
|
||||||
{ "keymap", "uhu", wayland_types + 0 },
|
|
||||||
{ "enter", "uoa", wayland_types + 79 },
|
|
||||||
{ "leave", "uo", wayland_types + 82 },
|
|
||||||
{ "key", "uuuu", wayland_types + 0 },
|
|
||||||
{ "modifiers", "uuuuu", wayland_types + 0 },
|
|
||||||
{ "repeat_info", "4ii", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_keyboard_interface = {
|
|
||||||
"wl_keyboard", 9,
|
|
||||||
1, wl_keyboard_requests,
|
|
||||||
6, wl_keyboard_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_touch_requests[] = {
|
|
||||||
{ "release", "3", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_touch_events[] = {
|
|
||||||
{ "down", "uuoiff", wayland_types + 84 },
|
|
||||||
{ "up", "uui", wayland_types + 0 },
|
|
||||||
{ "motion", "uiff", wayland_types + 0 },
|
|
||||||
{ "frame", "", wayland_types + 0 },
|
|
||||||
{ "cancel", "", wayland_types + 0 },
|
|
||||||
{ "shape", "6iff", wayland_types + 0 },
|
|
||||||
{ "orientation", "6if", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_touch_interface = {
|
|
||||||
"wl_touch", 9,
|
|
||||||
1, wl_touch_requests,
|
|
||||||
7, wl_touch_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_output_requests[] = {
|
|
||||||
{ "release", "3", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_output_events[] = {
|
|
||||||
{ "geometry", "iiiiissi", wayland_types + 0 },
|
|
||||||
{ "mode", "uiii", wayland_types + 0 },
|
|
||||||
{ "done", "2", wayland_types + 0 },
|
|
||||||
{ "scale", "2i", wayland_types + 0 },
|
|
||||||
{ "name", "4s", wayland_types + 0 },
|
|
||||||
{ "description", "4s", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_output_interface = {
|
|
||||||
"wl_output", 4,
|
|
||||||
1, wl_output_requests,
|
|
||||||
6, wl_output_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_region_requests[] = {
|
|
||||||
{ "destroy", "", wayland_types + 0 },
|
|
||||||
{ "add", "iiii", wayland_types + 0 },
|
|
||||||
{ "subtract", "iiii", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_region_interface = {
|
|
||||||
"wl_region", 1,
|
|
||||||
3, wl_region_requests,
|
|
||||||
0, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_subcompositor_requests[] = {
|
|
||||||
{ "destroy", "", wayland_types + 0 },
|
|
||||||
{ "get_subsurface", "noo", wayland_types + 90 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_subcompositor_interface = {
|
|
||||||
"wl_subcompositor", 1,
|
|
||||||
2, wl_subcompositor_requests,
|
|
||||||
0, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message wl_subsurface_requests[] = {
|
|
||||||
{ "destroy", "", wayland_types + 0 },
|
|
||||||
{ "set_position", "ii", wayland_types + 0 },
|
|
||||||
{ "place_above", "o", wayland_types + 93 },
|
|
||||||
{ "place_below", "o", wayland_types + 94 },
|
|
||||||
{ "set_sync", "", wayland_types + 0 },
|
|
||||||
{ "set_desync", "", wayland_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface wl_subsurface_interface = {
|
|
||||||
"wl_subsurface", 1,
|
|
||||||
6, wl_subsurface_requests,
|
|
||||||
0, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
/* Generated by wayland-scanner 1.23.1 */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2008-2013 Kristian Høgsberg
|
|
||||||
* Copyright © 2013 Rafael Antognolli
|
|
||||||
* Copyright © 2013 Jasper St. Pierre
|
|
||||||
* Copyright © 2010-2013 Intel Corporation
|
|
||||||
* Copyright © 2015-2017 Samsung Electronics Co., Ltd
|
|
||||||
* Copyright © 2015-2017 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* 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 <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "wayland-util.h"
|
|
||||||
|
|
||||||
#ifndef __has_attribute
|
|
||||||
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
|
|
||||||
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
|
|
||||||
#else
|
|
||||||
#define WL_PRIVATE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern const struct wl_interface wl_output_interface;
|
|
||||||
extern const struct wl_interface wl_seat_interface;
|
|
||||||
extern const struct wl_interface wl_surface_interface;
|
|
||||||
extern const struct wl_interface xdg_popup_interface;
|
|
||||||
extern const struct wl_interface xdg_positioner_interface;
|
|
||||||
extern const struct wl_interface xdg_surface_interface;
|
|
||||||
extern const struct wl_interface xdg_toplevel_interface;
|
|
||||||
|
|
||||||
static const struct wl_interface *xdg_shell_types[] = {
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&xdg_positioner_interface,
|
|
||||||
&xdg_surface_interface,
|
|
||||||
&wl_surface_interface,
|
|
||||||
&xdg_toplevel_interface,
|
|
||||||
&xdg_popup_interface,
|
|
||||||
&xdg_surface_interface,
|
|
||||||
&xdg_positioner_interface,
|
|
||||||
&xdg_toplevel_interface,
|
|
||||||
&wl_seat_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_seat_interface,
|
|
||||||
NULL,
|
|
||||||
&wl_seat_interface,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&wl_output_interface,
|
|
||||||
&wl_seat_interface,
|
|
||||||
NULL,
|
|
||||||
&xdg_positioner_interface,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_wm_base_requests[] = {
|
|
||||||
{ "destroy", "", xdg_shell_types + 0 },
|
|
||||||
{ "create_positioner", "n", xdg_shell_types + 4 },
|
|
||||||
{ "get_xdg_surface", "no", xdg_shell_types + 5 },
|
|
||||||
{ "pong", "u", xdg_shell_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_wm_base_events[] = {
|
|
||||||
{ "ping", "u", xdg_shell_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface xdg_wm_base_interface = {
|
|
||||||
"xdg_wm_base", 6,
|
|
||||||
4, xdg_wm_base_requests,
|
|
||||||
1, xdg_wm_base_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_positioner_requests[] = {
|
|
||||||
{ "destroy", "", xdg_shell_types + 0 },
|
|
||||||
{ "set_size", "ii", xdg_shell_types + 0 },
|
|
||||||
{ "set_anchor_rect", "iiii", xdg_shell_types + 0 },
|
|
||||||
{ "set_anchor", "u", xdg_shell_types + 0 },
|
|
||||||
{ "set_gravity", "u", xdg_shell_types + 0 },
|
|
||||||
{ "set_constraint_adjustment", "u", xdg_shell_types + 0 },
|
|
||||||
{ "set_offset", "ii", xdg_shell_types + 0 },
|
|
||||||
{ "set_reactive", "3", xdg_shell_types + 0 },
|
|
||||||
{ "set_parent_size", "3ii", xdg_shell_types + 0 },
|
|
||||||
{ "set_parent_configure", "3u", xdg_shell_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface xdg_positioner_interface = {
|
|
||||||
"xdg_positioner", 6,
|
|
||||||
10, xdg_positioner_requests,
|
|
||||||
0, NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_surface_requests[] = {
|
|
||||||
{ "destroy", "", xdg_shell_types + 0 },
|
|
||||||
{ "get_toplevel", "n", xdg_shell_types + 7 },
|
|
||||||
{ "get_popup", "n?oo", xdg_shell_types + 8 },
|
|
||||||
{ "set_window_geometry", "iiii", xdg_shell_types + 0 },
|
|
||||||
{ "ack_configure", "u", xdg_shell_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_surface_events[] = {
|
|
||||||
{ "configure", "u", xdg_shell_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface xdg_surface_interface = {
|
|
||||||
"xdg_surface", 6,
|
|
||||||
5, xdg_surface_requests,
|
|
||||||
1, xdg_surface_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_toplevel_requests[] = {
|
|
||||||
{ "destroy", "", xdg_shell_types + 0 },
|
|
||||||
{ "set_parent", "?o", xdg_shell_types + 11 },
|
|
||||||
{ "set_title", "s", xdg_shell_types + 0 },
|
|
||||||
{ "set_app_id", "s", xdg_shell_types + 0 },
|
|
||||||
{ "show_window_menu", "ouii", xdg_shell_types + 12 },
|
|
||||||
{ "move", "ou", xdg_shell_types + 16 },
|
|
||||||
{ "resize", "ouu", xdg_shell_types + 18 },
|
|
||||||
{ "set_max_size", "ii", xdg_shell_types + 0 },
|
|
||||||
{ "set_min_size", "ii", xdg_shell_types + 0 },
|
|
||||||
{ "set_maximized", "", xdg_shell_types + 0 },
|
|
||||||
{ "unset_maximized", "", xdg_shell_types + 0 },
|
|
||||||
{ "set_fullscreen", "?o", xdg_shell_types + 21 },
|
|
||||||
{ "unset_fullscreen", "", xdg_shell_types + 0 },
|
|
||||||
{ "set_minimized", "", xdg_shell_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_toplevel_events[] = {
|
|
||||||
{ "configure", "iia", xdg_shell_types + 0 },
|
|
||||||
{ "close", "", xdg_shell_types + 0 },
|
|
||||||
{ "configure_bounds", "4ii", xdg_shell_types + 0 },
|
|
||||||
{ "wm_capabilities", "5a", xdg_shell_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface xdg_toplevel_interface = {
|
|
||||||
"xdg_toplevel", 6,
|
|
||||||
14, xdg_toplevel_requests,
|
|
||||||
4, xdg_toplevel_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_popup_requests[] = {
|
|
||||||
{ "destroy", "", xdg_shell_types + 0 },
|
|
||||||
{ "grab", "ou", xdg_shell_types + 22 },
|
|
||||||
{ "reposition", "3ou", xdg_shell_types + 24 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct wl_message xdg_popup_events[] = {
|
|
||||||
{ "configure", "iiii", xdg_shell_types + 0 },
|
|
||||||
{ "popup_done", "", xdg_shell_types + 0 },
|
|
||||||
{ "repositioned", "3u", xdg_shell_types + 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
WL_PRIVATE const struct wl_interface xdg_popup_interface = {
|
|
||||||
"xdg_popup", 6,
|
|
||||||
3, xdg_popup_requests,
|
|
||||||
3, xdg_popup_events,
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1,114 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
#include <fennec/lang/types.h>
|
|
||||||
|
|
||||||
#ifndef FENNEC_LIB
|
|
||||||
#define FENNEC_LIB(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FENNEC_SYMBOL
|
|
||||||
#define FENNEC_SYMBOL(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FENNEC_GLOBAL
|
|
||||||
#define FENNEC_GLOBAL(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
FENNEC_LIB(WAYLAND);
|
|
||||||
|
|
||||||
FENNEC_SYMBOL(void, wl_proxy_marshal, struct wl_proxy*, uint32_t, ...);
|
|
||||||
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(void, wl_proxy_destroy, struct wl_proxy*);
|
|
||||||
FENNEC_SYMBOL(int, wl_proxy_add_listener, struct wl_proxy*, void (**)(void), void*);
|
|
||||||
FENNEC_SYMBOL(void, wl_proxy_set_user_data, struct wl_proxy*, void*);
|
|
||||||
FENNEC_SYMBOL(void*, wl_proxy_get_user_data, struct wl_proxy*);
|
|
||||||
FENNEC_SYMBOL(uint32_t, wl_proxy_get_version, struct wl_proxy*);
|
|
||||||
FENNEC_SYMBOL(uint32_t, wl_proxy_get_id, struct wl_proxy*);
|
|
||||||
FENNEC_SYMBOL(const char*, wl_proxy_get_class, struct wl_proxy*);
|
|
||||||
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_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_to_fd, int);
|
|
||||||
FENNEC_SYMBOL(void, wl_display_disconnect, struct wl_display*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_get_fd, struct wl_display*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_dispatch, struct wl_display*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_dispatch_queue, struct wl_display*, struct wl_event_queue*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_dispatch_queue_pending, struct wl_display*, struct wl_event_queue*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_dispatch_pending, struct wl_display*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_prepare_read, struct wl_display*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_prepare_read_queue, struct wl_display*, struct wl_event_queue*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_read_events, struct wl_display*);
|
|
||||||
FENNEC_SYMBOL(void, wl_display_cancel_read, struct wl_display*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_get_error, struct wl_display*);
|
|
||||||
FENNEC_SYMBOL(int, wl_display_flush, 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(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_list_init, struct wl_list*);
|
|
||||||
FENNEC_SYMBOL(void, wl_list_insert, struct wl_list*, struct wl_list*) ;
|
|
||||||
FENNEC_SYMBOL(void, wl_list_remove, 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(void, wl_list_insert_list, struct wl_list*, struct wl_list*);
|
|
||||||
|
|
||||||
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_callback_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_compositor_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_shm_pool_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_shm_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_buffer_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_data_offer_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_data_source_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_data_device_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_data_device_manager_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_shell_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_shell_surface_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_surface_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_seat_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_pointer_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_keyboard_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_touch_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_output_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_region_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_subcompositor_interface);
|
|
||||||
FENNEC_GLOBAL(const struct wl_interface, wl_subsurface_interface);
|
|
||||||
|
|
||||||
FENNEC_LIB(WAYLAND_EGL);
|
|
||||||
|
|
||||||
FENNEC_SYMBOL(struct wl_egl_window*, wl_egl_window_create, struct wl_surface *surface, int width, int height);
|
|
||||||
FENNEC_SYMBOL(void, wl_egl_window_destroy, struct wl_egl_window *egl_window);
|
|
||||||
FENNEC_SYMBOL(void, wl_egl_window_resize, struct wl_egl_window *egl_window, int width, int height, int dx, int dy);
|
|
||||||
FENNEC_SYMBOL(void, wl_egl_window_get_attached_size, struct wl_egl_window *egl_window, int *width, int *height);
|
|
||||||
|
|
||||||
#undef FENNEC_LIB
|
|
||||||
#undef FENNEC_SYMBOL
|
|
||||||
#undef FENNEC_GLOBAL
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,98 +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_CLIENT_H
|
|
||||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_LIB_WAYLAND_CLIENT_H
|
|
||||||
|
|
||||||
#include <wayland-client-core.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>
|
|
||||||
|
|
||||||
#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
|
|
||||||
@@ -1,83 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \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
|
|
||||||
@@ -1,144 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2009-2012 Daniel Stone
|
|
||||||
* Copyright © 2012 Intel Corporation
|
|
||||||
* Copyright © 2012 Ran Benita
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifndef FENNEC_LIB
|
|
||||||
#define FENNEC_LIB(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FENNEC_SYMBOL
|
|
||||||
#define FENNEC_SYMBOL(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FENNEC_GLOBAL
|
|
||||||
#define FENNEC_GLOBAL(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FENNEC_LIB(XKB);
|
|
||||||
|
|
||||||
FENNEC_SYMBOL(int, xkb_keysym_get_name, xkb_keysym_t, char*, size_t);
|
|
||||||
FENNEC_SYMBOL(xkb_keysym_t, xkb_keysym_from_name, const char*, enum xkb_keysym_flags);
|
|
||||||
FENNEC_SYMBOL(int, xkb_keysym_to_utf8, xkb_keysym_t, char*, size_t);
|
|
||||||
FENNEC_SYMBOL(uint32_t, xkb_keysym_to_utf32, xkb_keysym_t);
|
|
||||||
FENNEC_SYMBOL(xkb_keysym_t, xkb_utf32_to_keysym, uint32_t);
|
|
||||||
FENNEC_SYMBOL(xkb_keysym_t, xkb_keysym_to_upper, xkb_keysym_t);
|
|
||||||
FENNEC_SYMBOL(xkb_keysym_t, xkb_keysym_to_lower, xkb_keysym_t);
|
|
||||||
|
|
||||||
FENNEC_SYMBOL(struct xkb_context*, xkb_context_new, enum xkb_context_flags);
|
|
||||||
FENNEC_SYMBOL(struct xkb_context*, xkb_context_ref, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(void, xkb_context_unref, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(void, xkb_context_set_user_data, struct xkb_context*, void*);
|
|
||||||
FENNEC_SYMBOL(void*, xkb_context_get_user_data, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(int, xkb_context_include_path_append, struct xkb_context*, const char*);
|
|
||||||
FENNEC_SYMBOL(int, xkb_context_include_path_append_default, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(int, xkb_context_include_path_reset_defaults, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(void, xkb_context_include_path_clear, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(unsigned int, xkb_context_num_include_paths, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(const char*, xkb_context_include_path_get, struct xkb_context*, unsigned int);
|
|
||||||
FENNEC_SYMBOL(void, xkb_context_set_log_level, struct xkb_context*, enum xkb_log_level);
|
|
||||||
FENNEC_SYMBOL(enum xkb_log_level, xkb_context_get_log_level, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(void, xkb_context_set_log_verbosity, struct xkb_context*, int);
|
|
||||||
FENNEC_SYMBOL(int, xkb_context_get_log_verbosity, struct xkb_context*);
|
|
||||||
FENNEC_SYMBOL(void, xkb_context_set_log_fn, struct xkb_context*, void (*)(struct xkb_context*, enum xkb_log_level, const char*, va_list));
|
|
||||||
|
|
||||||
FENNEC_SYMBOL(struct xkb_keymap*, xkb_keymap_new_from_names, struct xkb_context*, const struct xkb_rule_names*, enum xkb_keymap_compile_flags);
|
|
||||||
FENNEC_SYMBOL(struct xkb_keymap*, xkb_keymap_new_from_file, struct xkb_context*, FILE*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
|
||||||
FENNEC_SYMBOL(struct xkb_keymap*, xkb_keymap_new_from_string, struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
|
||||||
FENNEC_SYMBOL(struct xkb_keymap*, xkb_keymap_new_from_buffer, struct xkb_context*, const char*, size_t, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
|
||||||
FENNEC_SYMBOL(struct xkb_keymap*, xkb_keymap_ref, struct xkb_keymap*);
|
|
||||||
FENNEC_SYMBOL(void, xkb_keymap_unref, struct xkb_keymap*);
|
|
||||||
FENNEC_SYMBOL(char*, xkb_keymap_get_as_string, struct xkb_keymap*, enum xkb_keymap_format);
|
|
||||||
FENNEC_SYMBOL(xkb_keycode_t, xkb_keymap_min_keycode, struct xkb_keymap*);
|
|
||||||
FENNEC_SYMBOL(xkb_keycode_t, xkb_keymap_max_keycode, struct xkb_keymap*);
|
|
||||||
FENNEC_SYMBOL(void, xkb_keymap_key_for_each, struct xkb_keymap*, xkb_keymap_key_iter_t, void*);
|
|
||||||
FENNEC_SYMBOL(const char*, xkb_keymap_key_get_name, struct xkb_keymap*, xkb_keycode_t);
|
|
||||||
FENNEC_SYMBOL(xkb_keycode_t, xkb_keymap_key_by_name, struct xkb_keymap*, const char*);
|
|
||||||
FENNEC_SYMBOL(xkb_mod_index_t, xkb_keymap_num_mods, struct xkb_keymap*);
|
|
||||||
FENNEC_SYMBOL(const char*, xkb_keymap_mod_get_name, struct xkb_keymap*, xkb_mod_index_t);
|
|
||||||
FENNEC_SYMBOL(xkb_mod_index_t, xkb_keymap_mod_get_index, struct xkb_keymap*, const char*);
|
|
||||||
FENNEC_SYMBOL(xkb_layout_index_t, xkb_keymap_num_layouts, struct xkb_keymap*);
|
|
||||||
FENNEC_SYMBOL(const char*, xkb_keymap_layout_get_name, struct xkb_keymap*, xkb_layout_index_t);
|
|
||||||
FENNEC_SYMBOL(xkb_layout_index_t, xkb_keymap_layout_get_index, struct xkb_keymap*, const char*);
|
|
||||||
FENNEC_SYMBOL(xkb_led_index_t, xkb_keymap_num_leds, struct xkb_keymap*);
|
|
||||||
FENNEC_SYMBOL(const char*, xkb_keymap_led_get_name, struct xkb_keymap*, xkb_led_index_t);
|
|
||||||
FENNEC_SYMBOL(xkb_led_index_t, xkb_keymap_led_get_index, struct xkb_keymap*, const char*);
|
|
||||||
FENNEC_SYMBOL(xkb_layout_index_t, xkb_keymap_num_layouts_for_key, struct xkb_keymap*, xkb_keycode_t);
|
|
||||||
FENNEC_SYMBOL(xkb_level_index_t, xkb_keymap_num_levels_for_key, struct xkb_keymap*, xkb_keycode_t, xkb_layout_index_t);
|
|
||||||
FENNEC_SYMBOL(size_t, xkb_keymap_key_get_mods_for_level, struct xkb_keymap*, xkb_keycode_t, xkb_layout_index_t, xkb_level_index_t, xkb_mod_mask_t*, size_t);
|
|
||||||
FENNEC_SYMBOL(int, xkb_keymap_key_get_syms_by_level, struct xkb_keymap*, xkb_keycode_t, xkb_layout_index_t, xkb_level_index_t, const xkb_keysym_t**);
|
|
||||||
FENNEC_SYMBOL(int, xkb_keymap_key_repeats, struct xkb_keymap*, xkb_keycode_t);
|
|
||||||
|
|
||||||
FENNEC_SYMBOL(struct xkb_state*, xkb_state_new, struct xkb_keymap*);
|
|
||||||
FENNEC_SYMBOL(struct xkb_state*, xkb_state_ref, struct xkb_state*);
|
|
||||||
FENNEC_SYMBOL(void, xkb_state_unref, struct xkb_state*);
|
|
||||||
FENNEC_SYMBOL(struct xkb_keymap*, xkb_state_get_keymap, struct xkb_state*);
|
|
||||||
FENNEC_SYMBOL(enum xkb_state_component, xkb_state_update_key, struct xkb_state*, xkb_keycode_t, enum xkb_key_direction);
|
|
||||||
FENNEC_SYMBOL(enum xkb_state_component, xkb_state_update_mask, struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_key_get_syms, struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_key_get_utf8, struct xkb_state*, xkb_keycode_t, char*, size_t);
|
|
||||||
FENNEC_SYMBOL(uint32_t, xkb_state_key_get_utf32, struct xkb_state*, xkb_keycode_t);
|
|
||||||
FENNEC_SYMBOL(xkb_keysym_t, xkb_state_key_get_one_sym, struct xkb_state*, xkb_keycode_t);
|
|
||||||
FENNEC_SYMBOL(xkb_layout_index_t, xkb_state_key_get_layout, struct xkb_state*, xkb_keycode_t);
|
|
||||||
FENNEC_SYMBOL(xkb_level_index_t, xkb_state_key_get_level, struct xkb_state*, xkb_keycode_t, xkb_layout_index_t);
|
|
||||||
FENNEC_SYMBOL(xkb_mod_mask_t, xkb_state_serialize_mods, struct xkb_state*, enum xkb_state_component);
|
|
||||||
FENNEC_SYMBOL(xkb_layout_index_t, xkb_state_serialize_layout, struct xkb_state*, enum xkb_state_component);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_mod_name_is_active, struct xkb_state*, const char*, enum xkb_state_component);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_mod_names_are_active, struct xkb_state*, enum xkb_state_component, enum xkb_state_match, ...);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_mod_index_is_active, struct xkb_state*, xkb_mod_index_t, enum xkb_state_component);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_mod_indices_are_active, struct xkb_state*, enum xkb_state_component, enum xkb_state_match, ...);
|
|
||||||
FENNEC_SYMBOL(xkb_mod_mask_t, xkb_state_key_get_consumed_mods2, struct xkb_state*, xkb_keycode_t, enum xkb_consumed_mode);
|
|
||||||
FENNEC_SYMBOL(xkb_mod_mask_t, xkb_state_key_get_consumed_mods, struct xkb_state*, xkb_keycode_t);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_mod_index_is_consumed2, struct xkb_state*, xkb_keycode_t, xkb_mod_index_t, enum xkb_consumed_mode);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_mod_index_is_consumed, struct xkb_state*, xkb_keycode_t, xkb_mod_index_t);
|
|
||||||
FENNEC_SYMBOL(xkb_mod_mask_t, xkb_state_mod_mask_remove_consumed, struct xkb_state*, xkb_keycode_t, xkb_mod_mask_t);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_layout_name_is_active, struct xkb_state*, const char*, enum xkb_state_component);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_layout_index_is_active, struct xkb_state*, xkb_layout_index_t, enum xkb_state_component);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_led_name_is_active, struct xkb_state*, const char*);
|
|
||||||
FENNEC_SYMBOL(int, xkb_state_led_index_is_active, struct xkb_state*, xkb_led_index_t);
|
|
||||||
|
|
||||||
#undef FENNEC_LIB
|
|
||||||
#undef FENNEC_SYMBOL
|
|
||||||
#undef FENNEC_GLOBAL
|
|
||||||
@@ -1,110 +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_XKB_LIB_XKB_H
|
|
||||||
#define FENNEC_PLATFORM_LINUX_XKB_LIB_XKB_H
|
|
||||||
|
|
||||||
#include <xkbcommon/xkbcommon.h>
|
|
||||||
|
|
||||||
#define FENNEC_LIB(name) extern bool FENNEC_HAS_LIB_##name;
|
|
||||||
#define FENNEC_SYMBOL(ret, fn, ...) using XKB_sym_##fn = ret(*)(__VA_ARGS__); \
|
|
||||||
extern XKB_sym_##fn XKB_##fn;
|
|
||||||
#define FENNEC_GLOBAL(type, name) extern type* XKB_##name;
|
|
||||||
#include <fennec/platform/linux/xkb/lib/sym.h>
|
|
||||||
|
|
||||||
#define xkb_keysym_get_name XKB_xkb_keysym_get_name
|
|
||||||
#define xkb_keysym_from_name XKB_xkb_keysym_from_name
|
|
||||||
#define xkb_keysym_to_utf8 XKB_xkb_keysym_to_utf8
|
|
||||||
#define xkb_keysym_to_utf32 XKB_xkb_keysym_to_utf32
|
|
||||||
#define xkb_utf32_to_keysym XKB_xkb_utf32_to_keysym
|
|
||||||
#define xkb_keysym_to_upper XKB_xkb_keysym_to_upper
|
|
||||||
#define xkb_keysym_to_lower XKB_xkb_keysym_to_lower
|
|
||||||
|
|
||||||
#define xkb_context_new XKB_xkb_context_new
|
|
||||||
#define xkb_context_ref XKB_xkb_context_ref
|
|
||||||
#define xkb_context_unref XKB_xkb_context_unref
|
|
||||||
#define xkb_context_set_user_data XKB_xkb_context_set_user_data
|
|
||||||
#define xkb_context_get_user_data XKB_xkb_context_get_user_data
|
|
||||||
#define xkb_context_include_path_append XKB_xkb_context_include_path_append
|
|
||||||
#define xkb_context_include_path_append_default XKB_xkb_context_include_path_append_default
|
|
||||||
#define xkb_context_include_path_reset_defaults XKB_xkb_context_include_path_reset_defaults
|
|
||||||
#define xkb_context_include_path_clear XKB_xkb_context_include_path_clear
|
|
||||||
#define xkb_context_num_include_paths XKB_xkb_context_num_include_paths
|
|
||||||
#define xkb_context_include_path_get XKB_xkb_context_include_path_get
|
|
||||||
#define xkb_context_set_log_level XKB_xkb_context_set_log_level
|
|
||||||
#define xkb_context_get_log_level XKB_xkb_context_get_log_level
|
|
||||||
#define xkb_context_set_log_verbosity XKB_xkb_context_set_log_verbosity
|
|
||||||
#define xkb_context_get_log_verbosity XKB_xkb_context_get_log_verbosity
|
|
||||||
#define xkb_context_set_log_fn XKB_xkb_context_set_log_fn
|
|
||||||
|
|
||||||
#define xkb_keymap_new_from_names XKB_xkb_keymap_new_from_names
|
|
||||||
#define xkb_keymap_new_from_file XKB_xkb_keymap_new_from_file
|
|
||||||
#define xkb_keymap_new_from_string XKB_xkb_keymap_new_from_string
|
|
||||||
#define xkb_keymap_new_from_buffer XKB_xkb_keymap_new_from_buffer
|
|
||||||
#define xkb_keymap_ref XKB_xkb_keymap_ref
|
|
||||||
#define xkb_keymap_unref XKB_xkb_keymap_unref
|
|
||||||
#define xkb_keymap_get_as_string XKB_xkb_keymap_get_as_string
|
|
||||||
#define xkb_keymap_min_keycode XKB_xkb_keymap_min_keycode
|
|
||||||
#define xkb_keymap_max_keycode XKB_xkb_keymap_max_keycode
|
|
||||||
#define xkb_keymap_key_for_each XKB_xkb_keymap_key_for_each
|
|
||||||
#define xkb_keymap_key_get_name XKB_xkb_keymap_key_get_name
|
|
||||||
#define xkb_keymap_key_by_name XKB_xkb_keymap_key_by_name
|
|
||||||
#define xkb_keymap_num_mods XKB_xkb_keymap_num_mods
|
|
||||||
#define xkb_keymap_mod_get_name XKB_xkb_keymap_mod_get_name
|
|
||||||
#define xkb_keymap_mod_get_index XKB_xkb_keymap_mod_get_index
|
|
||||||
#define xkb_keymap_num_layouts XKB_xkb_keymap_num_layouts
|
|
||||||
#define xkb_keymap_layout_get_name XKB_xkb_keymap_layout_get_name
|
|
||||||
#define xkb_keymap_layout_get_index XKB_xkb_keymap_layout_get_index
|
|
||||||
#define xkb_keymap_num_leds XKB_xkb_keymap_num_leds
|
|
||||||
#define xkb_keymap_led_get_name XKB_xkb_keymap_led_get_name
|
|
||||||
#define xkb_keymap_led_get_index XKB_xkb_keymap_led_get_index
|
|
||||||
#define xkb_keymap_num_layouts_for_key XKB_xkb_keymap_num_layouts_for_key
|
|
||||||
#define xkb_keymap_num_levels_for_key XKB_xkb_keymap_num_levels_for_key
|
|
||||||
#define xkb_keymap_key_get_mods_for_level XKB_xkb_keymap_key_get_mods_for_level
|
|
||||||
#define xkb_keymap_key_get_syms_by_level XKB_xkb_keymap_key_get_syms_by_level
|
|
||||||
#define xkb_keymap_key_repeats XKB_xkb_keymap_key_repeats
|
|
||||||
|
|
||||||
#define xkb_state_new XKB_xkb_state_new
|
|
||||||
#define xkb_state_ref XKB_xkb_state_ref
|
|
||||||
#define xkb_state_unref XKB_xkb_state_unref
|
|
||||||
#define xkb_state_get_keymap XKB_xkb_state_get_keymap
|
|
||||||
#define xkb_state_update_key XKB_xkb_state_update_key
|
|
||||||
#define xkb_state_update_mask XKB_xkb_state_update_mask
|
|
||||||
#define xkb_state_key_get_syms XKB_xkb_state_key_get_syms
|
|
||||||
#define xkb_state_key_get_utf8 XKB_xkb_state_key_get_utf8
|
|
||||||
#define xkb_state_key_get_utf32 XKB_xkb_state_key_get_utf32
|
|
||||||
#define xkb_state_key_get_one_sym XKB_xkb_state_key_get_one_sym
|
|
||||||
#define xkb_state_key_get_layout XKB_xkb_state_key_get_layout
|
|
||||||
#define xkb_state_key_get_level XKB_xkb_state_key_get_level
|
|
||||||
#define xkb_state_serialize_mods XKB_xkb_state_serialize_mods
|
|
||||||
#define xkb_state_serialize_layout XKB_xkb_state_serialize_layout
|
|
||||||
#define xkb_state_mod_name_is_active XKB_xkb_state_mod_name_is_active
|
|
||||||
#define xkb_state_mod_names_are_active XKB_xkb_state_mod_names_are_active
|
|
||||||
#define xkb_state_mod_index_is_active XKB_xkb_state_mod_index_is_active
|
|
||||||
#define xkb_state_mod_indices_are_active XKB_xkb_state_mod_indices_are_active
|
|
||||||
#define xkb_state_key_get_consumed_mods2 XKB_xkb_state_key_get_consumed_mods2
|
|
||||||
#define xkb_state_key_get_consumed_mods XKB_xkb_state_key_get_consumed_mods
|
|
||||||
#define xkb_state_mod_index_is_consumed2 XKB_xkb_state_mod_index_is_consumed2
|
|
||||||
#define xkb_state_mod_index_is_consumed XKB_xkb_state_mod_index_is_consumed
|
|
||||||
#define xkb_state_mod_mask_remove_consumed XKB_xkb_state_mod_mask_remove_consumed
|
|
||||||
#define xkb_state_layout_name_is_active XKB_xkb_state_layout_name_is_active
|
|
||||||
#define xkb_state_layout_index_is_active XKB_xkb_state_layout_index_is_active
|
|
||||||
#define xkb_state_led_name_is_active XKB_xkb_state_led_name_is_active
|
|
||||||
#define xkb_state_led_index_is_active XKB_xkb_state_led_index_is_active
|
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_LINUX_XKB_LIB_XKB_H
|
|
||||||
@@ -1,70 +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_OPENGL_EGL_CONTEXT_H
|
|
||||||
#define FENNEC_PLATFORM_OPENGL_EGL_CONTEXT_H
|
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
|
||||||
#include <fennec/platform/interface/gfxcontext.h>
|
|
||||||
#include <fennec/platform/opengl/egl/fwd.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
class eglcontext : public gfxcontext {
|
|
||||||
public:
|
|
||||||
eglcontext(display* display);
|
|
||||||
|
|
||||||
~eglcontext() override;
|
|
||||||
|
|
||||||
bool connected() override;
|
|
||||||
int32_t get_version_major() override { return _eglvmajor; }
|
|
||||||
int32_t get_version_minor() override { return _eglvminor; }
|
|
||||||
int32_t get_version() override { return _eglctype; }
|
|
||||||
const cstring& get_name() override;
|
|
||||||
bool check_extension(const cstring& ext) override;
|
|
||||||
|
|
||||||
gfxsurface* create_surface(window* window) 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:
|
|
||||||
EGLDisplay _egldisplay;
|
|
||||||
EGLContext _eglcontext;
|
|
||||||
EGLConfig _eglconfig;
|
|
||||||
EGLint _eglvmajor, _eglvminor, _eglctype;
|
|
||||||
cstring _extensions;
|
|
||||||
|
|
||||||
void cleanup();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_OPENGL_EGL_CONTEXT_H
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \file gfxsurface.h
|
/// \file sdlwindow.h
|
||||||
/// \brief
|
/// \brief
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -28,49 +28,40 @@
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_PLATFORM_INTERFACE_GFXSURFACE_H
|
#ifndef FENNEC_PLATFORM_SDL_SDLWINDOW_H
|
||||||
#define FENNEC_PLATFORM_INTERFACE_GFXSURFACE_H
|
#define FENNEC_PLATFORM_SDL_SDLWINDOW_H
|
||||||
|
|
||||||
#include <fennec/lang/types.h>
|
|
||||||
#include <fennec/lang/typeuuid.h>
|
|
||||||
#include <fennec/platform/interface/fwd.h>
|
|
||||||
#include <fennec/platform/interface/window.h>
|
#include <fennec/platform/interface/window.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class gfxsurface : public typed<gfxsurface> {
|
class sdlwindow : public window {
|
||||||
public:
|
public:
|
||||||
virtual ~gfxsurface() = default;
|
sdlwindow(window* parent, const config& cfg);
|
||||||
|
|
||||||
virtual void resize(size_t width, size_t height) {
|
bool running() override;
|
||||||
_width = width;
|
|
||||||
_height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxcontext* get_context() {
|
void set_fullscreen(bool) override;
|
||||||
return _context;
|
void set_borderless(bool) override;
|
||||||
}
|
|
||||||
|
|
||||||
window* get_window() {
|
void grab_mouse(bool) override;
|
||||||
return _window;
|
void grab_keyboard(bool) override;
|
||||||
}
|
|
||||||
|
void set_title(const cstring&) override;
|
||||||
|
void set_title(const string&) override;
|
||||||
|
void set_progress(bool, float) override;
|
||||||
|
|
||||||
|
void vsync(int8_t) override;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
void begin_frame() override;
|
||||||
gfxcontext* _context;
|
void end_frame() override;
|
||||||
window* _window;
|
|
||||||
size_t _width, _height;
|
private:
|
||||||
|
|
||||||
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
|
#endif // FENNEC_PLATFORM_SDL_SDLWINDOW_H
|
||||||
@@ -27,8 +27,8 @@ namespace fennec
|
|||||||
class unix_platform : public platform {
|
class unix_platform : public platform {
|
||||||
public:
|
public:
|
||||||
template<typename PlatformT>
|
template<typename PlatformT>
|
||||||
explicit unix_platform(const cstring& name, PlatformT*)
|
explicit unix_platform(const cstring& name, PlatformT* type)
|
||||||
: platform(name, (PlatformT*)(nullptr)) {
|
: platform(name, type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_object* load_object(const cstring& file) override;
|
shared_object* load_object(const cstring& file) override;
|
||||||
|
|||||||
46
include/fennec/renderers/interface/forward.h
Normal file
46
include/fennec/renderers/interface/forward.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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 forward.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_RENDERERS_INTERFACE_FORWARD_H
|
||||||
|
#define FENNEC_RENDERERS_INTERFACE_FORWARD_H
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class gfxpass; // Overarching rendering scheme
|
||||||
|
class gfxcontext; // Globals for an API's context
|
||||||
|
class gfxresourcepool; // Handles resource creation, allocation, and mapping
|
||||||
|
class gfxpass; // A pass of the renderer, holds a set of subpasses with one coherent objective
|
||||||
|
class gfxsubpass; // A subpass of the renderer, implements, for example, the steps of composing and lighting a deferred renderer
|
||||||
|
class gfxpipeline; // A user-defined pipeline, e.g. the Vulkan pipeline needed to render the G-Buffer
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_RENDERERS_INTERFACE_FORWARD_H
|
||||||
78
include/fennec/renderers/interface/gfxcontext.h
Normal file
78
include/fennec/renderers/interface/gfxcontext.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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 gfxcontext.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
|
||||||
|
#define FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
|
||||||
|
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
|
#include <fennec/langproc/strings/string.h>
|
||||||
|
#include <fennec/renderers/interface/forward.h>
|
||||||
|
#include <fennec/renderers/interface/gfxresourcepool.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class gfxcontext {
|
||||||
|
public:
|
||||||
|
enum texture_ : uint8_t {
|
||||||
|
texture_1d = 0,
|
||||||
|
texture_1d_array,
|
||||||
|
texture_2d,
|
||||||
|
texture_2d_array,
|
||||||
|
texture_multisample,
|
||||||
|
texture_multisample_array,
|
||||||
|
texture_cubemap,
|
||||||
|
texture_cubemap_array,
|
||||||
|
texture_3d,
|
||||||
|
};
|
||||||
|
|
||||||
|
using handle_t = uint32_t;
|
||||||
|
|
||||||
|
struct version_t {
|
||||||
|
uint8_t major, minor, patch;
|
||||||
|
string str;
|
||||||
|
};
|
||||||
|
|
||||||
|
const version_t version;
|
||||||
|
gfxresourcepool resources;
|
||||||
|
|
||||||
|
gfxcontext& operator=(const gfxcontext&) = delete;
|
||||||
|
gfxcontext& operator=(gfxcontext&&) = delete;
|
||||||
|
|
||||||
|
virtual gfxpass* create_pass() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
|
||||||
@@ -16,47 +16,43 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file gfxcontext.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_GFXCONTEXT_H
|
#ifndef FENNEC_PLATFORM_INTERFACE_GFXCONTEXT_H
|
||||||
#define FENNEC_PLATFORM_INTERFACE_GFXCONTEXT_H
|
#define FENNEC_PLATFORM_INTERFACE_GFXCONTEXT_H
|
||||||
|
|
||||||
|
#include <fennec/lang/types.h>
|
||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/langproc/strings/string.h>
|
||||||
#include <fennec/lang/typeuuid.h>
|
#include <fennec/renderers/interface/forward.h>
|
||||||
#include <fennec/platform/interface/fwd.h>
|
|
||||||
#include <fennec/platform/interface/window.h>
|
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class gfxcontext : public typed<gfxcontext> {
|
///
|
||||||
|
/// \brief Defines an interface that holds a series of passes with one coherent objective
|
||||||
|
/// \details This represents the overarching renderer, and not any platform specific behaviour.
|
||||||
|
/// I.E. This acts as a proxy for creating API objects, but the behaviour of those objects
|
||||||
|
/// is defined elsewhere.
|
||||||
|
class gfxpass {
|
||||||
public:
|
public:
|
||||||
const string name;
|
gfxsubpass* add_subpass();
|
||||||
|
|
||||||
virtual bool connected() = 0;
|
private:
|
||||||
virtual const cstring& get_name() = 0;
|
|
||||||
virtual int32_t get_version_major() = 0;
|
|
||||||
virtual int32_t get_version_minor() = 0;
|
|
||||||
virtual int32_t get_version() = 0;
|
|
||||||
|
|
||||||
virtual bool check_extension(const cstring& ext) = 0;
|
};
|
||||||
virtual void make_current(gfxsurface* surface) = 0;
|
|
||||||
|
|
||||||
virtual gfxsurface* create_surface(window* window) = 0;
|
class gfxsubpass {
|
||||||
|
|
||||||
virtual ~gfxcontext() = default;
|
|
||||||
|
|
||||||
display* get_display() {
|
|
||||||
return _display;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
display* _display;
|
|
||||||
|
|
||||||
template<typename ContextT>
|
|
||||||
gfxcontext(display* display, const cstring& name, ContextT* type)
|
|
||||||
: typed(type)
|
|
||||||
, name(name)
|
|
||||||
, _display(display) {
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -16,22 +16,28 @@
|
|||||||
// 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_PLATFORM_LINUX_WAYLAND_DYN_H
|
///
|
||||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_DYN_H
|
/// \file gfxresourcepool.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#include <fennec/platform/interface/platform.h>
|
#ifndef FENNEC_RENDERERS_INTERFACE_GFXRESOURCEPOOL_H
|
||||||
|
#define FENNEC_RENDERERS_INTERFACE_GFXRESOURCEPOOL_H
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace libwayland
|
class gfxresourcepool {
|
||||||
{
|
|
||||||
|
|
||||||
bool load_symbols(platform* platform);
|
};
|
||||||
void unload_symbols(platform* platform);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
#endif // FENNEC_RENDERERS_INTERFACE_GFXRESOURCEPOOL_H
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_DYN_H
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \file fwd.h
|
/// \file gfxsubpass.h
|
||||||
/// \brief
|
/// \brief
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -28,15 +28,14 @@
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_PLATFORM_OPENGL_EGL_FWD_H
|
#ifndef FENNEC_RENDERERS_INTERFACE_GFXSUBPASS_H
|
||||||
#define FENNEC_PLATFORM_OPENGL_EGL_FWD_H
|
#define FENNEC_RENDERERS_INTERFACE_GFXSUBPASS_H
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class eglcontext;
|
|
||||||
class eglsurface;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_OPENGL_EGL_FWD_H
|
#endif // FENNEC_RENDERERS_INTERFACE_GFXSUBPASS_H
|
||||||
@@ -61,16 +61,16 @@ enum access_ : GLbitfield {
|
|||||||
|
|
||||||
enum texture_ : GLenum {
|
enum texture_ : GLenum {
|
||||||
TEX_1D = GL_TEXTURE_1D,
|
TEX_1D = GL_TEXTURE_1D,
|
||||||
TEX_1D_V = GL_TEXTURE_1D_ARRAY,
|
TEX_1D_ARRAY = GL_TEXTURE_1D_ARRAY,
|
||||||
|
|
||||||
TEX_2D = GL_TEXTURE_2D,
|
TEX_2D = GL_TEXTURE_2D,
|
||||||
TEX_2D_V = GL_TEXTURE_2D_ARRAY,
|
TEX_2D_ARRAY = GL_TEXTURE_2D_ARRAY,
|
||||||
TEX_2D_MS = GL_TEXTURE_2D_MULTISAMPLE,
|
TEX_2D_MS = GL_TEXTURE_2D_MULTISAMPLE,
|
||||||
TEX_2D_MS_V = GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
|
TEX_2D_MS_ARRAY = GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
|
||||||
TEX_RECT = GL_TEXTURE_RECTANGLE,
|
TEX_RECT = GL_TEXTURE_RECTANGLE,
|
||||||
|
|
||||||
TEX_CUBEMAP = GL_TEXTURE_CUBE_MAP,
|
TEX_CUBEMAP = GL_TEXTURE_CUBE_MAP,
|
||||||
TEX_CUBEMAP_V = GL_TEXTURE_CUBE_MAP_ARRAY,
|
TEX_CUBEMAP_ARRAY = GL_TEXTURE_CUBE_MAP_ARRAY,
|
||||||
|
|
||||||
TEX_3D = GL_TEXTURE_3D,
|
TEX_3D = GL_TEXTURE_3D,
|
||||||
|
|
||||||
@@ -57,14 +57,14 @@ namespace gl
|
|||||||
{
|
{
|
||||||
|
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using texture1d = texture<TEX_1D, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using texture1d = texture<TEX_1D, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using texture1dv = texture<TEX_1D_V, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using texture1d_array = texture<TEX_1D_ARRAY, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d = texture<TEX_2D, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using texture2d = texture<TEX_2D, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using texture2dv = texture<TEX_2D_V, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using texture2d_array = texture<TEX_2D_ARRAY, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using texture_rect = texture<TEX_RECT, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using texture_rect = texture<TEX_RECT, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms = texture<TEX_2D_MS, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms = texture<TEX_2D_MS, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using texture2dv_ms = texture<TEX_2D_MS_V, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms_array = texture<TEX_2D_MS_ARRAY, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using cubemap = texture<TEX_CUBEMAP, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using cubemap = texture<TEX_CUBEMAP, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using cubemapv = texture<TEX_CUBEMAP_V, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using cubemap_array = texture<TEX_CUBEMAP_ARRAY, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using texture3d = texture<TEX_3D, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using texture3d = texture<TEX_3D, FormatV, ImmutableV>;
|
||||||
template<GLint FormatV, GLboolean ImmutableV> using buffer_texture = texture<TEX_BUFFER, FormatV, ImmutableV>;
|
template<GLint FormatV, GLboolean ImmutableV> using buffer_texture = texture<TEX_BUFFER, FormatV, ImmutableV>;
|
||||||
|
|
||||||
@@ -87,17 +87,17 @@ public:
|
|||||||
static constexpr GLboolean immutable = ImmutableV;
|
static constexpr GLboolean immutable = ImmutableV;
|
||||||
static constexpr GLboolean is_rect = type == TEX_RECT;
|
static constexpr GLboolean is_rect = type == TEX_RECT;
|
||||||
static constexpr GLboolean is_buffered = type == TEX_BUFFER;
|
static constexpr GLboolean is_buffered = type == TEX_BUFFER;
|
||||||
static constexpr GLboolean sampled = type == TEX_2D_MS or type == TEX_2D_MS_V;
|
static constexpr GLboolean sampled = type == TEX_2D_MS or type == TEX_2D_MS_ARRAY;
|
||||||
static constexpr GLboolean cubemap = type == TEX_CUBEMAP or type == TEX_CUBEMAP_V;
|
static constexpr GLboolean cubemap = type == TEX_CUBEMAP or type == TEX_CUBEMAP_ARRAY;
|
||||||
static constexpr GLboolean is_1d = type == TEX_1D or type == TEX_1D_V;
|
static constexpr GLboolean is_1d = type == TEX_1D or type == TEX_1D_ARRAY;
|
||||||
static constexpr GLboolean is_2d = sampled or is_rect or type == TEX_2D or type == TEX_2D_V or cubemap;
|
static constexpr GLboolean is_2d = sampled or is_rect or type == TEX_2D or type == TEX_2D_ARRAY or cubemap;
|
||||||
static constexpr GLboolean is_array = TypeV == TEX_1D_V or TypeV == TEX_2D_V or type == TEX_2D_MS_V or type == TEX_CUBEMAP_V;
|
static constexpr GLboolean is_array = TypeV == TEX_1D_ARRAY or TypeV == TEX_2D_ARRAY or type == TEX_2D_MS_ARRAY or type == TEX_CUBEMAP_ARRAY;
|
||||||
static constexpr GLboolean is_3d = TypeV == TEX_3D;
|
static constexpr GLboolean is_3d = TypeV == TEX_3D;
|
||||||
static constexpr GLboolean has_mipmaps = not(sampled or is_rect or is_buffered);
|
static constexpr GLboolean has_mipmaps = not(sampled or is_rect or is_buffered);
|
||||||
|
|
||||||
static constexpr GLboolean use_1d = is_1d and not is_array;
|
static constexpr GLboolean use_1d = is_1d and not is_array;
|
||||||
static constexpr GLboolean use_2d = (is_2d and not is_array) or (is_1d and is_array) and not sampled;
|
static constexpr GLboolean use_2d = ((is_2d and not is_array) or (is_1d and is_array)) and not sampled;
|
||||||
static constexpr GLboolean use_3d = is_3d or (is_2d and is_array) and not sampled and not cubemap;
|
static constexpr GLboolean use_3d = (is_3d or (is_2d and is_array)) and not (sampled or cubemap);
|
||||||
|
|
||||||
static constexpr GLint cubemap_faces = 6;
|
static constexpr GLint cubemap_faces = 6;
|
||||||
static constexpr GLenum base_cubemap_face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
static constexpr GLenum base_cubemap_face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
#include <fennec/containers/map.h>
|
#include <fennec/containers/map.h>
|
||||||
#include <fennec/containers/optional.h>
|
#include <fennec/containers/optional.h>
|
||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/langproc/strings/string.h>
|
||||||
#include <fennec/lang/typeuuid.h>
|
#include <fennec/lang/typed.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# 2D Graphics (`gfx2d`)
|
# 2D Graphics (`gfx2d`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
@@ -27,6 +29,11 @@ For the 2d rendering framework, Materials need to be rendered independently beca
|
|||||||
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.
|
||||||
|
|
||||||
|
I may have come up with a solution for the above problem. We can define software
|
||||||
|
subsections for images that are of differing size, then fit them to the optimal
|
||||||
|
texture array size. The textures will be centered in the storage, then have padding
|
||||||
|
that fits one of the wrapping models supported by samplers
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
struct Object
|
struct Object
|
||||||
{
|
{
|
||||||
@@ -62,3 +69,4 @@ struct Object
|
|||||||
- 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.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# 3D Graphics (`gfx3d`)
|
# 3D Graphics (`gfx3d`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
@@ -67,8 +69,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
|
`2:1`, and `4: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`. Same applies for `4:1`
|
||||||
Cubemaps and 3D textures may only be `1:1`.
|
Cubemaps and 3D textures may only be `1:1`.
|
||||||
|
|
||||||
- 8-Bit R Texture `4096, 2048, 1024, 512` (8)
|
- 8-Bit R Texture `4096, 2048, 1024, 512` (8)
|
||||||
@@ -170,12 +172,12 @@ Debug View: Visibility Buffer
|
|||||||
* S → used to represent the lighting model.
|
* S → used to represent the lighting model.
|
||||||
* Diffuse → `RGBA8`
|
* Diffuse → `RGBA8`
|
||||||
* A → Ambient Occlusion
|
* A → Ambient Occlusion
|
||||||
* Emission → `RGB8`
|
|
||||||
* Normal → `RGB8`
|
|
||||||
* Specular → `RGB8`
|
* Specular → `RGB8`
|
||||||
* R → Roughness
|
* R → Roughness
|
||||||
* G → Specularity (sometimes called the Metallicness)
|
* G → Specularity (sometimes called the Metallicity)
|
||||||
* B → Index of Refraction (IOR)
|
* B → Index of Refraction (IOR)
|
||||||
|
* Emission → `RGB8`
|
||||||
|
* Normal → `RGB8`
|
||||||
|
|
||||||
Debug View: Depth, Stencil, Diffuse, Emission, Normal, Specularity
|
Debug View: Depth, Stencil, Diffuse, Emission, Normal, Specularity
|
||||||
|
|
||||||
@@ -195,9 +197,9 @@ We can combine all of these into one framebuffer:
|
|||||||
- Depth - Stencil → `D24_S8`
|
- Depth - Stencil → `D24_S8`
|
||||||
- Visibility Info → `RGB32I`
|
- Visibility Info → `RGB32I`
|
||||||
- Diffuse → `RGBA8`
|
- Diffuse → `RGBA8`
|
||||||
|
- Specular → `RGB8`
|
||||||
- Emission → `RGB8`
|
- Emission → `RGB8`
|
||||||
- Normal → `RGB8`
|
- Normal → `RGB8`
|
||||||
- Specular → `RGB8`
|
|
||||||
- Lighting Buffer → `RGB16` w/ Mipmapping
|
- Lighting Buffer → `RGB16` w/ Mipmapping
|
||||||
- One more slot left open for another
|
- One more slot left open for another
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# 3D Physics (`physics3d`)
|
# 3D Physics (`physics3d`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# Artifical Intelligence (`ai`)
|
# Artifical Intelligence (`ai`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# Containers Library (`containers`)
|
# Containers Library (`containers`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# Planning Documentation for fennec
|
# Planning Documentation for fennec
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# C++ Language Library (`lang`)
|
# C++ Language Library (`lang`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
BIN
planning/ControlScene.ods
Normal file
BIN
planning/ControlScene.ods
Normal file
Binary file not shown.
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# fennec
|
# fennec
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# Language Processing Library (`langproc`)
|
# Language Processing Library (`langproc`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# Memory Library (`memory`)
|
# Memory Library (`memory`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
# Platform Support Library (`platform`)
|
# Platform Support Library (`platform`)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
@@ -20,6 +22,14 @@ to supporting various platforms. Platforms may be defined as any Hardware, OS, o
|
|||||||
Drivers that must be initialized for the engine context.
|
Drivers that must be initialized for the engine context.
|
||||||
|
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
  For the foreseeable future, I will be switching to SDL for window management.
|
||||||
|
SDL was chosen over GLFW due to GLFW's lack of support for Android and iOS. A custom
|
||||||
|
implementation is still something I would like to do, but is currently out of scope for
|
||||||
|
where I would like to focus my energy. As soon as SDL becomes
|
||||||
|
|
||||||
|
|
||||||
## Implementation
|
## Implementation
|
||||||
|
|
||||||
Platform Support will be implemented in the following order:
|
Platform Support will be implemented in the following order:
|
||||||
@@ -59,3 +69,56 @@ then support for other platforms will be resumed.
|
|||||||
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.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
We want this system to be fairly modular, renderers and their respective
|
||||||
|
gfxcontext implementation should be a drop-in, as well as window implementation.
|
||||||
|
This is a fairly complex problem to solve, especially since most display protocols
|
||||||
|
have their own specific implementation for supporting different contexts.
|
||||||
|
|
||||||
|
To illustrate this problem, let's say we have SDL and OpenGL implemented.
|
||||||
|
|
||||||
|
If we were to add Vulkan, there are Vulkan specific functions
|
||||||
|
for creating a window compatible with SDL, i.e. SDL_Vulkan_CreateSurface.
|
||||||
|
Who should know how to implement this function? How do we define the API
|
||||||
|
so that we do not have to modify existing classes to add Vulkan support?
|
||||||
|
|
||||||
|
The easiest solution to this problem is template functions. We can have a
|
||||||
|
template that takes a Renderer type as a template parameter, then initialize
|
||||||
|
the window for that. Now, if someone wants to create a Vulkan renderer, all they
|
||||||
|
have to do is write an overload for the template function. This can be neatly
|
||||||
|
wrapped up in a single C++ file. Only the gfxcontext implementation has to know
|
||||||
|
of this function's existence since it will be the one calling the function.
|
||||||
|
|
||||||
|
The main drawback with this implementation is an outside observer calling the
|
||||||
|
template function directly. Only the one C++ file knows of its existence. Template
|
||||||
|
functions are inlined after all. There are two options to solve this, the ``[[noinline]]``
|
||||||
|
attribute, or we simply scope protect the function and create it purely from a
|
||||||
|
"driver" standpoint. We can register drivers with the platform, then retrieve a
|
||||||
|
list of drivers with a specific type, e.g. glcontext, then the type aware implementation
|
||||||
|
is isolated to the C++ file associated with glcontext, and glcontext registers
|
||||||
|
itself with the platform. We can give drivers a priority so that Vulkan, a more
|
||||||
|
modern and "more powerful" renderer is chosen first, if available, and falls back
|
||||||
|
to OpenGL.
|
||||||
|
|
||||||
|
Now we run into the issue of, what if we want to implement Vulkan and Wayland separately?
|
||||||
|
These implementations will be part of the core engine, but let's take a more contrived
|
||||||
|
example; X-Box and Playstation. X-Box and Playstation have their own protocols for
|
||||||
|
display rendering, but both use DirectX. Say someone implements a DirectX api for Desktop
|
||||||
|
computers, then someone else implements a windowing system for X-Box or Playstation.
|
||||||
|
If another user wants to use DirectX with X-Box/Playstation, they will have to write
|
||||||
|
their own overloads for that implementation.
|
||||||
|
|
||||||
|
The only viable solution for this problem is to rely on the Open Source community.
|
||||||
|
Pray that someone finds both engine extensions and writes the overloads for you.
|
||||||
|
This might sound very familiar to modders, and this is my intention with this engine.
|
||||||
|
Pieces should be modular, and should be easily connected when two non-dependent systems
|
||||||
|
have underlying interdependencies.
|
||||||
|
|
||||||
|
There is one more option that I have come up with; mapping type ids. The implementation
|
||||||
|
of typed.h generates type ids *at runtime* which allows us to map a pair of ids for this
|
||||||
|
purpose. We can use a pair of window and gfxcontext uuids to determine the loading functions.
|
||||||
|
All we would need to do is register a function that takes a window as an arguments and
|
||||||
|
constructs the gfxcontext. We can combine this with the above to allow scoped access to
|
||||||
|
the classes if that is needed.
|
||||||
|
|||||||
26
planning/RENDERERS.md
Normal file
26
planning/RENDERERS.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
<!-- I release these notes into the public domain -->
|
||||||
|
|
||||||
|
# Renderers (`renderers`)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
  This library contains headers and classes related to creating renderers
|
||||||
|
that wrap various graphics pipelines, e.g. OpenGL & Vulkan.
|
||||||
|
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
OpenGL will be implemented first for prototyping, then Vulkan will
|
||||||
|
be implemented. These will be the first two renderers with official
|
||||||
|
support. OpenGL will be implemented twice, one targeting modern features,
|
||||||
|
and a fallback targeting OpenGL 4.3 / GLES 3.2.
|
||||||
|
|
||||||
|
OpenGL will be wrapped in a manner that reflects the Vulkan API. This
|
||||||
|
will help achieve higher performance with driver usage in OpenGL, and
|
||||||
|
it will make building pipelines on top of OpenGL easier. This will also
|
||||||
|
give the advantage of a cleaner porting process when writing the Vulkan
|
||||||
|
pipeline.
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <bits/posix2_lim.h>
|
||||||
|
|
||||||
#include <fennec/langproc/filesystem/file.h>
|
#include <fennec/langproc/filesystem/file.h>
|
||||||
#include <fennec/langproc/filesystem/path.h>
|
#include <fennec/langproc/filesystem/path.h>
|
||||||
@@ -921,7 +922,7 @@ bool file::eof() const {
|
|||||||
|
|
||||||
char file::getc() {
|
char file::getc() {
|
||||||
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
||||||
assert(not(_mode & fmode_wide), "Attempted Byte Operation on Wide File");
|
assert(not(_mode & fmode_wide), "Attempted Wide Operation on Byte File");
|
||||||
|
|
||||||
// Check if there is a file
|
// Check if there is a file
|
||||||
if (_handle == nullptr) {
|
if (_handle == nullptr) {
|
||||||
@@ -933,7 +934,7 @@ char file::getc() {
|
|||||||
|
|
||||||
wchar_t file::getwc() {
|
wchar_t file::getwc() {
|
||||||
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
||||||
assert(_mode & fmode_wide, "Attempted Wide Operation on Byte File");
|
assert(_mode & fmode_wide, "Attempted Byte Operation on Wide File");
|
||||||
|
|
||||||
// Check if there is a file
|
// Check if there is a file
|
||||||
if (_handle == nullptr) {
|
if (_handle == nullptr) {
|
||||||
@@ -959,92 +960,6 @@ size_t file::read(void* data, size_t size, size_t n) {
|
|||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
string file::getline() {
|
|
||||||
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
|
||||||
assert(not(_mode & fmode_wide), "Attempted Byte Operation on Wide File");
|
|
||||||
|
|
||||||
// Check if there is a file
|
|
||||||
if (_handle == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the next line;
|
|
||||||
char* line = nullptr;
|
|
||||||
size_t size = 0;
|
|
||||||
const size_t read = ::getline(&line, &size, _handle);
|
|
||||||
if (read == npos && ferror(_handle)) {
|
|
||||||
_error = strerror(errno);
|
|
||||||
if (line) free(line);
|
|
||||||
return string("");
|
|
||||||
}
|
|
||||||
|
|
||||||
string res = string(line, read);
|
|
||||||
free(line);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
wstring file::getwline() {
|
|
||||||
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
|
||||||
assert(_mode & fmode_wide, "Attempted Wide Operation on Byte File");
|
|
||||||
|
|
||||||
// Check if there is a file
|
|
||||||
if (_handle == nullptr) {
|
|
||||||
return _wstring{ L"" };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the next line;
|
|
||||||
wchar_t arr[257] = { L'\0' };
|
|
||||||
wcstring buff = arr;
|
|
||||||
wstring res{L""};
|
|
||||||
|
|
||||||
// read until first newline or end of file
|
|
||||||
while (fgetws(arr, 257, _handle)) {
|
|
||||||
res += wcstring(arr, buff.length());
|
|
||||||
if (buff.length() < 256 || buff[256] == L'\n') {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_error = strerror(errno);
|
|
||||||
return wstring(L"");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool file::putc(char c) {
|
|
||||||
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
|
||||||
assert(not(_mode & fmode_wide), "Attempted Byte Operation on Wide File");
|
|
||||||
|
|
||||||
// Check if there is a file
|
|
||||||
if (_handle == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int res;
|
|
||||||
if ((res = fputc(c, _handle)) != c && res != EOF) {
|
|
||||||
_error = strerror(errno);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool file::putwc(wchar_t c) {
|
|
||||||
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
|
||||||
assert(_mode & fmode_wide, "Attempted Wide Operation on Byte File");
|
|
||||||
|
|
||||||
// Check if there is a file
|
|
||||||
if (_handle == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int res;
|
|
||||||
if ((res = fputc(c, _handle)) != c && res != EOF) {
|
|
||||||
_error = strerror(errno);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t file::write(const void* data, size_t size, size_t n) {
|
size_t file::write(const void* data, size_t size, size_t n) {
|
||||||
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
||||||
|
|
||||||
@@ -1063,4 +978,92 @@ size_t file::write(const void* data, size_t size, size_t n) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string file::getline() {
|
||||||
|
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
||||||
|
assert(not(_mode & fmode_wide), "Attempted Wide Operation on Byte File");
|
||||||
|
|
||||||
|
// Check if there is a file
|
||||||
|
if (_handle == nullptr) {
|
||||||
|
return string{ "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next line;
|
||||||
|
char arr[LINE_MAX + 2] = { L'\0' };
|
||||||
|
cstring buff = arr;
|
||||||
|
string res{""};
|
||||||
|
|
||||||
|
// read until first newline or end of file
|
||||||
|
while (fgets(arr, LINE_MAX + 2, _handle)) {
|
||||||
|
res += cstring(arr, buff.length());
|
||||||
|
if (buff.length() < LINE_MAX || buff[LINE_MAX] == L'\n') {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_error = strerror(errno);
|
||||||
|
return string("");
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring file::getwline() {
|
||||||
|
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
||||||
|
assert(_mode & fmode_wide, "Attempted Byte Operation on Wide File");
|
||||||
|
|
||||||
|
// Check if there is a file
|
||||||
|
if (_handle == nullptr) {
|
||||||
|
return _wstring{ L"" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next line;
|
||||||
|
wchar_t arr[LINE_MAX + 2] = { L'\0' };
|
||||||
|
wcstring buff = arr;
|
||||||
|
wstring res{L""};
|
||||||
|
|
||||||
|
// read until first newline or end of file
|
||||||
|
while (fgetws(arr, LINE_MAX + 2, _handle)) {
|
||||||
|
res += wcstring(arr, buff.length());
|
||||||
|
if (buff.length() < LINE_MAX || buff[LINE_MAX] == L'\n') {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_error = strerror(errno);
|
||||||
|
return wstring(L"");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool file::putc(char c) {
|
||||||
|
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
||||||
|
assert(not(_mode & fmode_wide), "Attempted Wide Operation on Byte File");
|
||||||
|
|
||||||
|
// Check if there is a file
|
||||||
|
if (_handle == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res;
|
||||||
|
if ((res = fputc(c, _handle)) != c && res != EOF) {
|
||||||
|
_error = strerror(errno);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool file::putwc(wchar_t c) {
|
||||||
|
assert(_error == nullptr, "Attempted an Operation on a File in an Errored State");
|
||||||
|
assert(_mode & fmode_wide, "Attempted Byte Operation on Wide File");
|
||||||
|
|
||||||
|
// Check if there is a file
|
||||||
|
if (_handle == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res;
|
||||||
|
if ((res = fputc(c, _handle)) != c && res != EOF) {
|
||||||
|
_error = strerror(errno);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
// 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/interface/display.h>
|
|
||||||
#include <fennec/platform/interface/platform.h>
|
#include <fennec/platform/interface/platform.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
@@ -37,42 +36,17 @@ static constexpr void insert_driver(list<platform::driver<CtorT>>& drvrs, CtorT
|
|||||||
}
|
}
|
||||||
|
|
||||||
void platform::initialize() {
|
void platform::initialize() {
|
||||||
load_display();
|
|
||||||
_display->select_context();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform::shutdown() {
|
void platform::shutdown() {
|
||||||
delete _display;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform::load_display() {
|
window* platform::create_window(const window::config&) {
|
||||||
auto& globals = _get_globals();
|
return nullptr;
|
||||||
for (auto it : globals.displays) {
|
|
||||||
_display = it.constructor(this);
|
|
||||||
if (_display != nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform::add_driver(display_ctor ctor, int priority) {
|
void platform::register_window_driver(window_driver&& driver) {
|
||||||
auto& globals = _get_globals();
|
globals.windows.insert(fennec::forward<window_driver>(driver));
|
||||||
insert_driver(globals.displays, ctor, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
void platform::add_driver(input_ctor ctor, int priority) {
|
|
||||||
auto& globals = _get_globals();
|
|
||||||
insert_driver(globals.inputs, ctor, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
void platform::add_driver(gfxctx_ctor ctor, int priority) {
|
|
||||||
auto& globals = _get_globals();
|
|
||||||
insert_driver(globals.graphics, ctor, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
platform::global_context& platform::_get_globals() {
|
|
||||||
static global_context ctx;
|
|
||||||
return ctx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -29,11 +29,9 @@ STATIC_CONSTRUCTOR(_init_linux) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void linux_platform::initialize() {
|
void linux_platform::initialize() {
|
||||||
platform::initialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void linux_platform::shutdown() {
|
void linux_platform::shutdown() {
|
||||||
platform::shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,140 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
#include <fennec/platform/linux/wayland/display.h>
|
|
||||||
#include <fennec/platform/linux/wayland/lib/loader.h>
|
|
||||||
#include <fennec/platform/linux/wayland/lib/wayland.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
|
|
||||||
{
|
|
||||||
|
|
||||||
static display* _create_wayland_display(platform* platform) {
|
|
||||||
wayland_display* display = new wayland_display(platform);
|
|
||||||
if (not display->connected()) {
|
|
||||||
delete display, display = nullptr;
|
|
||||||
}
|
|
||||||
return display;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC_CONSTRUCTOR(_wayland_init) {
|
|
||||||
platform::add_driver(_create_wayland_display, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
wayland_display::wayland_display(platform* platform)
|
|
||||||
: display(platform, "wayland", this)
|
|
||||||
, _handle(nullptr)
|
|
||||||
, _registry(nullptr)
|
|
||||||
, _compositor(nullptr)
|
|
||||||
, _seat(nullptr)
|
|
||||||
, _shm(nullptr)
|
|
||||||
, _fifo(false) {
|
|
||||||
|
|
||||||
static constexpr wl_registry_listener listener = {
|
|
||||||
listen_global, listen_global_remove
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load libwayland.so
|
|
||||||
libwayland::load_symbols(_platform);
|
|
||||||
|
|
||||||
// Get handles
|
|
||||||
_handle = wl_display_connect(nullptr);
|
|
||||||
if (not _handle) {
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the wayland registry
|
|
||||||
_registry = wl_display_get_registry(_handle);
|
|
||||||
if (not _registry) {
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add listener for interfaces
|
|
||||||
wl_registry_add_listener(_registry, &listener, this);
|
|
||||||
wl_display_roundtrip(_handle);
|
|
||||||
|
|
||||||
// Check for fifo v1, wayland's builtin fifo only allows one frame to be in flight at a time
|
|
||||||
if (not _fifo) {
|
|
||||||
assert(_fifo, "Compositor does not support fifo-v1 protocol, falling back to other display protocols.");
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wayland_display::~wayland_display() {
|
|
||||||
if (_handle) {
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wayland_display::connected() const {
|
|
||||||
return _handle != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
window* wayland_display::create_window(window* parent) {
|
|
||||||
return new wayland_window(this, static_cast<wayland_window*>(parent));
|
|
||||||
}
|
|
||||||
|
|
||||||
void wayland_display::cleanup() {
|
|
||||||
|
|
||||||
// Cleanup members
|
|
||||||
if (_compositor) wl_compositor_destroy(_compositor);
|
|
||||||
if (_registry) wl_registry_destroy(_registry);
|
|
||||||
if (_handle) {
|
|
||||||
wl_display_flush(_handle);
|
|
||||||
wl_display_disconnect(_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
_compositor = nullptr;
|
|
||||||
_registry = nullptr;
|
|
||||||
_handle = nullptr;
|
|
||||||
|
|
||||||
libwayland::unload_symbols(_platform);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wayland_display::listen_global(void* data, wl_registry* registry, uint32_t name, const char* itfc, uint32_t version) {
|
|
||||||
static constexpr wl_seat_listener seat_listener = {
|
|
||||||
listen_seat, nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
wayland_display* device = static_cast<wayland_display*>(data);
|
|
||||||
const cstring interface = cstring(itfc, strlen(itfc) + 1);
|
|
||||||
|
|
||||||
if (interface == "wl_compositor") {
|
|
||||||
device->_compositor = static_cast<wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, version));
|
|
||||||
} else if (interface == "wl_seat") {
|
|
||||||
device->_seat = static_cast<wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, version));
|
|
||||||
wl_seat_add_listener(device->_seat, &seat_listener, device);
|
|
||||||
} else if (interface == "wp_fifo_manager_v1") {
|
|
||||||
device->_fifo = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void wayland_display::listen_global_remove(void*, wl_registry*, uint32_t) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void wayland_display::listen_seat(void*, wl_seat*, uint32_t) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,86 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
#include <fennec/platform/linux/wayland/lib/headers/wayland-client-protocols.h>
|
|
||||||
#include <fennec/platform/linux/wayland/lib/loader.h>
|
|
||||||
|
|
||||||
#define FENNEC_LIB(name) bool FENNEC_HAS_LIB_##name;
|
|
||||||
#define FENNEC_SYMBOL(ret, fn, ...) using WAYLAND_sym_##fn = ret(*)(__VA_ARGS__); \
|
|
||||||
WAYLAND_sym_##fn WAYLAND_##fn;
|
|
||||||
#define FENNEC_GLOBAL(type, name) type* WAYLAND_##name;
|
|
||||||
#include <fennec/platform/linux/wayland/lib/sym.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace libwayland
|
|
||||||
{
|
|
||||||
|
|
||||||
using shared_object = platform::shared_object;
|
|
||||||
|
|
||||||
struct shared_lib {
|
|
||||||
shared_object* obj;
|
|
||||||
const cstring name;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int _load_count = 0;
|
|
||||||
|
|
||||||
// Create private variables
|
|
||||||
#define FENNEC_LIB(lib) static shared_lib _FENNEC_LIB_##lib = { nullptr, FENNEC_LIB_##lib };
|
|
||||||
#include <fennec/platform/linux/wayland/lib/sym.h>
|
|
||||||
|
|
||||||
bool load_symbols(platform* platform) {
|
|
||||||
if (_load_count++ != 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_lib* current_lib = nullptr;
|
|
||||||
#define FENNEC_LIB(lib) _FENNEC_LIB_##lib.obj = platform->load_object(_FENNEC_LIB_##lib.name); \
|
|
||||||
FENNEC_HAS_LIB_##lib = _FENNEC_LIB_##lib.obj != nullptr; \
|
|
||||||
if(not FENNEC_HAS_LIB_##lib) { \
|
|
||||||
unload_symbols(platform); \
|
|
||||||
return false; \
|
|
||||||
} \
|
|
||||||
current_lib = &_FENNEC_LIB_##lib;
|
|
||||||
#define FENNEC_SYMBOL(ret, fn, ...) WAYLAND_##fn = (WAYLAND_sym_##fn)(platform->find_symbol(current_lib->obj, #fn)); \
|
|
||||||
assertf(WAYLAND_##fn != nullptr, "Failed to find symbol: " #fn);
|
|
||||||
#define FENNEC_GLOBAL(type, name) WAYLAND_##name = (type*)(platform->find_symbol(current_lib->obj, #name)); \
|
|
||||||
assertf(WAYLAND_##name != nullptr, "Failed to find global: " #name);
|
|
||||||
#include <fennec/platform/linux/wayland/lib/sym.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unload_symbols(platform* platform) {
|
|
||||||
if (--_load_count != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FENNEC_LIB(lib) platform->unload_object(_FENNEC_LIB_##lib.obj); \
|
|
||||||
_FENNEC_LIB_##lib.obj = nullptr;
|
|
||||||
#define FENNEC_SYMBOL(ret, fn, ...) WAYLAND_##fn = nullptr;
|
|
||||||
#define FENNEC_GLOBAL(type, name) WAYLAND_##name = nullptr;
|
|
||||||
#include <fennec/platform/linux/wayland/lib/sym.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,139 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
#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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,87 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
#include <fennec/platform/linux/xkb/lib/xkb.h>
|
|
||||||
#include <fennec/platform/linux/xkb/lib/loader.h>
|
|
||||||
#include <fennec/platform/interface/platform.h>
|
|
||||||
|
|
||||||
#define FENNEC_LIB(name) bool FENNEC_HAS_LIB_##name;
|
|
||||||
#define FENNEC_SYMBOL(ret, fn, ...) using XKB_sym_##fn = ret(*)(__VA_ARGS__); \
|
|
||||||
XKB_sym_##fn XKB_##fn;
|
|
||||||
#define FENNEC_GLOBAL(type, name) type* XKB_##name;
|
|
||||||
#include <fennec/platform/linux/xkb/lib/sym.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace libxkbcommon
|
|
||||||
{
|
|
||||||
|
|
||||||
using shared_object = platform::shared_object;
|
|
||||||
|
|
||||||
struct shared_lib {
|
|
||||||
shared_object* obj;
|
|
||||||
const cstring name;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int _load_count = 0;
|
|
||||||
|
|
||||||
// Create private variables
|
|
||||||
#define FENNEC_LIB(lib) static shared_lib _FENNEC_LIB_##lib = { nullptr, FENNEC_LIB_##lib };
|
|
||||||
#include <fennec/platform/linux/xkb/lib/sym.h>
|
|
||||||
|
|
||||||
bool load_symbols(platform* platform) {
|
|
||||||
if (_load_count++ != 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_lib* current_lib = nullptr;
|
|
||||||
#define FENNEC_LIB(lib) _FENNEC_LIB_##lib.obj = platform->load_object(_FENNEC_LIB_##lib.name); \
|
|
||||||
FENNEC_HAS_LIB_##lib = _FENNEC_LIB_##lib.obj != nullptr; \
|
|
||||||
if(not FENNEC_HAS_LIB_##lib) { \
|
|
||||||
unload_symbols(platform); \
|
|
||||||
return false; \
|
|
||||||
} \
|
|
||||||
current_lib = &_FENNEC_LIB_##lib;
|
|
||||||
#define FENNEC_SYMBOL(ret, fn, ...) XKB_##fn = (XKB_sym_##fn)(platform->find_symbol(current_lib->obj, #fn)); \
|
|
||||||
assertf(XKB_##fn != nullptr, "Failed to find symbol: " #fn);
|
|
||||||
#define FENNEC_GLOBAL(type, name) XKB_##name = (type*)(platform->find_symbol(current_lib->obj, #name)); \
|
|
||||||
assertf(XKB_##name != nullptr, "Failed to find global: " #name);
|
|
||||||
#include <fennec/platform/linux/xkb/lib/sym.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unload_symbols(platform* platform) {
|
|
||||||
if (--_load_count != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FENNEC_LIB(lib) platform->unload_object(_FENNEC_LIB_##lib.obj); \
|
|
||||||
_FENNEC_LIB_##lib.obj = nullptr;
|
|
||||||
#define FENNEC_SYMBOL(ret, fn, ...) XKB_##fn = nullptr;
|
|
||||||
#define FENNEC_GLOBAL(type, name) XKB_##name = nullptr;
|
|
||||||
#include <fennec/platform/linux/xkb/lib/sym.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,166 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
#include <fennec/langproc/filesystem/file.h>
|
|
||||||
#include <fennec/lang/startup.h>
|
|
||||||
#include <fennec/platform/interface/display.h>
|
|
||||||
#include <fennec/platform/interface/platform.h>
|
|
||||||
#include <fennec/platform/opengl/egl/context.h>
|
|
||||||
#include <fennec/platform/opengl/egl/surface.h>
|
|
||||||
|
|
||||||
#include <GL/gl.h>
|
|
||||||
|
|
||||||
namespace fennec
|
|
||||||
{
|
|
||||||
|
|
||||||
static gfxcontext* _create_egl_context(display* display) {
|
|
||||||
eglcontext* ctx = new eglcontext(display);
|
|
||||||
if (not ctx->connected()) {
|
|
||||||
delete ctx, ctx = nullptr;
|
|
||||||
}
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC_CONSTRUCTOR(_egl_init) {
|
|
||||||
platform::add_driver(_create_egl_context, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
eglcontext::eglcontext(display* display)
|
|
||||||
: gfxcontext(display, "EGL", this)
|
|
||||||
, _egldisplay(nullptr), _eglcontext(nullptr)
|
|
||||||
, _eglconfig(), _eglvmajor(0), _eglvminor(0)
|
|
||||||
, _eglctype(0), _extensions(nullptr) {
|
|
||||||
|
|
||||||
// Get the display format
|
|
||||||
const display::pixel_format& fmt = _display->get_color_format();
|
|
||||||
|
|
||||||
// Currently empty
|
|
||||||
EGLint context_attrs[] = {
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
// Configure the depth and rgb bit-depth
|
|
||||||
EGLint config_attrs[] = {
|
|
||||||
EGL_SURFACE_TYPE,
|
|
||||||
EGL_WINDOW_BIT,
|
|
||||||
EGL_DEPTH_SIZE, fmt.depth,
|
|
||||||
EGL_RED_SIZE, fmt.r,
|
|
||||||
EGL_RED_SIZE, fmt.g,
|
|
||||||
EGL_RED_SIZE, fmt.b,
|
|
||||||
|
|
||||||
EGL_RENDERABLE_TYPE,
|
|
||||||
EGL_OPENGL_BIT, // 7
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
// Attempt to retrieve an egl display from the native display
|
|
||||||
_egldisplay = eglGetDisplay(_display->get_native_handle());
|
|
||||||
if (_egldisplay == nullptr) {
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to initialize egl
|
|
||||||
if (not eglInitialize(_egldisplay, nullptr, nullptr)) {
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to bind to Core OpenGL, otherwise OpenGL ES
|
|
||||||
if (not eglBindAPI(EGL_OPENGL_API)) {
|
|
||||||
if (not eglBindAPI(EGL_OPENGL_ES_API)) {
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
config_attrs[7] = EGL_OPENGL_ES_BIT; // Change the support bit to OpenGL ES
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select a configuration
|
|
||||||
EGLint n;
|
|
||||||
if (not eglChooseConfig(_egldisplay, config_attrs, &_eglconfig, 1, &n)) {
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the context
|
|
||||||
_eglcontext = eglCreateContext(_egldisplay, _eglconfig, EGL_NO_CONTEXT, context_attrs);
|
|
||||||
if (_eglcontext == nullptr) {
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make this the current context so we can retrieve the information below
|
|
||||||
eglMakeCurrent(_egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, _eglcontext);
|
|
||||||
|
|
||||||
// Query available extensions
|
|
||||||
const char* ptr = eglQueryString(_egldisplay, EGL_EXTENSIONS);
|
|
||||||
_extensions = { ptr, strlen(ptr) + 1 };
|
|
||||||
|
|
||||||
// Query the context and version
|
|
||||||
eglQueryContext(_egldisplay, _eglcontext, EGL_CONTEXT_CLIENT_TYPE, &_eglctype);
|
|
||||||
glGetIntegerv(GL_MAJOR_VERSION, &_eglvmajor);
|
|
||||||
glGetIntegerv(GL_MINOR_VERSION, &_eglvminor);
|
|
||||||
}
|
|
||||||
|
|
||||||
eglcontext::~eglcontext() {
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eglcontext::connected() {
|
|
||||||
return _eglcontext != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cstring& eglcontext::get_name() {
|
|
||||||
static constexpr cstring opengl = "OpenGL";
|
|
||||||
static constexpr cstring gles = "GLES";
|
|
||||||
static constexpr cstring openvg = "OpenVG"; // this should never be used
|
|
||||||
switch (_eglctype) {
|
|
||||||
default:
|
|
||||||
case EGL_OPENGL_API: return opengl;
|
|
||||||
case EGL_OPENGL_ES_API: return gles;
|
|
||||||
case EGL_OPENVG_API: return openvg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eglcontext::check_extension(const cstring& ext) {
|
|
||||||
return _extensions.find(ext) != _extensions.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
||||||
eglDestroyContext(_display, _eglcontext);
|
|
||||||
eglTerminate(_display);
|
|
||||||
eglReleaseThread();
|
|
||||||
|
|
||||||
_egldisplay = nullptr;
|
|
||||||
_eglconfig = nullptr;
|
|
||||||
_eglcontext = nullptr;
|
|
||||||
_eglvmajor = 0;
|
|
||||||
_eglvminor = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,66 +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/>.
|
|
||||||
// =====================================================================================================================
|
|
||||||
|
|
||||||
#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!"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,8 @@ set(CMAKE_C_STANDARD 23)
|
|||||||
add_executable(fennec-test
|
add_executable(fennec-test
|
||||||
main.cpp
|
main.cpp
|
||||||
tests/containers/performance/test_iterator_visitor.h
|
tests/containers/performance/test_iterator_visitor.h
|
||||||
|
tests/containers/test_sequence.h
|
||||||
|
tests/langproc/test_format.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}"
|
target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \file surface.h
|
/// \file test_sequence.h
|
||||||
/// \brief
|
/// \brief
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -28,33 +28,37 @@
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
|
#ifndef FENNEC_TEST_CONTAINERS_SEQUENCE_H
|
||||||
#define FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
|
#define FENNEC_TEST_CONTAINERS_SEQUENCE_H
|
||||||
|
#include <fennec/containers/sequence.h>
|
||||||
#include <fennec/platform/interface/gfxsurface.h>
|
|
||||||
#include <fennec/platform/linux/wayland/window.h>
|
|
||||||
#include <fennec/platform/opengl/egl/context.h>
|
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class eglsurface : public gfxsurface {
|
namespace test
|
||||||
public:
|
{
|
||||||
~eglsurface() override;
|
|
||||||
|
|
||||||
void resize(size_t width, size_t height) override;
|
inline void fennec_test_containers_sequence() {
|
||||||
|
dynarray<size_t> ref;
|
||||||
|
sequence<size_t> test;
|
||||||
|
const size_t n = 50;
|
||||||
|
|
||||||
eglsurface(eglcontext* context, window* window);
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
size_t v = rand();
|
||||||
EGLSurface get_egl_surface() {
|
ref.push_back(v);
|
||||||
return _surface;
|
test.insert(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
for (size_t v : ref) {
|
||||||
void* _handle;
|
assertf(test.contains(v), "Failed Sequence Test!");
|
||||||
EGLSurface _surface;
|
test.erase(v);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
fennec_test_run(test.empty(), true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_TEST_CONTAINERS_SEQUENCE_H
|
||||||
@@ -16,27 +16,48 @@
|
|||||||
// 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/interface/display.h>
|
///
|
||||||
#include <fennec/platform/interface/gfxcontext.h>
|
/// \file test_format.h
|
||||||
#include <fennec/platform/interface/platform.h>
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_TEST_LANGPROC_FORMAT_H
|
||||||
|
#define FENNEC_TEST_LANGPROC_FORMAT_H
|
||||||
|
#include <fennec/langproc/format/tokenizer.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
display::~display() {
|
namespace test
|
||||||
delete _context;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
void display::select_context() {
|
inline void fennec_test_langproc_format() {
|
||||||
if (_context != nullptr) return;
|
|
||||||
|
|
||||||
const platform::global_context& globals = platform::get_globals();
|
tokenizer math = {
|
||||||
for (const auto& ctx : globals.graphics) {
|
.delimiter { " " },
|
||||||
_context = ctx.constructor(this);
|
.operators {"+-/*="},
|
||||||
if (_context) {
|
.braces { "()" },
|
||||||
return;
|
.escapes { "" },
|
||||||
}
|
.terminator { "" },
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto res = math.parse("1 + 2 = 3");
|
||||||
|
fennec_test_run(res.size(), size_t(5));
|
||||||
|
|
||||||
|
for (const auto& token : res) {
|
||||||
|
std::cout << token.second << ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_TEST_LANGPROC_FORMAT_H
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "containers/test_object_pool.h"
|
#include "containers/test_object_pool.h"
|
||||||
#include "containers/test_optional.h"
|
#include "containers/test_optional.h"
|
||||||
#include "containers/test_rdtree.h"
|
#include "containers/test_rdtree.h"
|
||||||
|
#include "containers/test_sequence.h"
|
||||||
#include "containers/test_set.h"
|
#include "containers/test_set.h"
|
||||||
#include "containers/test_tuple.h"
|
#include "containers/test_tuple.h"
|
||||||
|
|
||||||
@@ -71,6 +72,11 @@ namespace fennec::test
|
|||||||
fennec_test_containers_set();
|
fennec_test_containers_set();
|
||||||
fennec_test_spacer(3);
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
|
fennec_test_subheader("sequence tests");
|
||||||
|
fennec_test_spacer(2);
|
||||||
|
fennec_test_containers_sequence();
|
||||||
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
fennec_test_subheader("map tests");
|
fennec_test_subheader("map tests");
|
||||||
fennec_test_spacer(2);
|
fennec_test_spacer(2);
|
||||||
fennec_test_containers_map();
|
fennec_test_containers_map();
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "./langproc/test_strings.h"
|
#include "./langproc/test_strings.h"
|
||||||
#include "./langproc/test_io.h"
|
#include "./langproc/test_io.h"
|
||||||
|
#include "langproc/test_format.h"
|
||||||
|
|
||||||
namespace fennec::test
|
namespace fennec::test
|
||||||
{
|
{
|
||||||
@@ -33,6 +34,11 @@ namespace fennec::test
|
|||||||
fennec_test_langproc_strings();
|
fennec_test_langproc_strings();
|
||||||
fennec_test_spacer(3);
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
|
fennec_test_header("format");
|
||||||
|
fennec_test_spacer(2);
|
||||||
|
fennec_test_langproc_format();
|
||||||
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
fennec_test_header("io");
|
fennec_test_header("io");
|
||||||
fennec_test_spacer(2);
|
fennec_test_spacer(2);
|
||||||
fennec_test_langproc_io();
|
fennec_test_langproc_io();
|
||||||
|
|||||||
@@ -21,8 +21,6 @@
|
|||||||
|
|
||||||
#include "../test.h"
|
#include "../test.h"
|
||||||
|
|
||||||
#include <fennec/platform/interface/display.h>
|
|
||||||
#include <fennec/platform/interface/gfxcontext.h>
|
|
||||||
#include <fennec/platform/interface/platform.h>
|
#include <fennec/platform/interface/platform.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -31,37 +29,6 @@ namespace fennec::test
|
|||||||
|
|
||||||
inline void fennec_test_platform() {
|
inline void fennec_test_platform() {
|
||||||
|
|
||||||
platform* instance = platform::instance();
|
|
||||||
instance->initialize();
|
|
||||||
|
|
||||||
display* display = instance->get_display();
|
|
||||||
|
|
||||||
fennec_test_run(display != nullptr, true);
|
|
||||||
fennec_test_run(display->get_context() != nullptr, true);
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user