- More Documentation

- Vulkan Configuration Implementations
 - Fixed build errors on GCC and Clang
This commit is contained in:
2026-07-18 23:48:00 -04:00
parent ed381c4178
commit cf909624df
164 changed files with 19857 additions and 5872 deletions

View File

@@ -33,7 +33,7 @@ void platform::initialize() {
return;
}
logger::log(format("Initializing platform {}", get_type().name()));
logger::log(logger::alert, format("Initializing platform {}", get_type().name()));
// Setup Window Manager
wmanager = make_unique<window_manager>(this);

View File

@@ -25,12 +25,15 @@ namespace fennec
window::window(display_server* server, const config& conf, window* parent)
: server(server), parent(parent)
, root(parent ? parent : this)
, root([&]() -> auto {
window* rt = parent ? parent : this;
while (rt->get_parent() != nullptr and rt->is_popup()) {
rt = root->get_parent();
}
return rt;
}())
, cfg(conf), state() {
state.mode = conf.mode;
while (root->get_parent() != nullptr and root->is_popup()) {
root = root->get_parent();
}
// if parent is null, root will point to this
assertf(root != nullptr, "Failed to find appropriate top-level window.");

View File

@@ -32,15 +32,14 @@ wayland_eglsurface::wayland_eglsurface(wayland_window* win, eglcontext* ctx)
win->get_config().rect.size.x, win->get_config().rect.size.y
)
) {
}
wayland_eglsurface::~wayland_eglsurface() {
wl_egl_window_destroy(reinterpret_cast<wl_egl_window*>(_eglwindow));
wl_egl_window_destroy(static_cast<wl_egl_window*>(_eglwindow));
}
void wayland_eglsurface::resize(const ivec2& size) {
wl_egl_window_resize(reinterpret_cast<wl_egl_window*>(_eglwindow), size.x, size.y, 0, 0);
wl_egl_window_resize(static_cast<wl_egl_window*>(_eglwindow), size.x, size.y, 0, 0);
}
}

View File

