aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2021-01-18 22:56:18 +0100
committerladevieq <ladevie.quentin@gmail.com>2021-01-18 22:56:18 +0100
commit7c0d53684c638af98bece65edc7e744cae80806c (patch)
tree5736e296cbc15832b565f0143e059fa21bf79f7b /src
parent25125b2e23c02199bdefb3a638584465229fd833 (diff)
Event logic & handle resize & close for xcb windows
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp22
-rw-r--r--src/vk-renderer.cpp15
-rw-r--r--src/window.cpp75
3 files changed, 88 insertions, 24 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 03db2ab..56e8d08 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -55,17 +55,31 @@ int main() {
while(wnd.isOpen) {
wnd.poll_events();
+ for (auto event: wnd.events) {
+ switch(event.type) {
+ case EVENT_TYPES::RESIZE: {
+ renderer.recreate_swapchain();
+ renderer.mapped_data->width = event.width;
+ renderer.mapped_data->height = event.height;
+ break;
+ }
+ case EVENT_TYPES::QUIT: {
+ exit(1);
+ }
+ default: {
+ }
+ }
+ }
+
+ wnd.events.clear();
+
// To start a frame capture, call StartFrameCapture.
// You can specify NULL, NULL for the device to capture on if you have only one device and
// either no windows at all or only one window, and it will capture from that device.
// See the documentation below for a longer explanation
if(rdoc_api) rdoc_api->StartFrameCapture(NULL, NULL);
- auto start = std::chrono::high_resolution_clock::now();
renderer.compute();
- auto end = std::chrono::high_resolution_clock::now();
-
- std::cerr << "Image generation took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
// stop the capture
if(rdoc_api) rdoc_api->EndFrameCapture(NULL, NULL);
diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp
index d5511a9..e2e171e 100644
--- a/src/vk-renderer.cpp
+++ b/src/vk-renderer.cpp
@@ -155,9 +155,7 @@ void vkrenderer::compute() {
void vkrenderer::recreate_swapchain() {
VKRESULT(vkWaitForFences(device, 1, &submission_fences[frame_index], VK_TRUE, UINT64_MAX))
- destroy_swapchain();
-
- create_surface();
+ destroy_swapchain_images();
create_swapchain();
@@ -309,6 +307,8 @@ void vkrenderer::create_swapchain() {
surface_format = supported_formats[0];
+ VkSwapchainKHR old_swapchain = swapchain;
+
VkSwapchainCreateInfoKHR create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
create_info.pNext = nullptr;
@@ -325,10 +325,13 @@ void vkrenderer::create_swapchain() {
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
create_info.clipped = VK_TRUE;
- create_info.oldSwapchain = swapchain;
+ create_info.oldSwapchain = old_swapchain;
VKRESULT(vkCreateSwapchainKHR(device, &create_info, nullptr, &swapchain))
+ if (old_swapchain != VK_NULL_HANDLE) {
+ vkDestroySwapchainKHR(device, old_swapchain, nullptr);
+ }
swapchain_images_count = 0;
VKRESULT(vkGetSwapchainImagesKHR(device, swapchain, (uint32_t*)&swapchain_images_count, VK_NULL_HANDLE))
@@ -560,7 +563,7 @@ void vkrenderer::create_input_buffer(const input_data& inputs) {
}
-void vkrenderer::destroy_swapchain() {
+void vkrenderer::destroy_swapchain_images() {
if (swapchain != VK_NULL_HANDLE) {
for (auto view: swapchain_images_views) {
vkDestroyImageView(device, view, nullptr);
@@ -568,8 +571,6 @@ void vkrenderer::destroy_swapchain() {
swapchain_images_views.clear();
swapchain_images.clear();
-
- vkDestroySwapchainKHR(device, swapchain, nullptr);
}
}
diff --git a/src/window.cpp b/src/window.cpp
index 7662295..d1d2f4f 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -11,6 +11,9 @@ window::window(uint32_t width, uint32_t height)
auto setup = xcb_get_setup (connection);
auto screen_info = xcb_setup_roots_iterator(setup).data;
+ xcb_event_mask_t events[] = {
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY,
+ };
xcb_create_window(
connection,
XCB_COPY_FROM_PARENT,
@@ -23,8 +26,29 @@ window::window(uint32_t width, uint32_t height)
10,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen_info->root_visual,
- 0,
- nullptr
+ XCB_CW_EVENT_MASK,
+ events
+ );
+
+ // Ask for WM_PROTOCOLS atom
+ auto protocols_id = xcb_intern_atom(connection, true, 12, "WM_PROTOCOLS");
+ auto protocols_atom = xcb_intern_atom_reply(connection, protocols_id, NULL)->atom;
+
+ // Ask for WM_DELETE_WINDOW atom
+ auto win_delete_id = xcb_intern_atom(connection, false, 16, "WM_DELETE_WINDOW");
+ win_delete_atom = xcb_intern_atom_reply(connection, win_delete_id, NULL)->atom;
+
+ // Allow the window to receive win close events
+ // https://lists.freedesktop.org/archives/xcb/2010-December/006713.html
+ xcb_change_property(
+ connection,
+ XCB_PROP_MODE_REPLACE,
+ win,
+ protocols_atom,
+ 4, // Predefined value for atom type
+ 32,
+ 1,
+ &win_delete_atom
);
xcb_map_window(connection, win);
@@ -32,6 +56,41 @@ window::window(uint32_t width, uint32_t height)
isOpen = true;
}
+
+void window::poll_events() {
+ xcb_generic_event_t *event;
+ while((event = xcb_poll_for_event (connection))) {
+ switch(event->response_type & ~0x80) {
+ case XCB_CONFIGURE_NOTIFY: {
+ auto notify_event = (xcb_configure_notify_event_t*)event;
+
+ if (width != notify_event->width || height != notify_event->height) {
+ events.push_back({
+ .width = notify_event->width,
+ .height = notify_event->height,
+ .type = EVENT_TYPES::RESIZE
+ });
+
+ width = notify_event->width;
+ height = notify_event->height;
+ }
+
+ break;
+ }
+ case XCB_CLIENT_MESSAGE: {
+ auto client_message_event = (xcb_client_message_event_t*)event;
+ if (client_message_event->data.data32[0] == win_delete_atom) {
+ events.push_back({ .type = EVENT_TYPES::QUIT });
+ }
+ }
+ default: {
+ }
+ }
+
+ free(event);
+ }
+}
+
#elif defined(WINDOWS)
LRESULT CALLBACK window::window_procedure(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) {
window* win = nullptr;
@@ -102,17 +161,7 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
break;
}
case WM_SIZE: {
- RECT rect;
- if(GetWindowRect(hwnd, &rect))
- {
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
- }
-
- if (renderer != nullptr) {
- renderer->recreate_swapchain();
- break;
- }
+ event.push_back({ EVENT_TYPES::RESIZE });
}
default:
return DefWindowProc(hwnd, umsg, wparam, lparam);