aboutsummaryrefslogtreecommitdiffstats
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
parent25125b2e23c02199bdefb3a638584465229fd833 (diff)
Event logic & handle resize & close for xcb windows
-rw-r--r--include/vk-renderer.hpp6
-rw-r--r--include/window.hpp37
-rw-r--r--src/main.cpp22
-rw-r--r--src/vk-renderer.cpp15
-rw-r--r--src/window.cpp75
5 files changed, 112 insertions, 43 deletions
diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp
index a8c5d2b..aa51383 100644
--- a/include/vk-renderer.hpp
+++ b/include/vk-renderer.hpp
@@ -18,6 +18,8 @@ class vkrenderer {
void recreate_swapchain();
+ struct input_data* mapped_data;
+
private:
void create_instance();
@@ -43,7 +45,7 @@ class vkrenderer {
void create_input_buffer(const input_data& inputs);
- void destroy_swapchain();
+ void destroy_swapchain_images();
void select_physical_device();
@@ -88,8 +90,6 @@ class vkrenderer {
std::vector<VkImageView> swapchain_images_views;
uint32_t current_image_index;
- struct input_data* mapped_data;
-
window& wnd;
};
diff --git a/include/window.hpp b/include/window.hpp
index 3298d36..dae4f00 100644
--- a/include/window.hpp
+++ b/include/window.hpp
@@ -2,6 +2,7 @@
#define __WINDOW_HPP_
#include <cstdint>
+#include <vector>
#include "defines.hpp"
@@ -9,23 +10,20 @@ class vkrenderer;
#if defined(LINUX)
#include <xcb/xcb.h>
+#elif defined(WINDOWS)
+#include <Windows.h>
+#endif
-class window {
- public:
- window(uint32_t width, uint32_t height);
-
- void poll_events();
-
- xcb_connection_t* connection;
- xcb_window_t win;
-
- uint32_t width;
- uint32_t height;
+enum EVENT_TYPES: int32_t {
+ QUIT,
+ RESIZE,
+};
- bool isOpen;
+struct event {
+ uint32_t width;
+ uint32_t height;
+ EVENT_TYPES type;
};
-#elif defined(WINDOWS)
-#include <Windows.h>
class window {
public:
@@ -33,18 +31,25 @@ class window {
void poll_events();
+
+#if defined(WINDOWS)
LRESULT message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK window_procedure(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam);
HWND win_handle;
- vkrenderer* renderer = nullptr;
+#elif defined(LINUX)
+ xcb_connection_t* connection;
+ xcb_window_t win;
+ xcb_atom_t win_delete_atom;
+#endif
+
+ std::vector<event> events;
uint32_t width;
uint32_t height;
bool isOpen;
};
-#endif
#endif // !__WINDOW_HPP_
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);