@@ -1,4 +1,4 @@
/* Generated by wayland-scanner 1.24.0 */
/* Generated by wayland-scanner 1.25.0 */
/*
* Copyright © 2008-2011 Kristian Høgsberg
@@ -124,6 +124,7 @@ static const struct wl_interface *wayland_types[] = {
&wl_callback_interface,
&wl_region_interface,
&wl_region_interface,
&wl_callback_interface,
&wl_output_interface,
&wl_output_interface,
&wl_pointer_interface,
@@ -202,11 +203,12 @@ WL_PRIVATE const struct wl_interface wl_callback_interface = {
static const struct wl_message wl_compositor_requests[] = {
{ "create_surface", "n", wayland_types + 10 },
{ "create_region", "n", wayland_types + 11 },
{ "release", "7", wayland_types + 0 },
};
WL_PRIVATE const struct wl_interface wl_compositor_interface = {
"wl_compositor", 6,
2, wl_compositor_requests,
"wl_compositor", 7,
3, wl_compositor_requests,
0, NULL,
};
@@ -266,7 +268,7 @@ static const struct wl_message wl_data_offer_events[] = {
};
WL_PRIVATE const struct wl_interface wl_data_offer_interface = {
"wl_data_offer", 3,
"wl_data_offer", 4,
5, wl_data_offer_requests,
3, wl_data_offer_events,
};
@@ -287,7 +289,7 @@ static const struct wl_message wl_data_source_events[] = {
};
WL_PRIVATE const struct wl_interface wl_data_source_interface = {
"wl_data_source", 3,
"wl_data_source", 4,
3, wl_data_source_requests,
6, wl_data_source_events,
};
@@ -308,7 +310,7 @@ static const struct wl_message wl_data_device_events[] = {
};
WL_PRIVATE const struct wl_interface wl_data_device_interface = {
"wl_data_device", 3,
"wl_data_device", 4,
3, wl_data_device_requests,
6, wl_data_device_events,
};
@@ -316,11 +318,12 @@ WL_PRIVATE const struct wl_interface wl_data_device_interface = {
static const struct wl_message wl_data_device_manager_requests[] = {
{ "create_data_source", "n", wayland_types + 34 },
{ "get_data_device", "no", wayland_types + 35 },
{ "release", "4", wayland_types + 0 },
};
WL_PRIVATE const struct wl_interface wl_data_device_manager_interface = {
"wl_data_device_manager", 3,
2, wl_data_device_manager_requests,
"wl_data_device_manager", 4,
3, wl_data_device_manager_requests,
0, NULL,
};
@@ -371,25 +374,26 @@ static const struct wl_message wl_surface_requests[] = {
{ "set_buffer_scale", "3i", wayland_types + 0 },
{ "damage_buffer", "4iiii", wayland_types + 0 },
{ "offset", "5ii", wayland_types + 0 },
{ "get_release", "7n", wayland_types + 64 },
};
static const struct wl_message wl_surface_events[] = {
{ "enter", "o", wayland_types + 64 },
{ "leave", "o", wayland_types + 65 },
{ "enter", "o", wayland_types + 65 },
{ "leave", "o", wayland_types + 66 },
{ "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,
"wl_surface", 7,
12, 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 },
{ "get_pointer", "n", wayland_types + 67 },
{ "get_keyboard", "n", wayland_types + 68 },
{ "get_touch", "n", wayland_types + 69 },
{ "release", "5", wayland_types + 0 },
};
@@ -405,13 +409,13 @@ WL_PRIVATE const struct wl_interface wl_seat_interface = {
};
static const struct wl_message wl_pointer_requests[] = {
{ "set_cursor", "u?oii", wayland_types + 69 },
{ "set_cursor", "u?oii", wayland_types + 70 },
{ "release", "3", wayland_types + 0 },
};
static const struct wl_message wl_pointer_events[] = {
{ "enter", "uoff", wayland_types + 73 },
{ "leave", "uo", wayland_types + 77 },
{ "enter", "uoff", wayland_types + 74 },
{ "leave", "uo", wayland_types + 78 },
{ "motion", "uff", wayland_types + 0 },
{ "button", "uuuu", wayland_types + 0 },
{ "axis", "uuf", wayland_types + 0 },
@@ -435,8 +439,8 @@ static const struct wl_message wl_keyboard_requests[] = {
static const struct wl_message wl_keyboard_events[] = {
{ "keymap", "uhu", wayland_types + 0 },
{ "enter", "uoa", wayland_types + 79 },
{ "leave", "uo", wayland_types + 82 },
{ "enter", "uoa", wayland_types + 80 },
{ "leave", "uo", wayland_types + 83 },
{ "key", "uuuu", wayland_types + 0 },
{ "modifiers", "uuuuu", wayland_types + 0 },
{ "repeat_info", "4ii", wayland_types + 0 },
@@ -453,7 +457,7 @@ static const struct wl_message wl_touch_requests[] = {
};
static const struct wl_message wl_touch_events[] = {
{ "down", "uuoiff", wayland_types + 84 },
{ "down", "uuoiff", wayland_types + 85 },
{ "up", "uui", wayland_types + 0 },
{ "motion", "uiff", wayland_types + 0 },
{ "frame", "", wayland_types + 0 },
@@ -494,14 +498,14 @@ static const struct wl_message wl_region_requests[] = {
};
WL_PRIVATE const struct wl_interface wl_region_interface = {
"wl_region", 1,
"wl_region", 7,
3, wl_region_requests,
0, NULL,
};
static const struct wl_message wl_subcompositor_requests[] = {
{ "destroy", "", wayland_types + 0 },
{ "get_subsurface", "noo", wayland_types + 90 },
{ "get_subsurface", "noo", wayland_types + 91 },
};
WL_PRIVATE const struct wl_interface wl_subcompositor_interface = {
@@ -513,8 +517,8 @@ WL_PRIVATE const struct wl_interface wl_subcompositor_interface = {
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 },
{ "place_above", "o", wayland_types + 94 },
{ "place_below", "o", wayland_types + 95 },
{ "set_sync", "", wayland_types + 0 },
{ "set_desync", "", wayland_types + 0 },
};
@@ -527,7 +531,7 @@ WL_PRIVATE const struct wl_interface wl_subsurface_interface = {
static const struct wl_message wl_fixes_requests[] = {
{ "destroy", "", wayland_types + 0 },
{ "destroy_registry", "o", wayland_types + 95 },
{ "destroy_registry", "o", wayland_types + 96 },
};
WL_PRIVATE const struct wl_interface wl_fixes_interface = {

View File

@@ -1,4 +1,4 @@
/* Generated by wayland-scanner 1.24.0 */
/* Generated by wayland-scanner 1.25.0 */
/*
* Copyright © 2008-2013 Kristian Høgsberg

View File

@@ -234,7 +234,7 @@ void wayland_server::_xdg_listen_ping(void*, xdg_wm_base* xdg, uint32_t serial)
#if FENNEC_HAS_LIBDECOR
void wayland_server::_libdecor_on_error(struct libdecor*, libdecor_error error, const char* message) {
fennec::logger::log(
fennec::logger::log(logger::error,
fennec::format("libdecor error ({}): {}", static_cast<int>(error), fennec::cstring(message, strlen(message)))
);
}

View File

@@ -0,0 +1,72 @@
// =====================================================================================================================
// 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/vulkan/context.h>
#include <volk.h>
#include <fennec/platform/linux/wayland/server.h>
#include <fennec/renderers/vulkan/vksurface.h>
namespace fennec
{
namespace vk
{
struct wayland_surface_create_info : VkWaylandSurfaceCreateInfoKHR {
// Constructor & Destructor ============================================================================================
public:
wayland_surface_create_info(display_server* server, window* window)
: VkWaylandSurfaceCreateInfoKHR {
.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
.display = static_cast<wl_display*>(server->get_native_handle()),
.surface = static_cast<wl_surface*>(window->get_native_handle())
} {
}
operator const VkWaylandSurfaceCreateInfoKHR*() const {
return this;
}
};
}
wayland_vkcontext::wayland_vkcontext(display_server* display)
: vkcontext(display, extensions) {
}
wayland_vkcontext::~wayland_vkcontext() {
}
gfxsurface* wayland_vkcontext::create_surface(window* window) {
vk::wayland_surface_create_info info(window->server, window);
VkSurfaceKHR surface;
vkCreateWaylandSurfaceKHR(*instance, info, nullptr, &surface);
return new vksurface(window, this, make_unique<vk::surface>(surface));
}
}

View File

@@ -45,6 +45,10 @@ wayland_window::~wayland_window() {
}
void wayland_window::set_size(const ivec2&) {
}
void wayland_window::initialize() {
static constexpr wl_surface_listener surface_listener = {
.enter = _wl_surface_listen_enter,
@@ -124,7 +128,6 @@ void wayland_window::initialize() {
frame_callback = wl_surface_frame(surface);
wl_callback_add_listener(frame_callback, &frame_callback_listener, this);
wl_surface_commit(surface);
}
@@ -202,8 +205,8 @@ bool wayland_window::set_flag(uint8_t flag, bool value) {
case flag_borderless:
#if FENNEC_HAS_LIBDECOR
if (libdecorframe) {
bool vis = libdecor_frame_is_visible(libdecorframe);
bool tgt = not value;
const bool vis = libdecor_frame_is_visible(libdecorframe);
const bool tgt = not value;
if (vis != tgt) {
libdecor_frame_set_visibility(libdecorframe, tgt);
@@ -235,7 +238,7 @@ bool wayland_window::set_flag(uint8_t flag, bool value) {
default:
logger::log("Invalid flag passed to window::set_flag.");
logger::log(logger::error, "Invalid flag passed to window::set_flag.");
break;
}

View File

@@ -73,7 +73,7 @@ eglcontext::eglcontext(display_server* display)
// Initialize EGL
assertf(eglInitialize(_egldisplay, &_eglvmajor, &_eglvminor), "Failed to initialize egl.");
logger::log(format("Initialized EGL v{}.{}", _eglvmajor, _eglvminor));
logger::log(logger::info, format("Initialized EGL v{}.{}", _eglvmajor, _eglvminor));
// Reload EGL bindings
assertf(gladLoaderLoadEGL(_egldisplay), "Unable to load EGL Bindings.");
@@ -108,7 +108,8 @@ eglcontext::eglcontext(display_server* display)
version.minor = _eglvminor;
version.patch = 0;
version.meta = _eglctype;
logger::log(format("Created OpenGL Context: {} v{}.{}", egl_translate_type(version.meta), version.major, version.minor));
logger::log(logger::alert, format("Created OpenGL Context: {} v{}.{}", egl_translate_type(version.meta), version.major, version.minor));
}
eglcontext::~eglcontext() {

View File

@@ -37,8 +37,8 @@ eglsurface::eglsurface(fennec::window* win, eglcontext* ctx, void* eglwindow)
);
if (not _eglsurface) {
int32_t err = eglGetError();
logger::log(format("EGL error: {}", eglErrorString(err)));
const int32_t err = eglGetError();
logger::log(logger::error, format("EGL error: {}", eglErrorString(err)));
}
assertf(_eglsurface, "Failed to create EGL surface!");
@@ -46,17 +46,17 @@ eglsurface::eglsurface(fennec::window* win, eglcontext* ctx, void* eglwindow)
}
eglsurface::~eglsurface() {
eglcontext* ctx = static_cast<eglcontext*>(context);
eglcontext* ctx = dynamic_cast<eglcontext*>(context);
assertf(eglDestroySurface(ctx->_egldisplay, _eglsurface), "Error destroying EGL surface!");
}
void eglsurface::make_current() {
eglcontext* ctx = static_cast<eglcontext*>(context);
eglcontext* ctx = dynamic_cast<eglcontext*>(context);
assertf(eglMakeCurrent(ctx->_egldisplay, _eglsurface, _eglsurface, ctx->_eglcontext), "Error setting the current surface!");
}
void eglsurface::swap() {
eglcontext* ctx = static_cast<eglcontext*>(context);
eglcontext* ctx = dynamic_cast<eglcontext*>(context);
assertf(eglSwapBuffers(ctx->_egldisplay, _eglsurface), "Error swapping surface buffers!");
}

File diff suppressed because it is too large Load Diff

View File

@@ -45,13 +45,13 @@ void window_manager::initialize() {
// Find first valid server
while (not display_servers.is_empty()) {
display_server::entry it = display_servers.front();
const display_server::entry it = display_servers.front();
display_servers.pop();
unique_ptr<display_server> server = unique_ptr(it.ctor(_platform));
server->connect();
if (server->connected()) {
logger::log(format("Selected {} for the display server.", server->get_type().name()));
logger::log(logger::info, format("Selected {} for the display server.", server->get_type().name()));
_display = move(server);
break;
}
@@ -61,7 +61,7 @@ void window_manager::initialize() {
_thread = thread::current();
logger::log(format("Initializing Window Manager on thread: {:#016x}.", _thread));
logger::log(logger::info, format("Initializing Window Manager on thread: {:#016x}.", _thread));
}
void window_manager::shutdown() {
@@ -92,6 +92,11 @@ void window_manager::dispatch() {
assertf(_thread == thread::current(), "Attempted to dispatch Window Manager on a different thread!");
lock_guard guard(_lock);
size_t n = _commands.size();
while (n--) {
_commands.pop();
}
_display->dispatch();
}
@@ -104,7 +109,7 @@ window_id window_manager::create_window(const window::config& config, window_id
lock_guard guard(_lock);
window* p = parent == nullid ? nullptr : _windows[parent].get();
window_id id = _windows.emplace(_display->create_window(config, p));
const window_id id = _windows.emplace(_display->create_window(config, p));
_windows[id]->initialize();
return id;
}
@@ -144,11 +149,25 @@ void window_manager::close(window_id window) {
_windows.erase(window);
}
window_id window_manager::_parent(window_id) const {
window_id window_manager::_parent(window_id id) const {
window_id it = 0;
for (const auto& window : _windows) {
if (window.get() == _windows[id]->parent) {
return it;
}
++it;
}
return nullid;
}
window_id window_manager::_root(window_id) const {
window_id window_manager::_root(window_id id) const {
window_id it = 0;
for (const auto& window : _windows) {
if (window.get() == _windows[id]->root) {
return it;
}
++it;
}
return nullid;
}