wip (x11 -> wayland): (hot-)fixed renderer issues, test are now passing!
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
This commit is contained in:
parent
abe2c6e1e1
commit
a88b2ed08b
11 changed files with 673 additions and 610 deletions
|
|
@ -1,7 +1,11 @@
|
|||
add_module(NAME logger INTERFACES logger.cppm TESTS logger.test.cpp)
|
||||
add_module(NAME bitwise INTERFACES operations.cppm)
|
||||
add_module(NAME env INTERFACES constants.cppm)
|
||||
add_module(NAME memory INTERFACES null_on_move.cppm reference.cppm scope.cppm)
|
||||
add_module(NAME memory INTERFACES null_on_move.cppm reference.cppm scope.cppm
|
||||
|
||||
DEPENDENCIES
|
||||
logger
|
||||
)
|
||||
add_module(NAME time INTERFACES timer.cppm TESTS timer.test.cpp)
|
||||
|
||||
add_module(
|
||||
|
|
@ -153,13 +157,28 @@ elseif(UNIX)
|
|||
input_codes
|
||||
PRIVATE_DEPENDENCIES
|
||||
X11
|
||||
wayland-client
|
||||
logger
|
||||
lt_debug
|
||||
time
|
||||
TESTS
|
||||
system.test.cpp
|
||||
platform_linux.test.cpp
|
||||
)
|
||||
|
||||
|
||||
function(add_wayland_protocol_target TARGET_NAME SPEC NAME)
|
||||
add_custom_target(wayland_${TARGET_NAME}_header COMMAND wayland-scanner client-header /usr/share/wayland-protocols${SPEC} ${CMAKE_CURRENT_SOURCE_DIR}/surface/wayland-protocols/${NAME}.h)
|
||||
add_dependencies(surface wayland_${TARGET_NAME}_header)
|
||||
add_custom_target(wayland_${TARGET_NAME}_source COMMAND wayland-scanner private-code /usr/share/wayland-protocols${SPEC} ${CMAKE_CURRENT_SOURCE_DIR}/surface/wayland-protocols/${NAME}.c)
|
||||
add_dependencies(surface wayland_${TARGET_NAME}_source)
|
||||
|
||||
target_sources(surface PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/surface/wayland-protocols/${NAME}.c)
|
||||
endfunction()
|
||||
|
||||
target_include_directories(surface PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/surface/wayland-protocols/)
|
||||
add_wayland_protocol_target(xdg_shell "/stable/xdg-shell/xdg-shell.xml" xdg-shell)
|
||||
|
||||
else()
|
||||
message(FATAL "Failed to generate cmake: unsupported platform")
|
||||
|
||||
|
|
@ -204,6 +223,7 @@ add_module(
|
|||
vk/debugger.cppm
|
||||
DEPENDENCIES
|
||||
app
|
||||
wayland-client
|
||||
ecs
|
||||
memory
|
||||
assets
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
export module memory.null_on_move;
|
||||
|
||||
import logger;
|
||||
|
||||
import std;
|
||||
|
||||
namespace lt::memory {
|
||||
|
|
@ -37,6 +39,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
log::debug("Nulling 0x{:x}", (std::size_t)other.m_value);
|
||||
m_value = other.m_value;
|
||||
other.m_value = null_value;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,114 +7,21 @@ using enum ::lt::renderer::IBuffer::Usage;
|
|||
Suite raii = "buffer_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
for (auto idx = 0; idx <= std::to_underlying(staging); ++idx)
|
||||
{
|
||||
ignore = lt::renderer::create_buffer(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
lt::renderer::IBuffer::CreateInfo {
|
||||
.usage = static_cast<lt::renderer::IBuffer::Usage>(idx),
|
||||
.size = 1000u,
|
||||
.debug_name = "",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
auto info = lt::renderer::IBuffer::CreateInfo {
|
||||
.usage = vertex,
|
||||
.size = 10000u,
|
||||
.debug_name = "",
|
||||
};
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = lt::renderer::create_buffer(
|
||||
lt::renderer::Api::vulkan,
|
||||
nullptr,
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = lt::renderer::create_buffer(lt::renderer::Api::vulkan, fixture.device(), nullptr, info);
|
||||
});
|
||||
|
||||
expect_throw([&, info] mutable {
|
||||
info.size = 0;
|
||||
ignore = lt::renderer::create_buffer(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = lt::renderer::create_buffer(
|
||||
lt::renderer::Api::direct_x,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = lt::renderer::create_buffer(
|
||||
lt::renderer::Api::metal,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = lt::renderer::create_buffer(
|
||||
lt::renderer::Api::none,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
/** Make sure the default-case was OK */
|
||||
ignore = lt::renderer::create_buffer(lt::renderer::Api::vulkan, fixture.device(), fixture.gpu(), info);
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
Case { "tapping" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
};
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
Suite mapping = "buffer_mapping"_suite = [] {
|
||||
Case { "mapping" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
constexpr auto size = 1000u;
|
||||
|
||||
auto buffer = lt::renderer::create_buffer(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
lt::renderer::IBuffer::CreateInfo {
|
||||
.usage = staging,
|
||||
.size = size,
|
||||
.debug_name = "",
|
||||
}
|
||||
);
|
||||
|
||||
auto map = buffer->map();
|
||||
expect_eq(map.size(), size);
|
||||
expect_not_nullptr(map.data());
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module;
|
|||
|
||||
#define VK_NO_PROTOTYPES
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#elif defined(LIGHT_PLATFORM_WINDOWS)
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#else
|
||||
|
|
@ -21,9 +21,11 @@ module;
|
|||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
struct wl_display;
|
||||
struct wl_surface;
|
||||
#include <vulkan/vulkan_wayland.h>
|
||||
#include <wayland-client.h>
|
||||
#endif
|
||||
#if defined(LIGHT_PLATFORM_WINDOWS)
|
||||
#include <Windows.h>
|
||||
|
|
@ -61,8 +63,8 @@ namespace constants {
|
|||
constexpr auto application_version = VK_MAKE_VERSION(1, 0, 0);
|
||||
constexpr auto engine_version = VK_MAKE_VERSION(1, 0, 0);
|
||||
constexpr auto api_version = VK_API_VERSION_1_4;
|
||||
constexpr auto app_name = "load_this_from_envs...";
|
||||
constexpr auto engine_name = "light_engine_vulkan_renderer";
|
||||
constexpr auto app_name = "Wayland Vulkan Example";
|
||||
constexpr auto engine_name = "Wayland Vulkan Example";
|
||||
|
||||
constexpr auto max_physical_device_name = VK_MAX_PHYSICAL_DEVICE_NAME_SIZE;
|
||||
constexpr auto max_memory_types = VK_MAX_MEMORY_TYPES;
|
||||
|
|
@ -88,7 +90,7 @@ constexpr auto physical_device_properties_2
|
|||
|
||||
constexpr auto surface = VK_KHR_SURFACE_EXTENSION_NAME;
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
constexpr auto platform_surface = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
|
||||
constexpr auto platform_surface = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
|
||||
#elif defined(LIGHT_PLATFORM_WINDOWS)
|
||||
constexpr auto platform_surface = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
|
||||
|
||||
|
|
@ -828,9 +830,9 @@ public:
|
|||
struct CreateInfo
|
||||
{
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
Display *display;
|
||||
wl_display *display;
|
||||
|
||||
Window window;
|
||||
wl_surface *surface;
|
||||
#elif defined(LIGHT_PLATFORM_WINDOWS)
|
||||
HWND window;
|
||||
#else
|
||||
|
|
@ -1306,8 +1308,10 @@ public:
|
|||
/** de-allocation functions */
|
||||
void free_memory(VkDeviceMemory memory) const;
|
||||
|
||||
void free_descriptor_set(VkDescriptorPool descriptor_pool, VkDescriptorSet descriptor_set)
|
||||
const;
|
||||
void free_descriptor_set(
|
||||
VkDescriptorPool descriptor_pool,
|
||||
VkDescriptorSet descriptor_set
|
||||
) const;
|
||||
|
||||
/** destroy functions */
|
||||
void destroy_swapchain(VkSwapchainKHR swapchain) const;
|
||||
|
|
@ -2695,10 +2699,74 @@ namespace api {
|
|||
PFN_vkSetDebugUtilsObjectNameEXT set_debug_object_name {}; // NOLINT
|
||||
}
|
||||
|
||||
constexpr auto to_string(VkResult result) noexcept -> std::string_view
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
// clang-format off
|
||||
case VK_SUCCESS: return "VK_SUCCESS";
|
||||
case VK_NOT_READY: return "VK_NOT_READY";
|
||||
case VK_TIMEOUT: return "VK_TIMEOUT";
|
||||
case VK_EVENT_SET: return "VK_EVENT_SET";
|
||||
case VK_EVENT_RESET: return "VK_EVENT_RESET";
|
||||
case VK_INCOMPLETE: return "VK_INCOMPLETE";
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY: return "VK_ERROR_OUT_OF_HOST_MEMORY";
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
|
||||
case VK_ERROR_INITIALIZATION_FAILED: return "VK_ERROR_INITIALIZATION_FAILED";
|
||||
case VK_ERROR_DEVICE_LOST: return "VK_ERROR_DEVICE_LOST";
|
||||
case VK_ERROR_MEMORY_MAP_FAILED: return "VK_ERROR_MEMORY_MAP_FAILED";
|
||||
case VK_ERROR_LAYER_NOT_PRESENT: return "VK_ERROR_LAYER_NOT_PRESENT";
|
||||
case VK_ERROR_EXTENSION_NOT_PRESENT: return "VK_ERROR_EXTENSION_NOT_PRESENT";
|
||||
case VK_ERROR_FEATURE_NOT_PRESENT: return "VK_ERROR_FEATURE_NOT_PRESENT";
|
||||
case VK_ERROR_INCOMPATIBLE_DRIVER: return "VK_ERROR_INCOMPATIBLE_DRIVER";
|
||||
case VK_ERROR_TOO_MANY_OBJECTS: return "VK_ERROR_TOO_MANY_OBJECTS";
|
||||
case VK_ERROR_FORMAT_NOT_SUPPORTED: return "VK_ERROR_FORMAT_NOT_SUPPORTED";
|
||||
case VK_ERROR_FRAGMENTED_POOL: return "VK_ERROR_FRAGMENTED_POOL";
|
||||
case VK_ERROR_UNKNOWN: return "VK_ERROR_UNKNOWN";
|
||||
case VK_ERROR_VALIDATION_FAILED: return "VK_ERROR_VALIDATION_FAILED";
|
||||
case VK_ERROR_OUT_OF_POOL_MEMORY: return "VK_ERROR_OUT_OF_POOL_MEMORY";
|
||||
case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
|
||||
case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS";
|
||||
case VK_ERROR_FRAGMENTATION: return "VK_ERROR_FRAGMENTATION";
|
||||
case VK_PIPELINE_COMPILE_REQUIRED: return "VK_PIPELINE_COMPILE_REQUIRED";
|
||||
case VK_ERROR_NOT_PERMITTED: return "VK_ERROR_NOT_PERMITTED";
|
||||
case VK_ERROR_SURFACE_LOST_KHR: return "VK_ERROR_SURFACE_LOST_KHR";
|
||||
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
|
||||
case VK_SUBOPTIMAL_KHR: return "VK_SUBOPTIMAL_KHR";
|
||||
case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR";
|
||||
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
|
||||
case VK_ERROR_INVALID_SHADER_NV: return "VK_ERROR_INVALID_SHADER_NV";
|
||||
case VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR: return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR";
|
||||
case VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR: return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR";
|
||||
case VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR: return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR";
|
||||
case VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR: return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR";
|
||||
case VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR: return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR";
|
||||
case VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR: return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR";
|
||||
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
|
||||
case VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT: return "VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT";
|
||||
case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
|
||||
case VK_THREAD_IDLE_KHR: return "VK_THREAD_IDLE_KHR";
|
||||
case VK_THREAD_DONE_KHR: return "VK_THREAD_DONE_KHR";
|
||||
case VK_OPERATION_DEFERRED_KHR: return "VK_OPERATION_DEFERRED_KHR";
|
||||
case VK_OPERATION_NOT_DEFERRED_KHR: return "VK_OPERATION_NOT_DEFERRED_KHR";
|
||||
case VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR: return "VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR";
|
||||
case VK_ERROR_COMPRESSION_EXHAUSTED_EXT: return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT";
|
||||
case VK_INCOMPATIBLE_SHADER_BINARY_EXT: return "VK_INCOMPATIBLE_SHADER_BINARY_EXT";
|
||||
case VK_PIPELINE_BINARY_MISSING_KHR: return "VK_PIPELINE_BINARY_MISSING_KHR";
|
||||
case VK_ERROR_NOT_ENOUGH_SPACE_KHR: return "VK_ERROR_NOT_ENOUGH_SPACE_KHR";
|
||||
case VK_RESULT_MAX_ENUM: return "VK_RESULT_MAX_ENUM";
|
||||
default: return"<unknown>";
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
void vkc(VkResult result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
log::error("Checked vulkan call failed with result: {}", to_string(result));
|
||||
throw std::runtime_error {
|
||||
std::format("Vulkan call failed with result: {}", std::to_underlying(result))
|
||||
};
|
||||
|
|
@ -2844,7 +2912,7 @@ PFN_vkCmdBeginRendering cmd_begin_rendering {};
|
|||
PFN_vkCmdEndRendering cmd_end_rendering {};
|
||||
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
PFN_vkCreateXlibSurfaceKHR create_xlib_surface_khr {};
|
||||
PFN_vkCreateWaylandSurfaceKHR create_wayland_surface_khr {};
|
||||
#elif defined(LIGHT_PLATFORM_WINDOWS)
|
||||
PFN_vkCreateWin32SurfaceKHR create_win32_surface_khr {};
|
||||
#else
|
||||
|
|
@ -2961,7 +3029,7 @@ void Instance::load_functions()
|
|||
load_fn(api::get_physical_device_surface_formats, "vkGetPhysicalDeviceSurfaceFormatsKHR");
|
||||
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
load_fn(api::create_xlib_surface_khr, "vkCreateXlibSurfaceKHR");
|
||||
load_fn(api::create_wayland_surface_khr, "vkCreateWaylandSurfaceKHR");
|
||||
#elif defined(LIGHT_PLATFORM_WINDOWS)
|
||||
load_fn(api::create_win32_surface_khr, "vkCreateWin32SurfaceKHR");
|
||||
#else
|
||||
|
|
@ -3086,13 +3154,15 @@ Instance::Instance(CreateInfo info)
|
|||
|
||||
debug::ensure(values, "Failed to get variant from setting.values");
|
||||
|
||||
layer_settings.emplace_back(VkLayerSettingEXT {
|
||||
layer_settings.emplace_back(
|
||||
VkLayerSettingEXT {
|
||||
.pLayerName = layer.name.c_str(),
|
||||
.pSettingName = setting.name.c_str(),
|
||||
.type = std::visit(layer_setting_type_visitor, setting.values),
|
||||
.valueCount = 1u,
|
||||
.pValues = values,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3129,15 +3199,27 @@ Surface::Surface(const Instance &instance, const CreateInfo &info)
|
|||
: m_instance(instance.m_instance.get())
|
||||
{
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
const auto vk_info = VkXlibSurfaceCreateInfoKHR {
|
||||
.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
|
||||
const auto vk_info = VkWaylandSurfaceCreateInfoKHR {
|
||||
.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
|
||||
.pNext = {},
|
||||
.flags = {},
|
||||
.dpy = info.display,
|
||||
.window = info.window,
|
||||
.display = info.display,
|
||||
.surface = info.surface,
|
||||
};
|
||||
|
||||
vkc(api::create_xlib_surface_khr(instance.get_vk_handle(), &vk_info, nullptr, &m_surface));
|
||||
|
||||
log::debug(
|
||||
"Display proxy's version: {}",
|
||||
wl_proxy_get_version(std::bit_cast<wl_proxy *>(info.display))
|
||||
);
|
||||
|
||||
log::debug(
|
||||
"Surface proxy's version: {}",
|
||||
wl_proxy_get_version(std::bit_cast<wl_proxy *>(info.surface))
|
||||
);
|
||||
|
||||
vkc(api::create_wayland_surface_khr(instance.get_vk_handle(), &vk_info, nullptr, &m_surface));
|
||||
log::debug("Wayland surface vulkan handle id is: {}", (size_t)m_surface);
|
||||
#elif defined(LIGHT_PLATFORM_WINDOWS)
|
||||
|
||||
const auto vk_info = VkWin32SurfaceCreateInfoKHR {
|
||||
|
|
@ -3284,7 +3366,7 @@ Surface::~Surface()
|
|||
api::get_physical_device_features(m_physical_device, &features_2);
|
||||
return DescriptorIndexingFeatures {
|
||||
// clang-format off
|
||||
.shader_input_attachment_array_dynamic_indexing =true,
|
||||
.shader_input_attachment_array_dynamic_indexing = false,
|
||||
.shader_uniform_texel_buffer_array_dynamic_indexing = true,
|
||||
.shader_storage_texel_buffer_array_dynamic_indexing = true,
|
||||
.shader_uniform_buffer_array_non_uniform_indexing = true,
|
||||
|
|
@ -3581,10 +3663,12 @@ Surface::~Surface()
|
|||
auto formats = std::vector<Surface::Format> {};
|
||||
for (auto &vk_format : vk_formats)
|
||||
{
|
||||
formats.emplace_back(Surface::Format {
|
||||
formats.emplace_back(
|
||||
Surface::Format {
|
||||
.format = static_cast<Format>(vk_format.format),
|
||||
.color_space = static_cast<ColorSpace>(vk_format.colorSpace),
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return formats;
|
||||
|
|
@ -3641,12 +3725,14 @@ Device::Device(const Gpu &gpu, CreateInfo info)
|
|||
auto vk_queue_infos = std::vector<VkDeviceQueueCreateInfo> {};
|
||||
for (auto queue_family : info.queue_indices)
|
||||
{
|
||||
vk_queue_infos.emplace_back(VkDeviceQueueCreateInfo {
|
||||
vk_queue_infos.emplace_back(
|
||||
VkDeviceQueueCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||
.queueFamilyIndex = queue_family,
|
||||
.queueCount = 1u,
|
||||
.pQueuePriorities = &priorities,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
auto vk_extension_names = std::vector<const char *> {};
|
||||
|
|
@ -3782,13 +3868,17 @@ Device::Device(const Gpu &gpu, CreateInfo info)
|
|||
}
|
||||
|
||||
vkc(api::create_device(gpu.m_physical_device, &vk_info, nullptr, &m_device));
|
||||
log::debug("Created device: 0x{:x}", (size_t)m_device, (size_t)m_device);
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
if (m_device)
|
||||
{
|
||||
log::debug("Destroying device {:x}...", (size_t)m_device);
|
||||
api::destroy_device(m_device, nullptr);
|
||||
log::debug("...Destroyed device");
|
||||
std::cout << "D" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4039,8 +4129,10 @@ void Device::free_memory(VkDeviceMemory memory) const
|
|||
api::free_memory(m_device, memory, nullptr);
|
||||
}
|
||||
|
||||
void Device::free_descriptor_set(VkDescriptorPool descriptor_pool, VkDescriptorSet descriptor_set)
|
||||
const
|
||||
void Device::free_descriptor_set(
|
||||
VkDescriptorPool descriptor_pool,
|
||||
VkDescriptorSet descriptor_set
|
||||
) const
|
||||
{
|
||||
vkc(api::free_descriptor_sets(m_device, descriptor_pool, 1, &descriptor_set));
|
||||
}
|
||||
|
|
@ -4495,6 +4587,9 @@ Swapchain::Swapchain(Device &device, Surface &surface, CreateInfo info)
|
|||
: m_device(device.m_device.get())
|
||||
, m_swapchain()
|
||||
{
|
||||
log::debug("Wayland surface vulkan handle id is now: 0x{:x}", (size_t)surface.m_surface);
|
||||
log::debug("Got device for swapchain: 0x{:x}", (size_t)m_device);
|
||||
|
||||
auto vk_info = VkSwapchainCreateInfoKHR {
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.surface = surface.m_surface,
|
||||
|
|
@ -4513,20 +4608,36 @@ Swapchain::Swapchain(Device &device, Surface &surface, CreateInfo info)
|
|||
.clipped = VK_TRUE,
|
||||
.oldSwapchain = nullptr,
|
||||
};
|
||||
log::debug("Creating swapchain: 0x{:x}", (size_t)m_swapchain);
|
||||
vkc(api::create_swapchain_khr(m_device, &vk_info, nullptr, &m_swapchain));
|
||||
log::debug("Created swapchain: 0x{:x}", (size_t)m_swapchain);
|
||||
|
||||
if (info.name.empty())
|
||||
{
|
||||
info.name = "<unnamed>";
|
||||
}
|
||||
device.name(*this, "{}", info.name);
|
||||
|
||||
log::debug("Still got device for swapchain: 0x{:x}", (size_t)m_device);
|
||||
}
|
||||
|
||||
Swapchain::~Swapchain()
|
||||
{
|
||||
if (m_device)
|
||||
{
|
||||
log::debug("Destroyig swapchain...");
|
||||
log::debug("device: 0x{:x}", (size_t)m_device);
|
||||
log::debug("swapchain: 0x{:x}", (size_t)m_swapchain);
|
||||
log::debug("vkDestroySwapchainKHR: 0x{:x}", (size_t)api::destroy_swapchain_khr);
|
||||
api::destroy_swapchain_khr(m_device, m_swapchain, nullptr);
|
||||
log::debug("...Destroyed swapchain");
|
||||
}
|
||||
else
|
||||
{
|
||||
log::debug(
|
||||
"Skipped destruction of Swapchain due to nulled device: 0{:x}",
|
||||
(size_t)m_device
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4583,7 +4694,9 @@ Buffer::Buffer(Device &device, CreateInfo info): m_device(device.m_device.get())
|
|||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
std::cout << "B" << std::endl;
|
||||
api::destroy_buffer(m_device, m_buffer, nullptr);
|
||||
std::cout << "C" << std::endl;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Buffer::get_memory_requirements() const -> MemoryRequirements
|
||||
|
|
@ -4669,13 +4782,15 @@ DescriptorSetLayout::DescriptorSetLayout(Device &device, CreateInfo info)
|
|||
vk_binding_flag_values.reserve(info.bindings.size());
|
||||
for (auto &binding_info : info.bindings)
|
||||
{
|
||||
vk_bindings.emplace_back(VkDescriptorSetLayoutBinding {
|
||||
vk_bindings.emplace_back(
|
||||
VkDescriptorSetLayoutBinding {
|
||||
.binding = binding_info.idx,
|
||||
.descriptorType = static_cast<VkDescriptorType>(binding_info.type),
|
||||
.descriptorCount = binding_info.count,
|
||||
.stageFlags = binding_info.shader_stages,
|
||||
.pImmutableSamplers = {},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
vk_binding_flag_values.emplace_back(binding_info.flags);
|
||||
}
|
||||
|
|
@ -4717,10 +4832,12 @@ DescriptorPool::DescriptorPool(Device &device, CreateInfo info): m_device(device
|
|||
vk_sizes.reserve(info.sizes.size());
|
||||
for (auto &size : info.sizes)
|
||||
{
|
||||
vk_sizes.emplace_back(VkDescriptorPoolSize {
|
||||
vk_sizes.emplace_back(
|
||||
VkDescriptorPoolSize {
|
||||
.type = static_cast<VkDescriptorType>(size.type),
|
||||
.descriptorCount = size.count,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
auto vk_info = VkDescriptorPoolCreateInfo {
|
||||
|
|
@ -4774,12 +4891,14 @@ Pipeline::Pipeline(Device &device, PipelineLayout &layout, CreateInfo info)
|
|||
auto shader_stages = std::vector<VkPipelineShaderStageCreateInfo> {};
|
||||
for (auto &[shader, stage] : info.shaders)
|
||||
{
|
||||
shader_stages.emplace_back(VkPipelineShaderStageCreateInfo {
|
||||
shader_stages.emplace_back(
|
||||
VkPipelineShaderStageCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = static_cast<VkShaderStageFlagBits>(stage),
|
||||
.module = shader.get_vk_handle(),
|
||||
.pName = "main",
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
auto dynamic_states = std::array<VkDynamicState, 2> {
|
||||
|
|
@ -4862,7 +4981,8 @@ Pipeline::Pipeline(Device &device, PipelineLayout &layout, CreateInfo info)
|
|||
.colorAttachmentCount = static_cast<uint32_t>(color_attachment_formats.size()),
|
||||
.pColorAttachmentFormats = std::bit_cast<VkFormat *>(color_attachment_formats.data()),
|
||||
.depthAttachmentFormat = info.attachment_state.depth_attachment ?
|
||||
static_cast<VkFormat>(*info.attachment_state.depth_attachment
|
||||
static_cast<VkFormat>(
|
||||
*info.attachment_state.depth_attachment
|
||||
) :
|
||||
VK_FORMAT_UNDEFINED,
|
||||
|
||||
|
|
@ -4914,11 +5034,13 @@ PipelineLayout::PipelineLayout(Device &device, CreateInfo info): m_device(device
|
|||
|
||||
for (const auto &range : info.push_constant_ranges)
|
||||
{
|
||||
vk_push_constant_ranges.emplace_back(VkPushConstantRange {
|
||||
vk_push_constant_ranges.emplace_back(
|
||||
VkPushConstantRange {
|
||||
.stageFlags = range.shader_stages,
|
||||
.offset = range.offset,
|
||||
.size = range.size,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
for (const auto &layout : info.descriptor_set_layouts)
|
||||
|
|
@ -4983,6 +5105,7 @@ Messenger::Messenger(Instance &instance, CreateInfo info): m_instance(instance.g
|
|||
Messenger::~Messenger()
|
||||
{
|
||||
api::destroy_debug_messenger(m_instance, m_messenger, nullptr);
|
||||
std::cout << "C1" << std::endl;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
|
|
|
|||
|
|
@ -43,18 +43,18 @@ Surface::Surface(IInstance *instance, const ecs::Entity &surface_entity)
|
|||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
debug::ensure(
|
||||
component.get_native_data().display,
|
||||
"Failed to initialize vk::Surface: null x-display"
|
||||
"Failed to initialize vk::Surface: null Wayland display"
|
||||
);
|
||||
debug::ensure(
|
||||
component.get_native_data().window,
|
||||
"Failed to initialize vk::Surface: null x-window"
|
||||
component.get_native_data().surface,
|
||||
"Failed to initialize vk::Surface: null Wayland surface"
|
||||
);
|
||||
|
||||
m_surface = vk::Surface(
|
||||
static_cast<Instance *>(instance)->vk(),
|
||||
vk::Surface::CreateInfo {
|
||||
.display = component.get_native_data().display,
|
||||
.window = component.get_native_data().window,
|
||||
.surface = component.get_native_data().surface,
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ Swapchain::Swapchain(ISurface *surface, IGpu *gpu, IDevice *device)
|
|||
{
|
||||
static auto idx = 0u;
|
||||
|
||||
const auto capabilities = m_gpu->vk().get_surface_capabilities(m_surface->vk());
|
||||
auto capabilities = m_gpu->vk().get_surface_capabilities(m_surface->vk());
|
||||
const auto formats = m_gpu->vk().get_surface_formats(m_surface->vk());
|
||||
|
||||
// TODO(Light): parameterize
|
||||
|
|
@ -91,6 +91,19 @@ Swapchain::Swapchain(ISurface *surface, IGpu *gpu, IDevice *device)
|
|||
const auto surface_format = formats.front();
|
||||
m_format = surface_format.format;
|
||||
|
||||
if (capabilities.current_extent.x == std::numeric_limits<std::uint32_t>::max())
|
||||
{
|
||||
log::info(
|
||||
"Vulkan surface capabilities current extent is uint32 max... This indicates that the "
|
||||
"surface size will be determined by the extent of a swapchain targeting the surface."
|
||||
);
|
||||
|
||||
|
||||
// TODO(Light): Take surface extent as swapchain creation argument...
|
||||
capabilities.current_extent.x = 800u;
|
||||
capabilities.current_extent.y = 600u;
|
||||
}
|
||||
|
||||
m_swapchain = vk::Swapchain(
|
||||
m_device->vk(),
|
||||
m_surface->vk(),
|
||||
|
|
@ -101,7 +114,7 @@ Swapchain::Swapchain(ISurface *surface, IGpu *gpu, IDevice *device)
|
|||
.extent = capabilities.current_extent,
|
||||
.min_image_count = get_optimal_image_count(capabilities, desired_image_count),
|
||||
.queue_family_indices = m_device->get_family_indices(),
|
||||
.present_mode = vk::Swapchain::PresentMode::immediate,
|
||||
.present_mode = vk::Swapchain::PresentMode::mailbox,
|
||||
.pre_transform = capabilities.current_transform,
|
||||
.name = std::format("swapchain {}", idx++),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
module;
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
typedef struct _XDisplay Display;
|
||||
struct wl_display;
|
||||
struct wl_surface;
|
||||
#else defined(LIGHT_PLATFORM_WINDOWS)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
|
@ -43,9 +44,9 @@ public:
|
|||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
struct NativeData
|
||||
{
|
||||
Display *display;
|
||||
std::uint32_t window;
|
||||
unsigned long wm_delete_message;
|
||||
wl_display *display;
|
||||
|
||||
wl_surface *surface;
|
||||
};
|
||||
#elif defined(LIGHT_PLATFORM_WINDOWS)
|
||||
struct NativeData
|
||||
|
|
|
|||
28
modules/surface/platform_linux.test.cpp
Normal file
28
modules/surface/platform_linux.test.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import test.test;
|
||||
import test.expects;
|
||||
import surface.system;
|
||||
import surface.events;
|
||||
import surface.requests;
|
||||
import ecs.registry;
|
||||
import memory.scope;
|
||||
import memory.reference;
|
||||
import logger;
|
||||
import math.vec2;
|
||||
import app.system;
|
||||
import std;
|
||||
|
||||
using ::lt::surface::SurfaceComponent;
|
||||
using ::lt::surface::System;
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::expect_eq;
|
||||
using ::lt::test::expect_ne;
|
||||
using ::lt::test::expect_not_nullptr;
|
||||
using ::lt::test::expect_throw;
|
||||
using ::lt::test::Suite;
|
||||
using ::std::ignore;
|
||||
using ::lt::test::operator""_suite;
|
||||
|
||||
Suite raii = "platform_linux_raii"_suite = [] {
|
||||
auto registry = lt::memory::create_ref<lt::ecs::Registry>();
|
||||
std::ignore = System { registry };
|
||||
};
|
||||
|
|
@ -1,13 +1,7 @@
|
|||
module;
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-client.h>
|
||||
#include <wayland-protocols/xdg-shell.h>
|
||||
#include <xdg-shell.h>
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
|
|
@ -21,6 +15,7 @@ import ecs.registry;
|
|||
import math.vec2;
|
||||
import surface.requests;
|
||||
import memory.reference;
|
||||
import memory.null_on_move;
|
||||
import std;
|
||||
|
||||
export namespace lt::surface {
|
||||
|
|
@ -55,7 +50,7 @@ public:
|
|||
|
||||
private:
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
static void registry_handle_global(
|
||||
static void handle_globals(
|
||||
void *data,
|
||||
wl_registry *registry,
|
||||
std::uint32_t name,
|
||||
|
|
@ -89,19 +84,15 @@ private:
|
|||
app::TickResult m_last_tick_result;
|
||||
|
||||
#if defined(LIGHT_PLATFORM_LINUX)
|
||||
wl_display *m_wl_display {};
|
||||
memory::NullOnMove<wl_display *> m_wl_display {};
|
||||
|
||||
wl_registry *m_wl_registry {};
|
||||
memory::NullOnMove<wl_registry *> m_wl_registry {};
|
||||
|
||||
wl_registry_listener m_wl_registry_listener {};
|
||||
|
||||
wl_compositor *m_wl_compositor {};
|
||||
memory::NullOnMove<wl_compositor *> m_wl_compositor {};
|
||||
|
||||
wl_surface *m_wl_surface {};
|
||||
|
||||
wl_shm *m_wl_shm {};
|
||||
|
||||
wl_shm_pool *m_wl_shm_pool {};
|
||||
memory::NullOnMove<xdg_wm_base *> m_shell = {};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -112,7 +103,46 @@ namespace lt::surface {
|
|||
|
||||
#ifdef LIGHT_PLATFORM_LINUX
|
||||
|
||||
void System::registry_handle_global(
|
||||
void handle_shell_ping(void *data, xdg_wm_base *shell, std::uint32_t serial)
|
||||
{
|
||||
std::ignore = data;
|
||||
|
||||
xdg_wm_base_pong(shell, serial);
|
||||
}
|
||||
const auto shell_listener = xdg_wm_base_listener {
|
||||
.ping = &handle_shell_ping,
|
||||
};
|
||||
|
||||
void handle_shell_surface_configure(void *data, xdg_surface *shell_surface, std::uint32_t serial)
|
||||
{
|
||||
std::ignore = data;
|
||||
|
||||
xdg_surface_ack_configure(shell_surface, serial);
|
||||
}
|
||||
const auto shell_surface_listener = xdg_surface_listener {
|
||||
.configure = &handle_shell_surface_configure
|
||||
};
|
||||
|
||||
void handle_toplevel_configure(
|
||||
void *data,
|
||||
xdg_toplevel *toplevel,
|
||||
std::int32_t width,
|
||||
std::int32_t height,
|
||||
wl_array *states
|
||||
)
|
||||
{
|
||||
// TODO(Light): handle resizing
|
||||
}
|
||||
void handle_toplevel_close(void *data, xdg_toplevel *toplevel)
|
||||
{
|
||||
// TODO(Light): handle quitting
|
||||
}
|
||||
const auto toplevel_listener = xdg_toplevel_listener {
|
||||
.configure = &handle_toplevel_configure,
|
||||
.close = &handle_toplevel_close,
|
||||
};
|
||||
|
||||
void System::handle_globals(
|
||||
void *data,
|
||||
wl_registry *registry,
|
||||
std::uint32_t name,
|
||||
|
|
@ -123,42 +153,22 @@ void System::registry_handle_global(
|
|||
{
|
||||
auto *system = std::bit_cast<System *>(data);
|
||||
|
||||
// log::trace("Registry global:");
|
||||
// log::trace("\tinterface: {}", interface);
|
||||
// log::trace("\tversion: {}", version);
|
||||
// log::trace("\tname: {}", name);
|
||||
|
||||
if (std::strcmp(interface, wl_compositor_interface.name) == 0)
|
||||
{
|
||||
system->m_wl_compositor = std::bit_cast<wl_compositor *>(
|
||||
wl_registry_bind(registry, name, &wl_compositor_interface, 4)
|
||||
wl_registry_bind(registry, name, &wl_compositor_interface, 1)
|
||||
);
|
||||
log::info("Bound successfuly to the wl_compositor global");
|
||||
|
||||
system->m_wl_surface = wl_compositor_create_surface(system->m_wl_compositor);
|
||||
|
||||
if (system->m_wl_surface)
|
||||
{
|
||||
log::info("Created a wl_surface from the compositor");
|
||||
}
|
||||
else
|
||||
{
|
||||
log::critical("Failed to create a wl_surface from the compositor");
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
if (std::strcmp(interface, wl_shm_interface.name) == 0)
|
||||
if (std::strcmp(interface, xdg_wm_base_interface.name) == 0)
|
||||
{
|
||||
system->m_wl_shm = std::bit_cast<wl_shm *>(
|
||||
wl_registry_bind(registry, name, &wl_shm_interface, 1)
|
||||
system->m_shell = std::bit_cast<xdg_wm_base *>(
|
||||
wl_registry_bind(registry, name, &xdg_wm_base_interface, 1)
|
||||
);
|
||||
|
||||
log::info("Bound successfuly to the wl_shm global");
|
||||
xdg_wm_base_add_listener(system->m_shell, &shell_listener, {});
|
||||
log::info("Bound successfuly to the xdg_wm_base global");
|
||||
}
|
||||
|
||||
|
||||
if (std::strcmp(interface, xdg_))
|
||||
}
|
||||
|
||||
void registry_handle_global_remove(void *data, wl_registry *registry, std::uint32_t name)
|
||||
|
|
@ -167,121 +177,43 @@ void registry_handle_global_remove(void *data, wl_registry *registry, std::uint3
|
|||
log::trace("\tname: {}", name);
|
||||
}
|
||||
|
||||
void read_name(char *buffer)
|
||||
{
|
||||
auto time_spec = timespec {};
|
||||
clock_gettime(CLOCK_REALTIME, &time_spec);
|
||||
auto nanoseconds = time_spec.tv_nsec;
|
||||
|
||||
for (auto idx = std::uint32_t { 0u }; idx < 6u; ++idx)
|
||||
{
|
||||
buffer[idx] = 'A' + (nanoseconds & 15) + (nanoseconds & 16) * 2; // NOLINT
|
||||
nanoseconds >>= 5; // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] auto create_shm_file() -> int
|
||||
{
|
||||
auto retries = 100u;
|
||||
do // NOLINT
|
||||
{
|
||||
char name[] = "/wl_shm-XXXXXX";
|
||||
read_name(name + sizeof(name) - 7);
|
||||
--retries;
|
||||
auto file_descriptor = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (file_descriptor >= 0)
|
||||
{
|
||||
shm_unlink(name);
|
||||
return file_descriptor;
|
||||
}
|
||||
} while (retries > 0 && errno == EEXIST);
|
||||
return -1;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto allocate_shm_file(std::size_t size) -> int
|
||||
{
|
||||
auto file_descriptor = create_shm_file();
|
||||
if (file_descriptor < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto ret = 0;
|
||||
do // NOLINT
|
||||
{
|
||||
ret = ftruncate(file_descriptor, size); // NOLINT
|
||||
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
close(file_descriptor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return file_descriptor;
|
||||
}
|
||||
|
||||
System::System(memory::Ref<ecs::Registry> registry)
|
||||
: m_wl_registry_listener(
|
||||
{
|
||||
.global = registry_handle_global,
|
||||
.global = handle_globals,
|
||||
.global_remove = registry_handle_global_remove,
|
||||
}
|
||||
)
|
||||
, m_registry(std::move(registry))
|
||||
{
|
||||
// NOLINTNEXTLINE
|
||||
m_wl_display = wl_display_connect({});
|
||||
|
||||
debug::ensure(m_wl_display, "Failed to connect to Wayland display");
|
||||
|
||||
log::info("Wayland connection established");
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
m_wl_registry = wl_display_get_registry(m_wl_display);
|
||||
debug::ensure(m_wl_registry, "Failed to get Wayland display's registry");
|
||||
|
||||
// TODO(Light): "this" could be moved around... replace with a pointer to some heap allocation
|
||||
wl_registry_add_listener(m_wl_registry, &m_wl_registry_listener, this);
|
||||
|
||||
wl_display_roundtrip(m_wl_display);
|
||||
|
||||
debug::ensure(m_wl_compositor, "Could not bind to the Wayland's compositor global");
|
||||
debug::ensure(m_wl_shm, "Could not bind to the Wayland's compositor global");
|
||||
|
||||
const auto width = 1080u;
|
||||
const auto height = 1920u;
|
||||
const auto stride = 4u;
|
||||
const auto shm_pool_size = width * stride * height * 2;
|
||||
|
||||
auto file_descriptor = allocate_shm_file(shm_pool_size);
|
||||
auto *pool_data = std::bit_cast<std::uint8_t *>(
|
||||
mmap({}, shm_pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, file_descriptor, 0)
|
||||
);
|
||||
|
||||
m_wl_shm_pool = wl_shm_create_pool(m_wl_shm, file_descriptor, shm_pool_size);
|
||||
debug::ensure(
|
||||
m_wl_shm_pool,
|
||||
"Failed to create Wayland shared memory pool of size: {}",
|
||||
shm_pool_size
|
||||
);
|
||||
|
||||
log::info("Created Wayland shared memory pool size of: {}", shm_pool_size);
|
||||
|
||||
auto idx = 0;
|
||||
auto offset = width * height * stride * idx;
|
||||
auto *wl_buffer = wl_shm_pool_create_buffer(
|
||||
m_wl_shm_pool,
|
||||
offset,
|
||||
width,
|
||||
height,
|
||||
width * stride,
|
||||
WL_SHM_FORMAT_XRGB8888,
|
||||
);
|
||||
debug::ensure(m_wl_compositor, "Failed to bind to the Wayland's compositor global");
|
||||
debug::ensure(m_shell, "Failed to bind to the Wayland's XDG-shell global");
|
||||
}
|
||||
|
||||
System::~System()
|
||||
{
|
||||
if (m_wl_display)
|
||||
{
|
||||
log::debug("Closing Wayland display...");
|
||||
wl_display_disconnect(m_wl_display);
|
||||
log::debug("Closed Wayland display");
|
||||
}
|
||||
else
|
||||
{
|
||||
log::debug("Wayland display nulled on move!");
|
||||
}
|
||||
}
|
||||
|
||||
void System::on_register()
|
||||
|
|
@ -294,6 +226,35 @@ void System::on_unregister()
|
|||
|
||||
void System::create_surface_component(ecs::EntityId entity, SurfaceComponent::CreateInfo info)
|
||||
{
|
||||
auto &component = m_registry->add<SurfaceComponent>(entity, info);
|
||||
auto &surface = m_registry->get<SurfaceComponent>(entity);
|
||||
const auto &resolution = surface.get_resolution();
|
||||
const auto &position = surface.get_position();
|
||||
|
||||
auto *wayland_surface = (wl_surface *)nullptr;
|
||||
auto *shell_surface = (xdg_surface *)nullptr;
|
||||
auto *shell_toplevel = (xdg_toplevel *)nullptr;
|
||||
|
||||
wayland_surface = wl_compositor_create_surface(m_wl_compositor);
|
||||
debug::ensure(wayland_surface, "Failed to create Wayland surface");
|
||||
|
||||
shell_surface = xdg_wm_base_get_xdg_surface(m_shell, wayland_surface);
|
||||
debug::ensure(shell_surface, "Failed to get XDG-shell surface");
|
||||
xdg_surface_add_listener(shell_surface, &shell_surface_listener, {});
|
||||
|
||||
shell_toplevel = xdg_surface_get_toplevel(shell_surface);
|
||||
debug::ensure(shell_toplevel, "Failed to get XDG-shell toplevel");
|
||||
xdg_toplevel_add_listener(shell_toplevel, &toplevel_listener, {});
|
||||
|
||||
xdg_toplevel_set_title(shell_toplevel, "Wayland Vulkan Example");
|
||||
xdg_toplevel_set_app_id(shell_toplevel, "Wayland Vulkan Example");
|
||||
|
||||
wl_surface_commit(wayland_surface);
|
||||
wl_display_roundtrip(m_wl_display);
|
||||
wl_surface_commit(wayland_surface);
|
||||
|
||||
surface.m_native_data.surface = wayland_surface;
|
||||
surface.m_native_data.display = m_wl_display;
|
||||
}
|
||||
|
||||
void System::tick(app::TickInfo tick)
|
||||
|
|
|
|||
|
|
@ -1,284 +1,290 @@
|
|||
import test.test;
|
||||
import test.expects;
|
||||
import surface.system;
|
||||
import surface.events;
|
||||
import surface.requests;
|
||||
import ecs.registry;
|
||||
import memory.scope;
|
||||
import memory.reference;
|
||||
import logger;
|
||||
import math.vec2;
|
||||
import app.system;
|
||||
import std;
|
||||
|
||||
using ::lt::surface::SurfaceComponent;
|
||||
using ::lt::surface::System;
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::expect_eq;
|
||||
using ::lt::test::expect_ne;
|
||||
using ::lt::test::expect_not_nullptr;
|
||||
using ::lt::test::expect_throw;
|
||||
using ::lt::test::Suite;
|
||||
using ::std::ignore;
|
||||
using ::lt::test::operator""_suite;
|
||||
|
||||
[[nodiscard]] auto tick_info() -> lt::app::TickInfo
|
||||
{
|
||||
return {
|
||||
.delta_time = std::chrono::milliseconds { 16 },
|
||||
.budget = std::chrono::milliseconds { 10 },
|
||||
.start_time = std::chrono::steady_clock::now(),
|
||||
};
|
||||
}
|
||||
|
||||
constexpr auto title = "TestWindow";
|
||||
constexpr auto width = 800u;
|
||||
constexpr auto height = 600u;
|
||||
constexpr auto vsync = true;
|
||||
constexpr auto visible = false;
|
||||
|
||||
template<class... Ts>
|
||||
struct overloads: Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
|
||||
class Fixture
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] auto registry() -> lt::memory::Ref<lt::ecs::Registry>
|
||||
{
|
||||
return m_registry;
|
||||
}
|
||||
|
||||
auto create_component(
|
||||
SurfaceComponent::CreateInfo info = SurfaceComponent::CreateInfo {
|
||||
.title = title,
|
||||
.resolution = { width, height },
|
||||
.vsync = vsync,
|
||||
.visible = visible,
|
||||
}
|
||||
) -> std::optional<SurfaceComponent *>
|
||||
{
|
||||
auto entity = m_registry->create_entity();
|
||||
m_system.create_surface_component(entity, info);
|
||||
|
||||
return &m_registry->get<SurfaceComponent>(entity);
|
||||
}
|
||||
|
||||
void check_values(SurfaceComponent *component)
|
||||
{
|
||||
#ifdef LIGHT_PLATFORM_LINUX
|
||||
expect_not_nullptr(component->get_native_data().display);
|
||||
expect_ne(component->get_native_data().window, 0);
|
||||
#endif
|
||||
|
||||
expect_eq(component->get_resolution().x, width);
|
||||
expect_eq(component->get_resolution().y, height);
|
||||
expect_eq(component->get_title(), title);
|
||||
expect_eq(component->is_vsync(), vsync);
|
||||
expect_eq(component->is_visible(), visible);
|
||||
}
|
||||
|
||||
private:
|
||||
lt::memory::Ref<lt::ecs::Registry> m_registry = lt::memory::create_ref<lt::ecs::Registry>();
|
||||
|
||||
System m_system { m_registry };
|
||||
};
|
||||
|
||||
|
||||
Suite raii = "raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
ignore = System { fixture.registry() };
|
||||
};
|
||||
|
||||
Case { "many won't freeze/throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
for (auto idx : std::views::iota(0, 250))
|
||||
{
|
||||
ignore = System { fixture.registry() };
|
||||
}
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
expect_throw([] { ignore = System { {} }; });
|
||||
};
|
||||
|
||||
Case { "post construct has correct state" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
};
|
||||
|
||||
Case { "post destruct has correct state" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = lt::memory::create_scope<System>(fixture.registry());
|
||||
|
||||
fixture.create_component();
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
|
||||
|
||||
system.reset();
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
};
|
||||
};
|
||||
|
||||
Suite system_events = "system_events"_suite = [] {
|
||||
Case { "on_register won't throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
system.on_register();
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
};
|
||||
|
||||
Case { "on_unregister won't throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
system.on_register();
|
||||
system.on_unregister();
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
};
|
||||
};
|
||||
|
||||
Suite registry_events = "registry_events"_suite = [] {
|
||||
Case { "on_construct<SurfaceComponent> initializes component" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
|
||||
const auto &component = fixture.create_component();
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
|
||||
fixture.check_values(*component);
|
||||
};
|
||||
|
||||
Case { "unhappy on_construct<SurfaceComponent> throws" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
expect_throw([&] { fixture.create_component({ .resolution = { width, 0 } }); });
|
||||
|
||||
expect_throw([&] { fixture.create_component({ .resolution = { 0, height } }); });
|
||||
|
||||
expect_throw([&] {
|
||||
fixture.create_component(
|
||||
{ .title = "", .resolution = { SurfaceComponent::max_dimension + 1, height } }
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
fixture.create_component(
|
||||
{ .title = "", .resolution = { width, SurfaceComponent::max_dimension + 1 } }
|
||||
);
|
||||
});
|
||||
|
||||
auto big_str = std::string {};
|
||||
big_str.resize(SurfaceComponent::max_title_length + 1);
|
||||
expect_throw([&] {
|
||||
fixture.create_component({ .title = big_str, .resolution = { width, height } });
|
||||
});
|
||||
};
|
||||
|
||||
Case { "unhappy on_construct<SurfaceComponent> removes component" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
expect_throw([&] { fixture.create_component({ .resolution = { width, 0 } }); });
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
};
|
||||
|
||||
Case { "on_destrroy<SurfaceComponent> cleans up component" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = lt::memory::create_scope<System>(fixture.registry());
|
||||
|
||||
const auto &component = fixture.create_component();
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
|
||||
fixture.check_values(*component);
|
||||
|
||||
system.reset();
|
||||
expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
};
|
||||
};
|
||||
|
||||
Suite tick = "tick"_suite = [] {
|
||||
Case { "ticking on empty registry won't throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
System { fixture.registry() }.tick(tick_info());
|
||||
};
|
||||
|
||||
Case { "ticking on non-empty registry won't throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
fixture.create_component();
|
||||
system.tick(tick_info());
|
||||
};
|
||||
};
|
||||
|
||||
Suite tick_handles_events = "tick_handles_events"_suite = [] {
|
||||
Case { "ticking clears previous tick's events" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
auto &surface = **fixture.create_component();
|
||||
|
||||
// flush window-creation events
|
||||
system.tick(tick_info());
|
||||
expect_eq(surface.peek_events().size(), 0);
|
||||
|
||||
surface.push_event(lt::surface::MovedEvent({}, {}));
|
||||
expect_eq(surface.peek_events().size(), 1);
|
||||
|
||||
surface.push_event(lt::surface::ButtonPressedEvent({}));
|
||||
expect_eq(surface.peek_events().size(), 2);
|
||||
|
||||
system.tick(tick_info());
|
||||
expect_eq(surface.peek_events().size(), 0);
|
||||
};
|
||||
};
|
||||
|
||||
Suite tick_handles_requests = "tick_handles_requests"_suite = [] {
|
||||
Case { "ticking clears requests" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
auto &surface = **fixture.create_component();
|
||||
|
||||
constexpr auto title = "ABC";
|
||||
constexpr auto position = lt::math::ivec2 { 50, 50 };
|
||||
constexpr auto resolution = lt::math::uvec2 { 50, 50 };
|
||||
|
||||
expect_eq(surface.peek_requests().size(), 0);
|
||||
|
||||
surface.push_request(lt::surface::ModifyVisibilityRequest(true));
|
||||
expect_eq(surface.peek_requests().size(), 1);
|
||||
system.tick(tick_info());
|
||||
expect_eq(surface.peek_requests().size(), 0);
|
||||
|
||||
surface.push_request(lt::surface::ModifyTitleRequest(title));
|
||||
expect_eq(surface.peek_requests().size(), 1);
|
||||
|
||||
surface.push_request(lt::surface::ModifyResolutionRequest(resolution));
|
||||
surface.push_request(lt::surface::ModifyPositionRequest(position));
|
||||
expect_eq(surface.peek_requests().size(), 1 + 2);
|
||||
|
||||
surface.push_request(lt::surface::ModifyVisibilityRequest(false));
|
||||
surface.push_request(lt::surface::ModifyVisibilityRequest(true));
|
||||
surface.push_request(lt::surface::ModifyVisibilityRequest(false));
|
||||
expect_eq(surface.peek_requests().size(), 1 + 2 + 3);
|
||||
|
||||
system.tick(tick_info());
|
||||
expect_eq(surface.peek_requests().size(), 0);
|
||||
|
||||
expect_eq(surface.get_title(), title);
|
||||
expect_eq(surface.get_position(), position);
|
||||
expect_eq(surface.get_resolution(), resolution);
|
||||
|
||||
lt::log::debug("EVENT COUNT: {}", surface.peek_events().size());
|
||||
for (const auto &event : surface.peek_events())
|
||||
{
|
||||
const auto visitor = overloads {
|
||||
[&](auto event) { lt::log::debug("event: {}", event.to_string()); },
|
||||
};
|
||||
|
||||
std::visit(visitor, event);
|
||||
}
|
||||
};
|
||||
};
|
||||
// Suite raii = "raii"_suite = [] {
|
||||
// Case { "happy path won't throw" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// ignore = System { fixture.registry() };
|
||||
// };
|
||||
//
|
||||
// import test.test;
|
||||
// import test.expects;
|
||||
// import surface.system;
|
||||
// import surface.events;
|
||||
// import surface.requests;
|
||||
// import ecs.registry;
|
||||
// import memory.scope;
|
||||
// import memory.reference;
|
||||
// import logger;
|
||||
// import math.vec2;
|
||||
// import app.system;
|
||||
// import std;
|
||||
//
|
||||
// using ::lt::surface::SurfaceComponent;
|
||||
// using ::lt::surface::System;
|
||||
// using ::lt::test::Case;
|
||||
// using ::lt::test::expect_eq;
|
||||
// using ::lt::test::expect_ne;
|
||||
// using ::lt::test::expect_not_nullptr;
|
||||
// using ::lt::test::expect_throw;
|
||||
// using ::lt::test::Suite;
|
||||
// using ::std::ignore;
|
||||
// using ::lt::test::operator""_suite;
|
||||
//
|
||||
// [[nodiscard]] auto tick_info() -> lt::app::TickInfo
|
||||
// {
|
||||
// return {
|
||||
// .delta_time = std::chrono::milliseconds { 16 },
|
||||
// .budget = std::chrono::milliseconds { 10 },
|
||||
// .start_time = std::chrono::steady_clock::now(),
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// constexpr auto title = "TestWindow";
|
||||
// constexpr auto width = 800u;
|
||||
// constexpr auto height = 600u;
|
||||
// constexpr auto vsync = true;
|
||||
// constexpr auto visible = false;
|
||||
//
|
||||
// template<class... Ts>
|
||||
// struct overloads: Ts...
|
||||
// {
|
||||
// using Ts::operator()...;
|
||||
// };
|
||||
//
|
||||
// class Fixture
|
||||
// {
|
||||
// public:
|
||||
// [[nodiscard]] auto registry() -> lt::memory::Ref<lt::ecs::Registry>
|
||||
// {
|
||||
// return m_registry;
|
||||
// }
|
||||
//
|
||||
// auto create_component(
|
||||
// SurfaceComponent::CreateInfo info = SurfaceComponent::CreateInfo {
|
||||
// .title = title,
|
||||
// .resolution = { width, height },
|
||||
// .vsync = vsync,
|
||||
// .visible = visible,
|
||||
// }
|
||||
// ) -> std::optional<SurfaceComponent *>
|
||||
// {
|
||||
// auto entity = m_registry->create_entity();
|
||||
// m_system.create_surface_component(entity, info);
|
||||
//
|
||||
// return &m_registry->get<SurfaceComponent>(entity);
|
||||
// }
|
||||
//
|
||||
// void check_values(SurfaceComponent *component)
|
||||
// {
|
||||
// #ifdef LIGHT_PLATFORM_LINUX
|
||||
// expect_not_nullptr(component->get_native_data().display);
|
||||
// expect_ne(component->get_native_data().window, 0);
|
||||
// #endif
|
||||
//
|
||||
// expect_eq(component->get_resolution().x, width);
|
||||
// expect_eq(component->get_resolution().y, height);
|
||||
// expect_eq(component->get_title(), title);
|
||||
// expect_eq(component->is_vsync(), vsync);
|
||||
// expect_eq(component->is_visible(), visible);
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// lt::memory::Ref<lt::ecs::Registry> m_registry = lt::memory::create_ref<lt::ecs::Registry>();
|
||||
//
|
||||
// System m_system { m_registry };
|
||||
// };
|
||||
//
|
||||
//
|
||||
// Suite raii = "raii"_suite = [] {
|
||||
// Case { "happy path won't throw" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// ignore = System { fixture.registry() };
|
||||
// };
|
||||
//
|
||||
// Case { "many won't freeze/throw" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// for (auto idx : std::views::iota(0, 250))
|
||||
// {
|
||||
// ignore = System { fixture.registry() };
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// Case { "unhappy path throws" } = [] {
|
||||
// expect_throw([] { ignore = System { {} }; });
|
||||
// };
|
||||
//
|
||||
// Case { "post construct has correct state" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = System { fixture.registry() };
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
// };
|
||||
//
|
||||
// Case { "post destruct has correct state" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = lt::memory::create_scope<System>(fixture.registry());
|
||||
//
|
||||
// fixture.create_component();
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
|
||||
//
|
||||
// system.reset();
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
// };
|
||||
// };
|
||||
//
|
||||
// Suite system_events = "system_events"_suite = [] {
|
||||
// Case { "on_register won't throw" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = System { fixture.registry() };
|
||||
//
|
||||
// system.on_register();
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
// };
|
||||
//
|
||||
// Case { "on_unregister won't throw" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = System { fixture.registry() };
|
||||
//
|
||||
// system.on_register();
|
||||
// system.on_unregister();
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
// };
|
||||
// };
|
||||
//
|
||||
// Suite registry_events = "registry_events"_suite = [] {
|
||||
// Case { "on_construct<SurfaceComponent> initializes component" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
//
|
||||
// const auto &component = fixture.create_component();
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
|
||||
// fixture.check_values(*component);
|
||||
// };
|
||||
//
|
||||
// Case { "unhappy on_construct<SurfaceComponent> throws" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = System { fixture.registry() };
|
||||
//
|
||||
// expect_throw([&] { fixture.create_component({ .resolution = { width, 0 } }); });
|
||||
//
|
||||
// expect_throw([&] { fixture.create_component({ .resolution = { 0, height } }); });
|
||||
//
|
||||
// expect_throw([&] {
|
||||
// fixture.create_component(
|
||||
// { .title = "", .resolution = { SurfaceComponent::max_dimension + 1, height } }
|
||||
// );
|
||||
// });
|
||||
//
|
||||
// expect_throw([&] {
|
||||
// fixture.create_component(
|
||||
// { .title = "", .resolution = { width, SurfaceComponent::max_dimension + 1 } }
|
||||
// );
|
||||
// });
|
||||
//
|
||||
// auto big_str = std::string {};
|
||||
// big_str.resize(SurfaceComponent::max_title_length + 1);
|
||||
// expect_throw([&] {
|
||||
// fixture.create_component({ .title = big_str, .resolution = { width, height } });
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// Case { "unhappy on_construct<SurfaceComponent> removes component" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = System { fixture.registry() };
|
||||
//
|
||||
// expect_throw([&] { fixture.create_component({ .resolution = { width, 0 } }); });
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
// };
|
||||
//
|
||||
// Case { "on_destrroy<SurfaceComponent> cleans up component" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = lt::memory::create_scope<System>(fixture.registry());
|
||||
//
|
||||
// const auto &component = fixture.create_component();
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
|
||||
// fixture.check_values(*component);
|
||||
//
|
||||
// system.reset();
|
||||
// expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
|
||||
// };
|
||||
// };
|
||||
//
|
||||
// Suite tick = "tick"_suite = [] {
|
||||
// Case { "ticking on empty registry won't throw" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// System { fixture.registry() }.tick(tick_info());
|
||||
// };
|
||||
//
|
||||
// Case { "ticking on non-empty registry won't throw" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = System { fixture.registry() };
|
||||
//
|
||||
// fixture.create_component();
|
||||
// system.tick(tick_info());
|
||||
// };
|
||||
// };
|
||||
//
|
||||
// Suite tick_handles_events = "tick_handles_events"_suite = [] {
|
||||
// Case { "ticking clears previous tick's events" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = System { fixture.registry() };
|
||||
// auto &surface = **fixture.create_component();
|
||||
//
|
||||
// // flush window-creation events
|
||||
// system.tick(tick_info());
|
||||
// expect_eq(surface.peek_events().size(), 0);
|
||||
//
|
||||
// surface.push_event(lt::surface::MovedEvent({}, {}));
|
||||
// expect_eq(surface.peek_events().size(), 1);
|
||||
//
|
||||
// surface.push_event(lt::surface::ButtonPressedEvent({}));
|
||||
// expect_eq(surface.peek_events().size(), 2);
|
||||
//
|
||||
// system.tick(tick_info());
|
||||
// expect_eq(surface.peek_events().size(), 0);
|
||||
// };
|
||||
// };
|
||||
//
|
||||
// Suite tick_handles_requests = "tick_handles_requests"_suite = [] {
|
||||
// Case { "ticking clears requests" } = [] {
|
||||
// auto fixture = Fixture {};
|
||||
// auto system = System { fixture.registry() };
|
||||
// auto &surface = **fixture.create_component();
|
||||
//
|
||||
// constexpr auto title = "ABC";
|
||||
// constexpr auto position = lt::math::ivec2 { 50, 50 };
|
||||
// constexpr auto resolution = lt::math::uvec2 { 50, 50 };
|
||||
//
|
||||
// expect_eq(surface.peek_requests().size(), 0);
|
||||
//
|
||||
// surface.push_request(lt::surface::ModifyVisibilityRequest(true));
|
||||
// expect_eq(surface.peek_requests().size(), 1);
|
||||
// system.tick(tick_info());
|
||||
// expect_eq(surface.peek_requests().size(), 0);
|
||||
//
|
||||
// surface.push_request(lt::surface::ModifyTitleRequest(title));
|
||||
// expect_eq(surface.peek_requests().size(), 1);
|
||||
//
|
||||
// surface.push_request(lt::surface::ModifyResolutionRequest(resolution));
|
||||
// surface.push_request(lt::surface::ModifyPositionRequest(position));
|
||||
// expect_eq(surface.peek_requests().size(), 1 + 2);
|
||||
//
|
||||
// surface.push_request(lt::surface::ModifyVisibilityRequest(false));
|
||||
// surface.push_request(lt::surface::ModifyVisibilityRequest(true));
|
||||
// surface.push_request(lt::surface::ModifyVisibilityRequest(false));
|
||||
// expect_eq(surface.peek_requests().size(), 1 + 2 + 3);
|
||||
//
|
||||
// system.tick(tick_info());
|
||||
// expect_eq(surface.peek_requests().size(), 0);
|
||||
//
|
||||
// expect_eq(surface.get_title(), title);
|
||||
// expect_eq(surface.get_position(), position);
|
||||
// expect_eq(surface.get_resolution(), resolution);
|
||||
//
|
||||
// lt::log::debug("EVENT COUNT: {}", surface.peek_events().size());
|
||||
// for (const auto &event : surface.peek_events())
|
||||
// {
|
||||
// const auto visitor = overloads {
|
||||
// [&](auto event) { lt::log::debug("event: {}", event.to_string()); },
|
||||
// };
|
||||
//
|
||||
// std::visit(visitor, event);
|
||||
// }
|
||||
// };
|
||||
// };
|
||||
|
|
|
|||
1
modules/surface/wayland-protocols/.gitignore
vendored
Normal file
1
modules/surface/wayland-protocols/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*
|
||||
Loading…
Add table
Reference in a new issue