initial
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
project(loft_window)
|
||||
|
||||
file(GLOB FILES src/*.c src/*.cpp)
|
||||
|
||||
add_library(${PROJECT_NAME} ${FILES})
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/include/"
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
loft_base
|
||||
${SDL2_LIBRARIES}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${PROJECT_SOURCE_DIR}/include/
|
||||
)
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Created by martin on 11/12/23.
|
||||
//
|
||||
|
||||
#ifndef LOFT_SDLWINDOW_H
|
||||
#define LOFT_SDLWINDOW_H
|
||||
|
||||
#include "Window.hpp"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <utility>
|
||||
#include <volk.h>
|
||||
#include <string>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace lft::win {
|
||||
|
||||
class SDLWindow : public Window {
|
||||
private:
|
||||
SDL_Window *m_pWindow;
|
||||
SDL_Surface *m_pSurface;
|
||||
|
||||
VkExtent2D m_extent;
|
||||
|
||||
public:
|
||||
// rule of five
|
||||
|
||||
SDLWindow(const SDLWindow&) = delete;
|
||||
SDLWindow(SDLWindow&& other) :
|
||||
m_pWindow(std::exchange(other.m_pWindow, nullptr)),
|
||||
m_pSurface(std::exchange(other.m_pSurface, nullptr)){
|
||||
|
||||
}
|
||||
|
||||
SDLWindow& operator=(const SDLWindow&) = delete;
|
||||
SDLWindow& operator=(SDLWindow&& other) {
|
||||
*this = std::move(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SDL_Window* get_handle() const { return m_pWindow; }
|
||||
|
||||
SDLWindow(const std::string name, VkRect2D rect);
|
||||
|
||||
void resize() override;
|
||||
|
||||
VkExtent2D get_size() const override;
|
||||
|
||||
Surface create_surface(const Instance* instance) const override;
|
||||
|
||||
bool is_open() const override;
|
||||
|
||||
int32_t poll_event(SDL_Event *pOutEvent) const override;
|
||||
|
||||
std::vector<std::string> get_required_extensions() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //LOFT_SDLWINDOW_H
|
||||
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include "Gpu.hpp"
|
||||
#include "props.hpp"
|
||||
#include "resources/Image.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <volk.h>
|
||||
|
||||
struct ImageResourceLayout;
|
||||
|
||||
class Swapchain {
|
||||
private:
|
||||
const Gpu* m_gpu;
|
||||
VkSurfaceKHR m_surface;
|
||||
VkSwapchainKHR m_swapchain;
|
||||
|
||||
VkSurfaceFormatKHR m_format;
|
||||
VkExtent2D m_extent;
|
||||
|
||||
unsigned m_numImages;
|
||||
unsigned m_numFrames;
|
||||
|
||||
VkImage *m_pImages;
|
||||
VkImageView *m_pImageViews;
|
||||
|
||||
VkSurfaceFormatKHR choose_format();
|
||||
VkPresentModeKHR choose_present_mode();
|
||||
VkExtent2D choose_extent(VkExtent2D actualExtent = {0, 0});
|
||||
|
||||
ResultCode create_swapchain();
|
||||
|
||||
ResultCode get_images(unsigned *pOutCount, VkImage *pOut);
|
||||
|
||||
ResultCode create_views();
|
||||
|
||||
std::vector<Image> m_images;
|
||||
std::vector<ImageView> m_views;
|
||||
|
||||
public:
|
||||
GET(m_format, format);
|
||||
GET(m_swapchain, swapchain);
|
||||
GET(m_extent, extent);
|
||||
GET(m_numImages, num_images);
|
||||
REF(m_images, images);
|
||||
REF(m_views, views);
|
||||
GET(m_surface, surface);
|
||||
|
||||
const Image* get_image(uint32_t idx) const {
|
||||
if(idx >= m_numImages) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &m_images[idx];
|
||||
}
|
||||
|
||||
VkResult get_next_image_idx(VkSemaphore signalSemaphore, VkFence signalFence, uint32_t *pOutImageIdx) const {
|
||||
return vkAcquireNextImageKHR(m_gpu->dev(), m_swapchain, UINT64_MAX, signalSemaphore, signalFence, pOutImageIdx);
|
||||
}
|
||||
|
||||
void present(std::vector<VkSemaphore> waitSemaphores,
|
||||
uint32_t imageIdx) const {
|
||||
VkPresentInfoKHR presentInfo = {};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
presentInfo.waitSemaphoreCount = (uint32_t)waitSemaphores.size();
|
||||
presentInfo.pWaitSemaphores = waitSemaphores.data();
|
||||
presentInfo.swapchainCount = 1;
|
||||
presentInfo.pSwapchains = &m_swapchain;
|
||||
presentInfo.pImageIndices = &imageIdx;
|
||||
|
||||
m_gpu->enqueue_present(&presentInfo);
|
||||
}
|
||||
|
||||
void cleanup();
|
||||
|
||||
void resize(VkExtent2D size);
|
||||
|
||||
Swapchain(const Gpu* gpu, VkExtent2D extent, Surface* surface);
|
||||
};
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <volk.h>
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Surface.hpp"
|
||||
#include "Instance.hpp"
|
||||
|
||||
namespace lft::win {
|
||||
|
||||
/**
|
||||
* Universal interface for windows.
|
||||
* WARNING: It is not responsible for interacting with some graphics API!
|
||||
* Instead, it should contain a function that Gpu interface will call by itself
|
||||
* when ready.
|
||||
*/
|
||||
|
||||
class Window {
|
||||
public:
|
||||
virtual void resize() = 0;
|
||||
|
||||
[[nodiscard("Getter should not be discarded")]]
|
||||
virtual VkExtent2D get_size() const = 0;
|
||||
|
||||
bool has_size(VkExtent2D size) const {
|
||||
return get_size().width == size.width &&
|
||||
get_size().height == size.height;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual bool is_open() const = 0;
|
||||
|
||||
virtual int32_t poll_event(SDL_Event *pOutEvent) const = 0;
|
||||
|
||||
virtual std::vector<std::string> get_required_extensions() const = 0;
|
||||
|
||||
virtual Surface create_surface(const Instance* instance) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
#define CURSOR_num_glyphs 154
|
||||
#define CURSOR_X_cursor 0
|
||||
#define CURSOR_arrow 2
|
||||
#define CURSOR_based_arrow_down 4
|
||||
#define CURSOR_based_arrow_up 6
|
||||
#define CURSOR_boat 8
|
||||
#define CURSOR_bogosity 10
|
||||
#define CURSOR_bottom_left_corner 12
|
||||
#define CURSOR_bottom_right_corner 14
|
||||
#define CURSOR_bottom_side 16
|
||||
#define CURSOR_bottom_tee 18
|
||||
#define CURSOR_box_spiral 20
|
||||
#define CURSOR_center_ptr 22
|
||||
#define CURSOR_circle 24
|
||||
#define CURSOR_clock 26
|
||||
#define CURSOR_coffee_mug 28
|
||||
#define CURSOR_cross 30
|
||||
#define CURSOR_cross_reverse 32
|
||||
#define CURSOR_crosshair 34
|
||||
#define CURSOR_diamond_cross 36
|
||||
#define CURSOR_dot 38
|
||||
#define CURSOR_dotbox 40
|
||||
#define CURSOR_double_arrow 42
|
||||
#define CURSOR_draft_large 44
|
||||
#define CURSOR_draft_small 46
|
||||
#define CURSOR_draped_box 48
|
||||
#define CURSOR_exchange 50
|
||||
#define CURSOR_fleur 52
|
||||
#define CURSOR_gobbler 54
|
||||
#define CURSOR_gumby 56
|
||||
#define CURSOR_hand1 58
|
||||
#define CURSOR_hand2 60
|
||||
#define CURSOR_heart 62
|
||||
#define CURSOR_icon 64
|
||||
#define CURSOR_iron_cross 66
|
||||
#define CURSOR_left_ptr 68
|
||||
#define CURSOR_left_side 70
|
||||
#define CURSOR_left_tee 72
|
||||
#define CURSOR_leftbutton 74
|
||||
#define CURSOR_ll_angle 76
|
||||
#define CURSOR_lr_angle 78
|
||||
#define CURSOR_man 80
|
||||
#define CURSOR_middlebutton 82
|
||||
#define CURSOR_mouse 84
|
||||
#define CURSOR_pencil 86
|
||||
#define CURSOR_pirate 88
|
||||
#define CURSOR_plus 90
|
||||
#define CURSOR_question_arrow 92
|
||||
#define CURSOR_right_ptr 94
|
||||
#define CURSOR_right_side 96
|
||||
#define CURSOR_right_tee 98
|
||||
#define CURSOR_rightbutton 100
|
||||
#define CURSOR_rtl_logo 102
|
||||
#define CURSOR_sailboat 104
|
||||
#define CURSOR_sb_down_arrow 106
|
||||
#define CURSOR_sb_h_double_arrow 108
|
||||
#define CURSOR_sb_left_arrow 110
|
||||
#define CURSOR_sb_right_arrow 112
|
||||
#define CURSOR_sb_up_arrow 114
|
||||
#define CURSOR_sb_v_double_arrow 116
|
||||
#define CURSOR_shuttle 118
|
||||
#define CURSOR_sizing 120
|
||||
#define CURSOR_spider 122
|
||||
#define CURSOR_spraycan 124
|
||||
#define CURSOR_star 126
|
||||
#define CURSOR_target 128
|
||||
#define CURSOR_tcross 130
|
||||
#define CURSOR_top_left_arrow 132
|
||||
#define CURSOR_top_left_corner 134
|
||||
#define CURSOR_top_right_corner 136
|
||||
#define CURSOR_top_side 138
|
||||
#define CURSOR_top_tee 140
|
||||
#define CURSOR_trek 142
|
||||
#define CURSOR_ul_angle 144
|
||||
#define CURSOR_umbrella 146
|
||||
#define CURSOR_ur_angle 148
|
||||
#define CURSOR_watch 150
|
||||
#define CURSOR_xterm 152
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum EventType {
|
||||
NONE_EVENT_TYPE,
|
||||
KEY_EVENT_TYPE,
|
||||
BUTTON_EVENT_TYPE,
|
||||
MOTION_EVENT_TYPE,
|
||||
TRANSFORM_EVENT_TYPE
|
||||
} EventType;
|
||||
|
||||
typedef enum KeyState {
|
||||
STATE_RELEASED = 0,
|
||||
STATE_PRESSED = 1,
|
||||
} KeyState;
|
||||
|
||||
typedef struct KeyEvent {
|
||||
EventType type;
|
||||
KeyState state;
|
||||
int key;
|
||||
char *txt;
|
||||
} KeyEvent;
|
||||
|
||||
typedef struct ButtonEvent {
|
||||
EventType type;
|
||||
KeyState state;
|
||||
int button;
|
||||
int x, y;
|
||||
} ButtonEvent;
|
||||
|
||||
typedef struct MotionEvent {
|
||||
EventType type;
|
||||
int x, y;
|
||||
} MotionEvent;
|
||||
|
||||
typedef struct TransformEvent {
|
||||
EventType type;
|
||||
int x, y;
|
||||
int width, height;
|
||||
} TransformEvent;
|
||||
|
||||
typedef union WindowEvent {
|
||||
EventType type;
|
||||
KeyEvent key;
|
||||
ButtonEvent button;
|
||||
MotionEvent motion;
|
||||
TransformEvent transform;
|
||||
} WindowEvent;
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
#include "event.h"
|
||||
|
||||
inline float get_scroll_y(const ButtonEvent *pEvent) {
|
||||
if(pEvent->button == 4) {
|
||||
return 1.0f;
|
||||
} else if(pEvent->button == 5) {
|
||||
return -1.0f;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
#define KEY_BackSpace 0xff08 /* Back space, back char */
|
||||
#define KEY_Tab 0xff09
|
||||
#define KEY_Linefeed 0xff0a /* Linefeed, LF */
|
||||
#define KEY_Clear 0xff0b
|
||||
#define KEY_Return 0xff0d /* Return, enter */
|
||||
#define KEY_Pause 0xff13 /* Pause, hold */
|
||||
#define KEY_Scroll_Lock 0xff14
|
||||
#define KEY_Sys_Req 0xff15
|
||||
#define KEY_Escape 0xff1b
|
||||
#define KEY_Delete 0xffff /* Delete, rubout */
|
||||
|
||||
|
||||
|
||||
/* Cursor control & motion */
|
||||
|
||||
#define KEY_Home 0xff50
|
||||
#define KEY_Left 0xff51 /* Move left, left arrow */
|
||||
#define KEY_Up 0xff52 /* Move up, up arrow */
|
||||
#define KEY_Right 0xff53 /* Move right, right arrow */
|
||||
#define KEY_Down 0xff54 /* Move down, down arrow */
|
||||
#define KEY_Prior 0xff55 /* Prior, previous */
|
||||
#define KEY_Page_Up 0xff55
|
||||
#define KEY_Next 0xff56 /* Next */
|
||||
#define KEY_Page_Down 0xff56
|
||||
#define KEY_End 0xff57 /* EOL */
|
||||
#define KEY_Begin 0xff58 /* BOL */
|
||||
|
||||
|
||||
/* Misc functions */
|
||||
|
||||
#define KEY_Select 0xff60 /* Select, mark */
|
||||
#define KEY_Print 0xff61
|
||||
#define KEY_Execute 0xff62 /* Execute, run, do */
|
||||
#define KEY_Insert 0xff63 /* Insert, insert here */
|
||||
#define KEY_Undo 0xff65
|
||||
#define KEY_Redo 0xff66 /* Redo, again */
|
||||
#define KEY_Menu 0xff67
|
||||
#define KEY_Find 0xff68 /* Find, search */
|
||||
#define KEY_Cancel 0xff69 /* Cancel, stop, abort, exit */
|
||||
#define KEY_Help 0xff6a /* Help */
|
||||
#define KEY_Break 0xff6b
|
||||
#define KEY_Mode_switch 0xff7e /* Character set switch */
|
||||
#define KEY_script_switch 0xff7e /* Alias for mode_switch */
|
||||
#define KEY_Num_Lock 0xff7f
|
||||
|
||||
/* Modifiers */
|
||||
|
||||
#define KEY_Shift_L 0xffe1 /* Left shift */
|
||||
#define KEY_Shift_R 0xffe2 /* Right shift */
|
||||
#define KEY_Control_L 0xffe3 /* Left control */
|
||||
#define KEY_Control_R 0xffe4 /* Right control */
|
||||
#define KEY_Caps_Lock 0xffe5 /* Caps lock */
|
||||
#define KEY_Shift_Lock 0xffe6 /* Shift lock */
|
||||
|
||||
#define KEY_Meta_L 0xffe7 /* Left meta */
|
||||
#define KEY_Meta_R 0xffe8 /* Right meta */
|
||||
#define KEY_Alt_L 0xffe9 /* Left alt */
|
||||
#define KEY_Alt_R 0xffea /* Right alt */
|
||||
#define KEY_Super_L 0xffeb /* Left super */
|
||||
#define KEY_Super_R 0xffec /* Right super */
|
||||
#define KEY_Hyper_L 0xffed /* Left hyper */
|
||||
#define KEY_Hyper_R 0xffee /* Right hyper */
|
||||
|
||||
|
||||
/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */
|
||||
|
||||
#define KEY_KP_Space 0xff80 /* Space */
|
||||
#define KEY_KP_Tab 0xff89
|
||||
#define KEY_KP_Enter 0xff8d /* Enter */
|
||||
#define KEY_KP_F1 0xff91 /* PF1, KP_A, ... */
|
||||
#define KEY_KP_F2 0xff92
|
||||
#define KEY_KP_F3 0xff93
|
||||
#define KEY_KP_F4 0xff94
|
||||
#define KEY_KP_Home 0xff95
|
||||
#define KEY_KP_Left 0xff96
|
||||
#define KEY_KP_Up 0xff97
|
||||
#define KEY_KP_Right 0xff98
|
||||
#define KEY_KP_Down 0xff99
|
||||
#define KEY_KP_Prior 0xff9a
|
||||
#define KEY_KP_Page_Up 0xff9a
|
||||
#define KEY_KP_Next 0xff9b
|
||||
#define KEY_KP_Page_Down 0xff9b
|
||||
#define KEY_KP_End 0xff9c
|
||||
#define KEY_KP_Begin 0xff9d
|
||||
#define KEY_KP_Insert 0xff9e
|
||||
#define KEY_KP_Delete 0xff9f
|
||||
#define KEY_KP_Equal 0xffbd /* Equals */
|
||||
#define KEY_KP_Multiply 0xffaa
|
||||
#define KEY_KP_Add 0xffab
|
||||
#define KEY_KP_Separator 0xffac /* Separator, often comma */
|
||||
#define KEY_KP_Subtract 0xffad
|
||||
#define KEY_KP_Decimal 0xffae
|
||||
#define KEY_KP_Divide 0xffaf
|
||||
|
||||
#define KEY_KP_0 0xffb0
|
||||
#define KEY_KP_1 0xffb1
|
||||
#define KEY_KP_2 0xffb2
|
||||
#define KEY_KP_3 0xffb3
|
||||
#define KEY_KP_4 0xffb4
|
||||
#define KEY_KP_5 0xffb5
|
||||
#define KEY_KP_6 0xffb6
|
||||
#define KEY_KP_7 0xffb7
|
||||
#define KEY_KP_8 0xffb8
|
||||
#define KEY_KP_9 0xffb9
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Auxiliary functions; note the duplicate definitions for left and right
|
||||
* function keys; Sun keyboards and a few other manufacturers have such
|
||||
* function key groups on the left and/or right sides of the keyboard.
|
||||
* We've not found a keyboard with more than 35 function keys total.
|
||||
*/
|
||||
|
||||
#define KEY_F1 0xffbe
|
||||
#define KEY_F2 0xffbf
|
||||
#define KEY_F3 0xffc0
|
||||
#define KEY_F4 0xffc1
|
||||
#define KEY_F5 0xffc2
|
||||
#define KEY_F6 0xffc3
|
||||
#define KEY_F7 0xffc4
|
||||
#define KEY_F8 0xffc5
|
||||
#define KEY_F9 0xffc6
|
||||
#define KEY_F10 0xffc7
|
||||
#define KEY_F11 0xffc8
|
||||
#define KEY_L1 0xffc8
|
||||
#define KEY_F12 0xffc9
|
||||
#define KEY_L2 0xffc9
|
||||
#define KEY_F13 0xffca
|
||||
#define KEY_L3 0xffca
|
||||
#define KEY_F14 0xffcb
|
||||
#define KEY_L4 0xffcb
|
||||
#define KEY_F15 0xffcc
|
||||
#define KEY_L5 0xffcc
|
||||
#define KEY_F16 0xffcd
|
||||
#define KEY_L6 0xffcd
|
||||
#define KEY_F17 0xffce
|
||||
#define KEY_L7 0xffce
|
||||
#define KEY_F18 0xffcf
|
||||
#define KEY_L8 0xffcf
|
||||
#define KEY_F19 0xffd0
|
||||
#define KEY_L9 0xffd0
|
||||
#define KEY_F20 0xffd1
|
||||
#define KEY_L10 0xffd1
|
||||
#define KEY_F21 0xffd2
|
||||
#define KEY_R1 0xffd2
|
||||
#define KEY_F22 0xffd3
|
||||
#define KEY_R2 0xffd3
|
||||
#define KEY_F23 0xffd4
|
||||
#define KEY_R3 0xffd4
|
||||
#define KEY_F24 0xffd5
|
||||
#define KEY_R4 0xffd5
|
||||
#define KEY_F25 0xffd6
|
||||
#define KEY_R5 0xffd6
|
||||
#define KEY_F26 0xffd7
|
||||
#define KEY_R6 0xffd7
|
||||
#define KEY_F27 0xffd8
|
||||
#define KEY_R7 0xffd8
|
||||
#define KEY_F28 0xffd9
|
||||
#define KEY_R8 0xffd9
|
||||
#define KEY_F29 0xffda
|
||||
#define KEY_R9 0xffda
|
||||
#define KEY_F30 0xffdb
|
||||
#define KEY_R10 0xffdb
|
||||
#define KEY_F31 0xffdc
|
||||
#define KEY_R11 0xffdc
|
||||
#define KEY_F32 0xffdd
|
||||
#define KEY_R12 0xffdd
|
||||
#define KEY_F33 0xffde
|
||||
#define KEY_R13 0xffde
|
||||
#define KEY_F34 0xffdf
|
||||
#define KEY_R14 0xffdf
|
||||
#define KEY_F35 0xffe0
|
||||
#define KEY_R15 0xffe0
|
||||
|
||||
#define KEY_space 0x0020 /* U+0020 SPACE */
|
||||
#define KEY_exclam 0x0021 /* U+0021 EXCLAMATION MARK */
|
||||
#define KEY_quotedbl 0x0022 /* U+0022 QUOTATION MARK */
|
||||
#define KEY_numbersign 0x0023 /* U+0023 NUMBER SIGN */
|
||||
#define KEY_dollar 0x0024 /* U+0024 DOLLAR SIGN */
|
||||
#define KEY_percent 0x0025 /* U+0025 PERCENT SIGN */
|
||||
#define KEY_ampersand 0x0026 /* U+0026 AMPERSAND */
|
||||
#define KEY_apostrophe 0x0027 /* U+0027 APOSTROPHE */
|
||||
#define KEY_quoteright 0x0027 /* deprecated */
|
||||
#define KEY_parenleft 0x0028 /* U+0028 LEFT PARENTHESIS */
|
||||
#define KEY_parenright 0x0029 /* U+0029 RIGHT PARENTHESIS */
|
||||
#define KEY_asterisk 0x002a /* U+002A ASTERISK */
|
||||
#define KEY_plus 0x002b /* U+002B PLUS SIGN */
|
||||
#define KEY_comma 0x002c /* U+002C COMMA */
|
||||
#define KEY_minus 0x002d /* U+002D HYPHEN-MINUS */
|
||||
#define KEY_period 0x002e /* U+002E FULL STOP */
|
||||
#define KEY_slash 0x002f /* U+002F SOLIDUS */
|
||||
#define KEY_0 0x0030 /* U+0030 DIGIT ZERO */
|
||||
#define KEY_1 0x0031 /* U+0031 DIGIT ONE */
|
||||
#define KEY_2 0x0032 /* U+0032 DIGIT TWO */
|
||||
#define KEY_3 0x0033 /* U+0033 DIGIT THREE */
|
||||
#define KEY_4 0x0034 /* U+0034 DIGIT FOUR */
|
||||
#define KEY_5 0x0035 /* U+0035 DIGIT FIVE */
|
||||
#define KEY_6 0x0036 /* U+0036 DIGIT SIX */
|
||||
#define KEY_7 0x0037 /* U+0037 DIGIT SEVEN */
|
||||
#define KEY_8 0x0038 /* U+0038 DIGIT EIGHT */
|
||||
#define KEY_9 0x0039 /* U+0039 DIGIT NINE */
|
||||
#define KEY_colon 0x003a /* U+003A COLON */
|
||||
#define KEY_semicolon 0x003b /* U+003B SEMICOLON */
|
||||
#define KEY_less 0x003c /* U+003C LESS-THAN SIGN */
|
||||
#define KEY_equal 0x003d /* U+003D EQUALS SIGN */
|
||||
#define KEY_greater 0x003e /* U+003E GREATER-THAN SIGN */
|
||||
#define KEY_question 0x003f /* U+003F QUESTION MARK */
|
||||
#define KEY_at 0x0040 /* U+0040 COMMERCIAL AT */
|
||||
#define KEY_A 0x0041 /* U+0041 LATIN CAPITAL LETTER A */
|
||||
#define KEY_B 0x0042 /* U+0042 LATIN CAPITAL LETTER B */
|
||||
#define KEY_C 0x0043 /* U+0043 LATIN CAPITAL LETTER C */
|
||||
#define KEY_D 0x0044 /* U+0044 LATIN CAPITAL LETTER D */
|
||||
#define KEY_E 0x0045 /* U+0045 LATIN CAPITAL LETTER E */
|
||||
#define KEY_F 0x0046 /* U+0046 LATIN CAPITAL LETTER F */
|
||||
#define KEY_G 0x0047 /* U+0047 LATIN CAPITAL LETTER G */
|
||||
#define KEY_H 0x0048 /* U+0048 LATIN CAPITAL LETTER H */
|
||||
#define KEY_I 0x0049 /* U+0049 LATIN CAPITAL LETTER I */
|
||||
#define KEY_J 0x004a /* U+004A LATIN CAPITAL LETTER J */
|
||||
#define KEY_K 0x004b /* U+004B LATIN CAPITAL LETTER K */
|
||||
#define KEY_L 0x004c /* U+004C LATIN CAPITAL LETTER L */
|
||||
#define KEY_M 0x004d /* U+004D LATIN CAPITAL LETTER M */
|
||||
#define KEY_N 0x004e /* U+004E LATIN CAPITAL LETTER N */
|
||||
#define KEY_O 0x004f /* U+004F LATIN CAPITAL LETTER O */
|
||||
#define KEY_P 0x0050 /* U+0050 LATIN CAPITAL LETTER P */
|
||||
#define KEY_Q 0x0051 /* U+0051 LATIN CAPITAL LETTER Q */
|
||||
#define KEY_R 0x0052 /* U+0052 LATIN CAPITAL LETTER R */
|
||||
#define KEY_S 0x0053 /* U+0053 LATIN CAPITAL LETTER S */
|
||||
#define KEY_T 0x0054 /* U+0054 LATIN CAPITAL LETTER T */
|
||||
#define KEY_U 0x0055 /* U+0055 LATIN CAPITAL LETTER U */
|
||||
#define KEY_V 0x0056 /* U+0056 LATIN CAPITAL LETTER V */
|
||||
#define KEY_W 0x0057 /* U+0057 LATIN CAPITAL LETTER W */
|
||||
#define KEY_X 0x0058 /* U+0058 LATIN CAPITAL LETTER X */
|
||||
#define KEY_Y 0x0059 /* U+0059 LATIN CAPITAL LETTER Y */
|
||||
#define KEY_Z 0x005a /* U+005A LATIN CAPITAL LETTER Z */
|
||||
#define KEY_bracketleft 0x005b /* U+005B LEFT SQUARE BRACKET */
|
||||
#define KEY_backslash 0x005c /* U+005C REVERSE SOLIDUS */
|
||||
#define KEY_bracketright 0x005d /* U+005D RIGHT SQUARE BRACKET */
|
||||
#define KEY_asciicircum 0x005e /* U+005E CIRCUMFLEX ACCENT */
|
||||
#define KEY_underscore 0x005f /* U+005F LOW LINE */
|
||||
#define KEY_grave 0x0060 /* U+0060 GRAVE ACCENT */
|
||||
#define KEY_quoteleft 0x0060 /* deprecated */
|
||||
#define KEY_a 0x0061 /* U+0061 LATIN SMALL LETTER A */
|
||||
#define KEY_b 0x0062 /* U+0062 LATIN SMALL LETTER B */
|
||||
#define KEY_c 0x0063 /* U+0063 LATIN SMALL LETTER C */
|
||||
#define KEY_d 0x0064 /* U+0064 LATIN SMALL LETTER D */
|
||||
#define KEY_e 0x0065 /* U+0065 LATIN SMALL LETTER E */
|
||||
#define KEY_f 0x0066 /* U+0066 LATIN SMALL LETTER F */
|
||||
#define KEY_g 0x0067 /* U+0067 LATIN SMALL LETTER G */
|
||||
#define KEY_h 0x0068 /* U+0068 LATIN SMALL LETTER H */
|
||||
#define KEY_i 0x0069 /* U+0069 LATIN SMALL LETTER I */
|
||||
#define KEY_j 0x006a /* U+006A LATIN SMALL LETTER J */
|
||||
#define KEY_k 0x006b /* U+006B LATIN SMALL LETTER K */
|
||||
#define KEY_l 0x006c /* U+006C LATIN SMALL LETTER L */
|
||||
#define KEY_m 0x006d /* U+006D LATIN SMALL LETTER M */
|
||||
#define KEY_n 0x006e /* U+006E LATIN SMALL LETTER N */
|
||||
#define KEY_o 0x006f /* U+006F LATIN SMALL LETTER O */
|
||||
#define KEY_p 0x0070 /* U+0070 LATIN SMALL LETTER P */
|
||||
#define KEY_q 0x0071 /* U+0071 LATIN SMALL LETTER Q */
|
||||
#define KEY_r 0x0072 /* U+0072 LATIN SMALL LETTER R */
|
||||
#define KEY_s 0x0073 /* U+0073 LATIN SMALL LETTER S */
|
||||
#define KEY_t 0x0074 /* U+0074 LATIN SMALL LETTER T */
|
||||
#define KEY_u 0x0075 /* U+0075 LATIN SMALL LETTER U */
|
||||
#define KEY_v 0x0076 /* U+0076 LATIN SMALL LETTER V */
|
||||
#define KEY_w 0x0077 /* U+0077 LATIN SMALL LETTER W */
|
||||
#define KEY_x 0x0078 /* U+0078 LATIN SMALL LETTER X */
|
||||
#define KEY_y 0x0079 /* U+0079 LATIN SMALL LETTER Y */
|
||||
#define KEY_z 0x007a /* U+007A LATIN SMALL LETTER Z */
|
||||
#define KEY_braceleft 0x007b /* U+007B LEFT CURLY BRACKET */
|
||||
#define KEY_bar 0x007c /* U+007C VERTICAL LINE */
|
||||
#define KEY_braceright 0x007d /* U+007D RIGHT CURLY BRACKET */
|
||||
#define KEY_asciitilde 0x007e /* U+007E TILDE */
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "cursors.h"
|
||||
|
||||
typedef struct WindowHandle_T *WindowHandle;
|
||||
typedef struct VkSurfaceKHR_T *VkSurfaceKHR;
|
||||
typedef struct VkInstance_T *VkInstance;
|
||||
|
||||
typedef struct WindowCreateInfo {
|
||||
int x, y;
|
||||
unsigned width, height;
|
||||
} WindowCreateInfo;
|
||||
|
||||
typedef unsigned WindowCursor;
|
||||
|
||||
typedef enum WindowResult {
|
||||
WINDOW_SUCCESS,
|
||||
WINDOW_CONNECTION_FAILED,
|
||||
WINDOW_ALLOCATION_FAILED,
|
||||
} WindowResult;
|
||||
|
||||
/* Creates new window */
|
||||
WindowResult window_new(WindowCreateInfo *pInfo, WindowHandle *pOut);
|
||||
|
||||
/* Cleans up the window */
|
||||
void window_destroy(WindowHandle window);
|
||||
|
||||
/* Hides the window, basically minimizes */
|
||||
void window_hide(WindowHandle window);
|
||||
|
||||
/* Show the window */
|
||||
void window_show(WindowHandle window);
|
||||
|
||||
VkSurfaceKHR window_vk_create_surface(VkInstance instance, WindowHandle window);
|
||||
|
||||
int window_is_closed(WindowHandle window);
|
||||
|
||||
void window_close(WindowHandle window);
|
||||
|
||||
int window_next_event(WindowHandle handle, WindowEvent *pOutEvent);
|
||||
|
||||
int window_pending_event(WindowHandle handle);
|
||||
|
||||
char *window_get_clipboard(const WindowHandle window);
|
||||
|
||||
void window_set_clipboard(WindowHandle window, const char *text);
|
||||
|
||||
WindowCursor window_create_cursor(WindowHandle window, int idx);
|
||||
|
||||
int window_is_minimized(WindowHandle window);
|
||||
|
||||
void window_get_extent(WindowHandle window, int *pOutWidth, int *pOutHeight);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
#include <SDL2/SDL_error.h>
|
||||
#include <SDL_video.h>
|
||||
#include <volk.h>
|
||||
#include <stdexcept>
|
||||
#include "SDLWindow.h"
|
||||
#include "LoftException.hpp"
|
||||
#include <SDL2/SDL_vulkan.h>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace lft::win {
|
||||
|
||||
//
|
||||
// Created by martin on 11/12/23.
|
||||
//
|
||||
void SDLWindow::resize() {
|
||||
|
||||
}
|
||||
|
||||
VkExtent2D SDLWindow::get_size() const {
|
||||
VkExtent2D extent = {};
|
||||
SDL_GetWindowSize(m_pWindow, (int*)&extent.width, (int*)&extent.height);
|
||||
|
||||
return extent;
|
||||
}
|
||||
|
||||
SDLWindow::SDLWindow(std::string name, VkRect2D rect) :
|
||||
m_extent{rect.extent}
|
||||
{
|
||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVERYTHING) < 0) {
|
||||
throw std::runtime_error("Failed to initialize sdl");
|
||||
}
|
||||
|
||||
m_pWindow = SDL_CreateWindow(name.c_str(),
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
rect.extent.width,
|
||||
rect.extent.height,
|
||||
SDL_WINDOW_VULKAN | SDL_WINDOW_ALLOW_HIGHDPI |
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if(m_pWindow == nullptr) {
|
||||
throw GpuException(std::format("Failed to create window:\n{}", SDL_GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
Surface SDLWindow::create_surface(const Instance* instance) const {
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
SDL_Vulkan_CreateSurface(m_pWindow, instance->instance(), &surface);
|
||||
return Surface(instance, surface);
|
||||
}
|
||||
|
||||
bool SDLWindow::is_open() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t SDLWindow::poll_event(SDL_Event *pOutEvent) const {
|
||||
return SDL_PollEvent(pOutEvent);
|
||||
}
|
||||
|
||||
std::vector<std::string> SDLWindow::get_required_extensions() const {
|
||||
uint32_t count = 0;
|
||||
SDL_Vulkan_GetInstanceExtensions(m_pWindow, &count, nullptr);
|
||||
|
||||
std::vector<const char*> extensions(count);
|
||||
SDL_Vulkan_GetInstanceExtensions(m_pWindow, &count, extensions.data());
|
||||
|
||||
std::vector<std::string> extension_strings(count);
|
||||
std::transform(extensions.begin(), extensions.end(),
|
||||
extension_strings.begin(),
|
||||
[](const char* str) {
|
||||
return std::string(str);
|
||||
});
|
||||
|
||||
return extension_strings;
|
||||
}
|
||||
|
||||
}
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
#include "Swapchain.hpp"
|
||||
#include "Instance.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <print>
|
||||
|
||||
VkSurfaceFormatKHR Swapchain::choose_format() {
|
||||
uint32_t formatCount = 0;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_gpu->gpu(), m_surface, &formatCount, nullptr);
|
||||
assert(formatCount > 0);
|
||||
|
||||
auto formats = std::vector<VkSurfaceFormatKHR>(formatCount);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_gpu->gpu(), m_surface, &formatCount, formats.data());
|
||||
|
||||
for(uint32_t i = 0; i < formatCount; i++) {
|
||||
if(formats[i].format == VK_FORMAT_B8G8R8A8_UNORM &&
|
||||
formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||
return formats[i];
|
||||
}
|
||||
}
|
||||
|
||||
auto result = formats[0];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VkPresentModeKHR Swapchain::choose_present_mode() {
|
||||
uint32_t presentModeCount = 0;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(m_gpu->gpu(), m_surface,
|
||||
&presentModeCount, nullptr);
|
||||
|
||||
VkPresentModeKHR presentModeResult = VK_PRESENT_MODE_FIFO_KHR;
|
||||
|
||||
auto presentModes = new VkPresentModeKHR[presentModeCount];
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(m_gpu->gpu(), m_surface,
|
||||
&presentModeCount, presentModes);
|
||||
|
||||
for(uint32_t i = 0; i < presentModeCount; i++) {
|
||||
if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||
presentModeResult = presentModes[i];
|
||||
}
|
||||
}
|
||||
|
||||
delete [] presentModes;
|
||||
|
||||
return presentModeResult;
|
||||
}
|
||||
|
||||
VkExtent2D Swapchain::choose_extent(VkExtent2D actualExtent) {
|
||||
VkSurfaceCapabilitiesKHR capabilities = {};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_gpu->gpu(), m_surface, &capabilities);
|
||||
|
||||
VkExtent2D result = {};
|
||||
|
||||
if(capabilities.currentExtent.width != UINT32_MAX) {
|
||||
result = capabilities.currentExtent;
|
||||
} else {
|
||||
result.width = std::max(
|
||||
capabilities.minImageExtent.width,
|
||||
std::min(capabilities.maxImageExtent.width, actualExtent.width)
|
||||
);
|
||||
|
||||
result.height = std::max(
|
||||
capabilities.minImageExtent.height,
|
||||
std::min(capabilities.maxImageExtent.height, actualExtent.height)
|
||||
);
|
||||
}
|
||||
|
||||
assert(result.width > 0 && result.height > 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ResultCode Swapchain::get_images(uint32_t *pOutNumImages, VkImage *pOutImages) {
|
||||
/* Get images to render to, rendertargets */
|
||||
EXPECT(vkGetSwapchainImagesKHR(m_gpu->dev(), m_swapchain, pOutNumImages, pOutImages) == VK_SUCCESS,
|
||||
"Failed to get swapchain images");
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
ResultCode Swapchain::create_views() {
|
||||
m_pImageViews = (VkImageView*)malloc(sizeof(VkImageView) * m_numImages);
|
||||
assert(m_pImageViews);
|
||||
|
||||
for(unsigned i = 0; i < m_numImages; i++) {
|
||||
VkImageViewCreateInfo viewInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = m_pImages[i],
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = m_format.format,
|
||||
.components = {
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY
|
||||
},
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
}
|
||||
};
|
||||
|
||||
EXPECT(vkCreateImageView(m_gpu->dev(), &viewInfo, NULL, &m_pImageViews[i]) == VK_SUCCESS,
|
||||
"Failed to create image view");
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
ResultCode Swapchain::create_swapchain() {
|
||||
VkSurfaceCapabilitiesKHR capabilities = {};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_gpu->gpu(), m_surface, &capabilities);
|
||||
|
||||
VkSwapchainCreateInfoKHR swapchainInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.surface = m_surface,
|
||||
.minImageCount = m_numImages,
|
||||
.imageFormat = m_format.format,
|
||||
.imageColorSpace = m_format.colorSpace,
|
||||
.imageExtent = m_extent,
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
.preTransform = capabilities.currentTransform,
|
||||
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||
.presentMode = choose_present_mode(),
|
||||
.clipped = VK_TRUE
|
||||
};
|
||||
|
||||
/* Allow sharing across graphics and present queue when those two are not
|
||||
* the same. Meaning we can draw with commands submitted to graphics queue
|
||||
* to swapchain images, that need to be used by command submitted to
|
||||
* present queue. */
|
||||
auto presentQueues = m_gpu->present_queue_ids();
|
||||
if(presentQueues.size() > 1) {
|
||||
swapchainInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||
swapchainInfo.queueFamilyIndexCount = presentQueues.size();
|
||||
swapchainInfo.pQueueFamilyIndices = presentQueues.data();
|
||||
} else {
|
||||
/* Don't need to share the images */
|
||||
swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
}
|
||||
|
||||
EXPECT(vkCreateSwapchainKHR(m_gpu->dev(), &swapchainInfo, NULL, &m_swapchain) == VK_SUCCESS, "Failed to create swapchain");
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void Swapchain::cleanup() {
|
||||
for(int i = 0; i < m_numImages; i++) {
|
||||
vkDestroyImageView(m_gpu->dev(), m_pImageViews[i], nullptr);
|
||||
}
|
||||
|
||||
vkDestroySwapchainKHR(m_gpu->dev(), m_swapchain, nullptr);
|
||||
}
|
||||
|
||||
void Swapchain::resize(VkExtent2D extent) {
|
||||
cleanup();
|
||||
|
||||
m_extent = extent;
|
||||
|
||||
create_swapchain();
|
||||
|
||||
get_images(&m_numImages, NULL);
|
||||
m_pImages = new VkImage[m_numImages];
|
||||
get_images(&m_numImages, m_pImages);
|
||||
|
||||
create_views();
|
||||
|
||||
m_images.resize(m_numImages);
|
||||
m_views.resize(m_numImages);
|
||||
for(int i = 0; i < m_numImages; i++) {
|
||||
m_images[i].img = m_pImages[i];
|
||||
std::println("View: {:#06x}", (unsigned long)m_pImageViews[i]);
|
||||
m_views[i].view = m_pImageViews[i];
|
||||
}
|
||||
}
|
||||
|
||||
Swapchain::Swapchain(const Gpu* gpu, VkExtent2D extent, Surface* surface) :
|
||||
m_gpu(gpu),
|
||||
m_surface(surface->surface())
|
||||
{
|
||||
VkSurfaceCapabilitiesKHR capabilities = {};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_gpu->gpu(), m_surface, &capabilities);
|
||||
|
||||
m_format = choose_format();
|
||||
m_extent = choose_extent(extent);
|
||||
|
||||
uint32_t imageCount = capabilities.minImageCount + 1;
|
||||
m_numImages = imageCount;
|
||||
|
||||
if(capabilities.maxImageCount > 0 &&
|
||||
imageCount < capabilities.maxImageCount) {
|
||||
m_numImages = capabilities.maxImageCount;
|
||||
}
|
||||
m_numFrames = m_numImages;
|
||||
|
||||
create_swapchain();
|
||||
|
||||
get_images(&m_numImages, NULL);
|
||||
m_pImages = new VkImage[m_numImages];
|
||||
get_images(&m_numImages, m_pImages);
|
||||
|
||||
create_views();
|
||||
|
||||
m_images.resize(m_numImages);
|
||||
m_views.resize(m_numImages);
|
||||
for(int i = 0; i < m_numImages; i++) {
|
||||
m_images[i].img = m_pImages[i];
|
||||
m_views[i].view = m_pImageViews[i];
|
||||
}
|
||||
}
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
#include "../include/event.h"
|
||||
#include "../include/window.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include <X11/X.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_xlib.h>
|
||||
|
||||
struct WindowHandle_T {
|
||||
Window window;
|
||||
|
||||
/* Used for comparing when ConfigureNotify event occurs, to see if we just
|
||||
* moved or scaled */
|
||||
int x, y;
|
||||
unsigned width, height;
|
||||
|
||||
Display *pDisplay;
|
||||
XVisualInfo *pVisual;
|
||||
Colormap colormap;
|
||||
|
||||
Atom wmDeleteWindow;
|
||||
int isOpen;
|
||||
|
||||
int isMinimized;
|
||||
};
|
||||
|
||||
static int
|
||||
xlib_debug_callback(Display* display, XErrorEvent* event) {
|
||||
char* buffer = (char*)malloc(2048);
|
||||
XGetErrorText(display, event->error_code, buffer, 2048);
|
||||
|
||||
printf("Xlib error => %s", buffer);
|
||||
free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WindowResult window_new(WindowCreateInfo *pInfo, WindowHandle *pOut) {
|
||||
*pOut = (struct WindowHandle_T*)malloc(sizeof(struct WindowHandle_T));
|
||||
if(!pOut) {
|
||||
return WINDOW_ALLOCATION_FAILED;
|
||||
}
|
||||
// memset(pOut, 0, sizeof(struct WindowHandle_T));
|
||||
|
||||
/* XInitThreads(); */
|
||||
XSetErrorHandler(xlib_debug_callback);
|
||||
|
||||
(*pOut)->pDisplay = XOpenDisplay(NULL);
|
||||
if(!(*pOut)->pDisplay) {
|
||||
return WINDOW_CONNECTION_FAILED;
|
||||
}
|
||||
|
||||
long visualMask = VisualScreenMask;
|
||||
XVisualInfo visualInfo = {};
|
||||
visualInfo.screen = DefaultScreen((*pOut)->pDisplay);
|
||||
|
||||
int visualCount = 0;
|
||||
(*pOut)->pVisual = XGetVisualInfo((*pOut)->pDisplay, visualMask, &visualInfo, &visualCount);
|
||||
(*pOut)->colormap = XCreateColormap((*pOut)->pDisplay,
|
||||
DefaultRootWindow((*pOut)->pDisplay),
|
||||
(*pOut)->pVisual->visual, AllocNone);
|
||||
|
||||
{
|
||||
XSetWindowAttributes windowAttributes = {};
|
||||
windowAttributes.colormap = (*pOut)->colormap;
|
||||
windowAttributes.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | StructureNotifyMask;
|
||||
windowAttributes.override_redirect = False;
|
||||
|
||||
(*pOut)->window = XCreateWindow((*pOut)->pDisplay, DefaultRootWindow((*pOut)->pDisplay),
|
||||
pInfo->x, pInfo->y,
|
||||
pInfo->width, pInfo->height, 0,
|
||||
(*pOut)->pVisual->depth, InputOutput,
|
||||
(*pOut)->pVisual->visual,
|
||||
CWColormap | CWEventMask | CWOverrideRedirect,
|
||||
&windowAttributes);
|
||||
}
|
||||
|
||||
(*pOut)->isOpen = 1;
|
||||
|
||||
/* handles closing the window by the user */
|
||||
(*pOut)->wmDeleteWindow = XInternAtom((*pOut)->pDisplay, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols((*pOut)->pDisplay, (*pOut)->window, &(*pOut)->wmDeleteWindow, 1);
|
||||
|
||||
XMapWindow((*pOut)->pDisplay, (*pOut)->window);
|
||||
XFlush((*pOut)->pDisplay);
|
||||
|
||||
(*pOut)->width = pInfo->width;
|
||||
(*pOut)->height = pInfo->height;
|
||||
|
||||
return WINDOW_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
VkSurfaceKHR window_vk_create_surface(VkInstance instance, WindowHandle window) {
|
||||
VkXlibSurfaceCreateInfoKHR surfaceInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
|
||||
.dpy = window->pDisplay,
|
||||
.window = window->window,
|
||||
};
|
||||
|
||||
VkSurfaceKHR result = VK_NULL_HANDLE;
|
||||
|
||||
if(vkCreateXlibSurfaceKHR(instance, &surfaceInfo, NULL, &result) != VK_SUCCESS) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int window_solve_event(XEvent *pEvent, WindowEvent *pOutEvent) {
|
||||
assert(pEvent && pOutEvent);
|
||||
|
||||
WindowEvent result = {};
|
||||
result.type = NONE_EVENT_TYPE;
|
||||
switch(pEvent->type) {
|
||||
case KeyPress:
|
||||
result.type = KEY_EVENT_TYPE;
|
||||
result.key.state = STATE_PRESSED;
|
||||
result.key.key = XLookupKeysym(&pEvent->xkey, 0);
|
||||
break;
|
||||
case KeyRelease:
|
||||
result.type = KEY_EVENT_TYPE;
|
||||
result.key.state = STATE_RELEASED;
|
||||
result.key.key = XLookupKeysym(&pEvent->xkey, 0);
|
||||
result.key.txt = XKeysymToString(result.key.key);
|
||||
break;
|
||||
case ButtonPress:
|
||||
result.type = BUTTON_EVENT_TYPE;
|
||||
result.button.state = STATE_PRESSED;
|
||||
result.button.button = pEvent->xbutton.button;
|
||||
result.button.x = pEvent->xbutton.x;
|
||||
result.button.y = pEvent->xbutton.y;
|
||||
break;
|
||||
case ButtonRelease:
|
||||
result.type = BUTTON_EVENT_TYPE;
|
||||
result.button.state = STATE_RELEASED;
|
||||
result.button.button = pEvent->xbutton.button;
|
||||
result.button.x = pEvent->xbutton.x;
|
||||
result.button.y = pEvent->xbutton.y;
|
||||
break;
|
||||
case MotionNotify:
|
||||
result.type = MOTION_EVENT_TYPE;
|
||||
result.motion.x = pEvent->xmotion.x;
|
||||
result.motion.y = pEvent->xmotion.y;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
result.type = TRANSFORM_EVENT_TYPE;
|
||||
result.transform.x = pEvent->xconfigure.x;
|
||||
result.transform.y = pEvent->xconfigure.y;
|
||||
result.transform.width = pEvent->xconfigure.width;
|
||||
result.transform.height = pEvent->xconfigure.height;
|
||||
break;
|
||||
}
|
||||
|
||||
*pOutEvent = result;
|
||||
|
||||
return result.type != NONE_EVENT_TYPE;
|
||||
}
|
||||
|
||||
int window_is_closed(WindowHandle window) {
|
||||
return !window->isOpen;
|
||||
}
|
||||
|
||||
void window_close(WindowHandle window) {
|
||||
window->isOpen = 0;
|
||||
}
|
||||
|
||||
int window_next_event(WindowHandle window, WindowEvent *pOutEvent) {
|
||||
assert(window && pOutEvent);
|
||||
|
||||
XEvent event;
|
||||
int status = XNextEvent(window->pDisplay, &event);
|
||||
|
||||
WindowEvent solvedEvent = {};
|
||||
status = window_solve_event(&event, &solvedEvent);
|
||||
|
||||
if(event.type == ClientMessage) {
|
||||
if(event.xclient.data.l[0] == window->wmDeleteWindow) {
|
||||
window_close(window);
|
||||
}
|
||||
} else if(event.type == MapNotify) {
|
||||
window->isMinimized = 1;
|
||||
} else if(event.type == UnmapNotify) {
|
||||
window->isMinimized = 0;
|
||||
} else if(event.type == ConfigureNotify) {
|
||||
window->width = event.xconfigure.width;
|
||||
window->height = event.xconfigure.height;
|
||||
}
|
||||
|
||||
if(status) {
|
||||
*pOutEvent = solvedEvent;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int window_pending_event(WindowHandle window) {
|
||||
return XPending(window->pDisplay);
|
||||
}
|
||||
|
||||
void window_destroy(WindowHandle window) {
|
||||
XDestroyWindow(window->pDisplay, window->window);
|
||||
XCloseDisplay(window->pDisplay);
|
||||
}
|
||||
|
||||
int window_is_minimized(WindowHandle window) {
|
||||
return window->isMinimized;
|
||||
}
|
||||
|
||||
void window_get_extent(WindowHandle window, int *pOutWidth, int *pOutHeight) {
|
||||
*pOutWidth = window->width;
|
||||
*pOutHeight = window->height;
|
||||
}
|
||||
|
||||
void window_set_clipboard(WindowHandle window, const char *text) {
|
||||
|
||||
}
|
||||
|
||||
char *window_get_clipboard(WindowHandle window) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WindowCursor window_create_cursor(WindowHandle window, int idx) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user