Crafter.Graphics/interfaces/Crafter.Graphics-Window.cppm

197 lines
7.3 KiB
Text
Raw Normal View History

2025-05-07 19:21:51 +02:00
/*
Crafter®.Graphics
2026-03-09 20:10:19 +01:00
Copyright (C) 2026 Catcrafts®
2025-11-22 20:58:42 +01:00
catcrafts.net
2025-05-07 19:21:51 +02:00
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
2025-11-22 20:58:42 +01:00
License version 3.0 as published by the Free Software Foundation;
2025-05-07 19:21:51 +02:00
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
2025-11-17 00:44:45 +01:00
module;
2026-03-09 20:10:19 +01:00
#ifdef CRAFTER_GRAPHICS_WINDOW_WAYLAND
2025-11-22 20:58:42 +01:00
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/input-event-codes.h>
2025-11-17 00:44:45 +01:00
#include <xkbcommon/xkbcommon.h>
#include "../lib/xdg-shell-client-protocol.h"
#include "../lib/wayland-xdg-decoration-unstable-v1-client-protocol.h"
2025-12-29 18:56:06 +01:00
#include "../lib/fractional-scale-v1.h"
#include "../lib/viewporter.h"
2025-11-22 20:58:42 +01:00
#include <string.h>
#include <linux/input.h>
#include <sys/mman.h>
#include <wayland-cursor.h>
#include <errno.h>
#include <fcntl.h>
#include <print>
#include <wayland-client.h>
#include <wayland-client-protocol.h>
#endif
2026-03-09 20:10:19 +01:00
#ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN
2026-03-02 23:53:13 +01:00
#include "vulkan/vulkan.h"
2026-02-24 02:32:37 +01:00
#endif
2025-11-17 00:44:45 +01:00
2025-04-16 00:43:33 +02:00
export module Crafter.Graphics:Window;
2025-11-16 15:32:11 +01:00
import std;
2025-11-23 04:04:53 +01:00
import :Types;
2026-03-09 20:10:19 +01:00
import :Rendertarget;
import :Transform2D;
2025-11-23 04:04:53 +01:00
import Crafter.Event;
2026-03-09 20:10:19 +01:00
#ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN
2026-01-29 01:31:17 +01:00
import :PipelineRTVulkan;
#endif
2025-04-16 00:43:33 +02:00
export namespace Crafter {
2026-03-09 20:10:19 +01:00
#ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN
struct Semaphores {
// Swap chain image presentation
VkSemaphore presentComplete;
// Command buffer submission and execution
VkSemaphore renderComplete;
};
#endif
struct MouseElement;
struct Window {
2026-01-30 00:09:37 +01:00
FrameTime currentFrameTime;
2026-03-09 20:10:19 +01:00
std::uint32_t width;
std::uint32_t height;
2025-11-25 18:52:32 +01:00
std::chrono::time_point<std::chrono::high_resolution_clock> lastFrameBegin;
2025-11-23 04:04:53 +01:00
Event<void> onClose;
2025-11-24 03:38:20 +01:00
Event<FrameTime> onUpdate;
2025-11-23 04:04:53 +01:00
bool open = true;
bool updating = false;
2025-12-28 00:05:03 +01:00
bool heldkeys[static_cast<std::uint32_t>(CrafterKeys::CrafterKeysMax)] = {};
Event<void> onKeyDown[static_cast<std::uint32_t>(CrafterKeys::CrafterKeysMax)];
Event<void> onKeyHold[static_cast<std::uint32_t>(CrafterKeys::CrafterKeysMax)];
Event<void> onKeyUp[static_cast<std::uint32_t>(CrafterKeys::CrafterKeysMax)];
Event<CrafterKeys> onAnyKeyDown;
Event<CrafterKeys> onAnyKeyHold;
Event<CrafterKeys> onAnyKeyUp;
2026-03-09 20:10:19 +01:00
Event<void> onMouseRightClick;
Event<void> onMouseLeftClick;
Event<void> onMouseRightHold;
Event<void> onMouseLeftHold;
Event<void> onMouseRightRelease;
Event<void> onMouseLeftRelease;
Event<void> onMouseMove;
Event<void> onMouseEnter;
Event<void> onMouseLeave;
2025-12-30 23:28:38 +01:00
Event<std::uint32_t> onMouseScroll;
2026-03-09 20:10:19 +01:00
Vector<float, 2> currentMousePos;
Vector<float, 2> lastMousePos;
Vector<float, 2> mouseDelta;
2025-11-23 04:04:53 +01:00
bool mouseLeftHeld = false;
bool mouseRightHeld = false;
2025-11-25 19:43:40 +01:00
std::vector<MouseElement*> mouseElements;
2025-12-29 22:21:22 +01:00
std::vector<MouseElement*> pendingMouseElements;
2025-11-22 20:58:42 +01:00
2026-03-09 20:10:19 +01:00
Window(std::uint32_t width, std::uint32_t height);
Window(std::uint32_t width, std::uint32_t height, const std::string_view title);
Window(Window&) = delete;
Window(Window&&) = delete;
Window& operator=(const Window&) = delete;
2025-11-22 20:58:42 +01:00
2026-03-09 20:10:19 +01:00
void StartSync();
void StartUpdate();
void StopUpdate();
void SetTitle(const std::string_view title);
void Resize(std::uint32_t width, std::uint32_t height);
void Render();
void Update();
#ifdef CRAFTER_TIMING
std::chrono::nanoseconds totalUpdate;
std::vector<std::pair<const EventListener<FrameTime>*, std::chrono::nanoseconds>> updateTimings;
std::chrono::nanoseconds totalRender;
std::chrono::nanoseconds vblank;
std::chrono::nanoseconds totalFrame;
std::chrono::time_point<std::chrono::high_resolution_clock> frameEnd;
std::vector<std::chrono::nanoseconds> frameTimes;
void LogTiming();
#endif
2025-11-22 20:58:42 +01:00
2026-03-09 20:10:19 +01:00
#ifdef CRAFTER_GRAPHICS_WINDOW_WAYLAND
float scale;
#ifdef CRAFTER_GRAPHICS_RENDERER_SOFTWARE
Rendertarget renderer;
#endif
2025-11-23 04:04:53 +01:00
bool configured = false;
xdg_toplevel* xdgToplevel = nullptr;
2025-12-29 18:56:06 +01:00
wp_viewport* wpViewport = nullptr;
2025-11-23 04:04:53 +01:00
wl_surface* surface = nullptr;
wl_buffer* buffer = nullptr;
wl_buffer* backBuffer = nullptr;
xdg_surface* xdgSurface = nullptr;
wl_callback* cb = nullptr;
2026-03-09 20:10:19 +01:00
static void xdg_surface_handle_preferred_scale(void* data, wp_fractional_scale_v1*, std::uint32_t scale);
2025-11-23 04:04:53 +01:00
static void wl_surface_frame_done(void *data, wl_callback *cb, uint32_t time);
static void xdg_toplevel_handle_close(void* data, xdg_toplevel*);
static void xdg_surface_handle_configure(void* data, xdg_surface* xdg_surface, std::uint32_t serial);
static void xdg_toplevel_configure(void*, xdg_toplevel*, std::int32_t, std::int32_t, wl_array*);
2026-03-09 20:10:19 +01:00
2025-11-23 04:04:53 +01:00
constexpr static xdg_toplevel_listener xdg_toplevel_listener = {
.configure = xdg_toplevel_configure,
.close = xdg_toplevel_handle_close,
2025-11-22 20:58:42 +01:00
};
2025-11-23 04:04:53 +01:00
constexpr static wl_callback_listener wl_callback_listener = {
.done = wl_surface_frame_done,
};
constexpr static xdg_surface_listener xdg_surface_listener = {
.configure = xdg_surface_handle_configure,
2025-11-22 20:58:42 +01:00
};
2025-12-29 18:56:06 +01:00
constexpr static wp_fractional_scale_v1_listener wp_fractional_scale_v1_listener = {
.preferred_scale = xdg_surface_handle_preferred_scale,
};
2026-03-09 20:10:19 +01:00
inline static wp_fractional_scale_v1* wp_scale = nullptr;
#endif
2026-01-27 22:34:24 +01:00
2026-03-09 20:10:19 +01:00
#ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN
2026-01-29 01:31:17 +01:00
std::vector<VkDescriptorSet> descriptorsRt;
2026-01-31 21:08:42 +01:00
template <typename Pipeline>
2026-01-29 01:31:17 +01:00
void SetPipelineRT() {
2026-01-31 21:08:42 +01:00
rtPipeline = Pipeline::pipeline;
rtPipelineLayout = Pipeline::pipelineLayout;
raygenRegion = Pipeline::raygenRegion;
missRegion = Pipeline::missRegion;
hitRegion = Pipeline::hitRegion;
callableRegion = Pipeline::callableRegion;
2026-01-29 01:31:17 +01:00
}
2026-03-09 20:10:19 +01:00
void SetPipelineRT(PipelineRTVulkan& pipeline);
2026-02-24 02:32:37 +01:00
VkCommandBuffer StartInit();
void FinishInit();
void CreateSwapchain();
2026-03-09 20:10:19 +01:00
static constexpr std::uint8_t numFrames = 3;
2026-02-24 02:32:37 +01:00
VkSurfaceKHR vulkanSurface = VK_NULL_HANDLE;
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
VkFormat colorFormat;
VkColorSpaceKHR colorSpace;
VkImage images[numFrames];
VkImageView imageViews[numFrames];
std::thread thread;
VkCommandBuffer drawCmdBuffers[numFrames];
VkSubmitInfo submitInfo;
Semaphores semaphores;
2026-03-09 20:10:19 +01:00
std::uint32_t currentBuffer = 0;
2026-02-24 02:32:37 +01:00
VkPipelineStageFlags submitPipelineStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkPipeline rtPipeline;
VkPipelineLayout rtPipelineLayout;
VkStridedDeviceAddressRegionKHR raygenRegion;
VkStridedDeviceAddressRegionKHR missRegion;
VkStridedDeviceAddressRegionKHR hitRegion;
VkStridedDeviceAddressRegionKHR callableRegion;
2026-03-09 20:10:19 +01:00
#endif
2026-02-24 02:32:37 +01:00
};
2025-04-16 00:43:33 +02:00
}