vulkan_test2
changeset 4:c31c4115d44a
test 2, open window, create queue, etc ...
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 22 Sep 2017 15:26:29 +0300 |
parents | 68e1c437343f |
children | cec4b0e7fce8 |
files | .hgignore Makefile src/main.c src/vku.c src/vku.h src/wsys.h src/wsys_x11.c |
diffstat | 7 files changed, 577 insertions(+), 21 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Fri Sep 22 15:26:29 2017 +0300 1.3 @@ -0,0 +1,4 @@ 1.4 +\.o$ 1.5 +\.swp$ 1.6 +\.d$ 1.7 +^test$
2.1 --- a/Makefile Fri Sep 22 01:01:10 2017 +0300 2.2 +++ b/Makefile Fri Sep 22 15:26:29 2017 +0300 2.3 @@ -3,7 +3,7 @@ 2.4 bin = test 2.5 2.6 CFLAGS = -pedantic -Wall -g 2.7 -LDFLAGS = -lvulkan 2.8 +LDFLAGS = -lvulkan -lX11 2.9 2.10 $(bin): $(obj) 2.11 $(CC) -o $@ $(obj) $(LDFLAGS)
3.1 --- a/src/main.c Fri Sep 22 01:01:10 2017 +0300 3.2 +++ b/src/main.c Fri Sep 22 15:26:29 2017 +0300 3.3 @@ -1,13 +1,45 @@ 3.4 #include <stdio.h> 3.5 -#include <vulkan/vulkan.h> 3.6 +#include "wsys.h" 3.7 #include "vku.h" 3.8 3.9 +static void display(void); 3.10 +static void reshape(int x, int y); 3.11 +static void keyboard(int key, int pressed); 3.12 + 3.13 int main(void) 3.14 { 3.15 if(vku_create_dev() == -1) { 3.16 - return -1; 3.17 + return 1; 3.18 } 3.19 3.20 + if(wsys_create_window(800, 600) == -1) { 3.21 + return 1; 3.22 + } 3.23 + wsys_set_window_title("Vulkan test 2"); 3.24 + 3.25 + wsys_display_callback(display); 3.26 + wsys_reshape_callback(reshape); 3.27 + wsys_keyboard_callback(keyboard); 3.28 + 3.29 + while(wsys_process_events(WSYS_BLOCKING) != -1); 3.30 + 3.31 + wsys_destroy_window(); 3.32 vku_cleanup(); 3.33 return 0; 3.34 } 3.35 + 3.36 +static void display(void) 3.37 +{ 3.38 + wsys_swap_buffers(); 3.39 +} 3.40 + 3.41 +static void reshape(int x, int y) 3.42 +{ 3.43 +} 3.44 + 3.45 +static void keyboard(int key, int pressed) 3.46 +{ 3.47 + if(key == 27) { 3.48 + wsys_quit(); 3.49 + } 3.50 +}
4.1 --- a/src/vku.c Fri Sep 22 01:01:10 2017 +0300 4.2 +++ b/src/vku.c Fri Sep 22 15:26:29 2017 +0300 4.3 @@ -1,7 +1,7 @@ 4.4 #include <stdio.h> 4.5 #include <stdlib.h> 4.6 #include <string.h> 4.7 -#include <alloca.h> 4.8 +#include <stdint.h> 4.9 #include "vku.h" 4.10 4.11 static const char *get_device_name(VkPhysicalDeviceType type); 4.12 @@ -12,26 +12,108 @@ 4.13 static int ver_patch(uint32_t ver); 4.14 static const char *mem_size_str(long sz); 4.15 4.16 - 4.17 VkInstance vk; 4.18 VkDevice vkdev; 4.19 VkQueue vkq; 4.20 4.21 +static VkPhysicalDevice *phys_devices; 4.22 +static int sel_dev, sel_qfamily; 4.23 + 4.24 +static VkExtensionProperties *vkext, *vkdevext; 4.25 +static uint32_t vkext_count, vkdevext_count; 4.26 + 4.27 + 4.28 +int vku_have_extension(const char *name) 4.29 +{ 4.30 + int i; 4.31 + 4.32 + if(!vkext) { 4.33 + vkext_count = 0; 4.34 + vkEnumerateInstanceExtensionProperties(0, &vkext_count, 0); 4.35 + if(vkext_count) { 4.36 + if(!(vkext = malloc(vkext_count * sizeof *vkext))) { 4.37 + perror("failed to allocate instance extension list"); 4.38 + return 0; 4.39 + } 4.40 + vkEnumerateInstanceExtensionProperties(0, &vkext_count, vkext); 4.41 + 4.42 + printf("instance extensions:\n"); 4.43 + for(i=0; i<(int)vkext_count; i++) { 4.44 + printf(" %s (ver: %u)\n", vkext[i].extensionName, (unsigned int)vkext[i].specVersion); 4.45 + } 4.46 + } 4.47 + } 4.48 + 4.49 + for(i=0; i<(int)vkext_count; i++) { 4.50 + if(strcmp(vkext[i].extensionName, name) == 0) { 4.51 + return 1; 4.52 + } 4.53 + } 4.54 + return 0; 4.55 +} 4.56 + 4.57 +int vku_have_device_extension(const char *name) 4.58 +{ 4.59 + int i; 4.60 + 4.61 + if(sel_dev < 0) return 0; 4.62 + 4.63 + if(!vkdevext) { 4.64 + vkdevext_count = 0; 4.65 + vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, 0); 4.66 + if(vkdevext_count) { 4.67 + if(!(vkdevext = malloc(vkdevext_count * sizeof *vkdevext))) { 4.68 + perror("failed to allocate device extension list"); 4.69 + return 0; 4.70 + } 4.71 + vkEnumerateDeviceExtensionProperties(phys_devices[sel_dev], 0, &vkdevext_count, vkdevext); 4.72 + 4.73 + printf("selected device extensions:\n"); 4.74 + for(i=0; i<(int)vkdevext_count; i++) { 4.75 + printf(" %s (ver: %u)\n", vkdevext[i].extensionName, (unsigned int)vkdevext[i].specVersion); 4.76 + } 4.77 + } 4.78 + } 4.79 + 4.80 + for(i=0; i<(int)vkdevext_count; i++) { 4.81 + if(strcmp(vkdevext[i].extensionName, name) == 0) { 4.82 + return 1; 4.83 + } 4.84 + } 4.85 + return 0; 4.86 +} 4.87 + 4.88 int vku_create_dev(void) 4.89 { 4.90 int i, j; 4.91 VkInstanceCreateInfo inst_info; 4.92 - VkPhysicalDevice *devices; 4.93 VkDeviceCreateInfo dev_info; 4.94 VkDeviceQueueCreateInfo queue_info; 4.95 VkCommandPoolCreateInfo cmdpool_info; 4.96 uint32_t num_devices; 4.97 - int sel_dev = -1; 4.98 - int sel_qfamily = -1; 4.99 float qprio = 0.0f; 4.100 4.101 + static const char *ext_names[] = { 4.102 +#ifdef VK_USE_PLATFORM_XLIB_KHR 4.103 + "VK_KHR_xlib_surface", 4.104 +#endif 4.105 + "VK_KHR_surface" 4.106 + }; 4.107 + 4.108 + sel_dev = -1; 4.109 + sel_qfamily = -1; 4.110 + 4.111 + for(i=0; i<sizeof ext_names / sizeof *ext_names; i++) { 4.112 + if(!vku_have_extension(ext_names[i])) { 4.113 + fprintf(stderr, "required extension (%s) not found\n", ext_names[i]); 4.114 + return -1; 4.115 + } 4.116 + } 4.117 + 4.118 memset(&inst_info, 0, sizeof inst_info); 4.119 inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 4.120 + inst_info.ppEnabledExtensionNames = ext_names; 4.121 + inst_info.enabledExtensionCount = sizeof ext_names / sizeof *ext_names; 4.122 4.123 if(vkCreateInstance(&inst_info, 0, &vk) != 0) { 4.124 fprintf(stderr, "failed to create vulkan instance\n"); 4.125 @@ -43,8 +125,8 @@ 4.126 fprintf(stderr, "failed to enumerate vulkan physical devices\n"); 4.127 return -1; 4.128 } 4.129 - devices = alloca(num_devices * sizeof *devices); 4.130 - if(vkEnumeratePhysicalDevices(vk, &num_devices, devices) != 0) { 4.131 + phys_devices = malloc(num_devices * sizeof *phys_devices); 4.132 + if(vkEnumeratePhysicalDevices(vk, &num_devices, phys_devices) != 0) { 4.133 fprintf(stderr, "failed to enumerate vulkan physical devices\n"); 4.134 return -1; 4.135 } 4.136 @@ -56,7 +138,7 @@ 4.137 VkQueueFamilyProperties *qprop; 4.138 uint32_t qprop_count; 4.139 4.140 - vkGetPhysicalDeviceProperties(devices[i], &dev_prop); 4.141 + vkGetPhysicalDeviceProperties(phys_devices[i], &dev_prop); 4.142 4.143 printf("Device %d: %s\n", i, dev_prop.deviceName); 4.144 printf(" type: %s\n", get_device_name(dev_prop.deviceType)); 4.145 @@ -67,7 +149,7 @@ 4.146 printf(" vendor id: %x device id: %x\n", dev_prop.vendorID, dev_prop.deviceID); 4.147 4.148 4.149 - vkGetPhysicalDeviceMemoryProperties(devices[i], &mem_prop); 4.150 + vkGetPhysicalDeviceMemoryProperties(phys_devices[i], &mem_prop); 4.151 printf(" %d memory heaps:\n", mem_prop.memoryHeapCount); 4.152 for(j=0; j<mem_prop.memoryHeapCount; j++) { 4.153 VkMemoryHeap heap = mem_prop.memoryHeaps[j]; 4.154 @@ -81,12 +163,12 @@ 4.155 get_mem_prop_flag_string(type.propertyFlags)); 4.156 } 4.157 4.158 - vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &qprop_count, 0); 4.159 + vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, 0); 4.160 if(qprop_count <= 0) { 4.161 continue; 4.162 } 4.163 qprop = malloc(qprop_count * sizeof *qprop); 4.164 - vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &qprop_count, qprop); 4.165 + vkGetPhysicalDeviceQueueFamilyProperties(phys_devices[i], &qprop_count, qprop); 4.166 4.167 for(j=0; j<qprop_count; j++) { 4.168 printf(" Queue family %d:\n", j); 4.169 @@ -119,7 +201,7 @@ 4.170 dev_info.queueCreateInfoCount = 1; 4.171 dev_info.pQueueCreateInfos = &queue_info; 4.172 4.173 - if(vkCreateDevice(devices[sel_dev], &dev_info, 0, &vkdev) != 0) { 4.174 + if(vkCreateDevice(phys_devices[sel_dev], &dev_info, 0, &vkdev) != 0) { 4.175 fprintf(stderr, "failed to create device %d\n", sel_dev); 4.176 return -1; 4.177 } 4.178 @@ -138,6 +220,11 @@ 4.179 return -1; 4.180 } 4.181 4.182 + if(!(vkcmdbuf = vku_alloc_cmdbuf(vkcmdpool, VK_COMMAND_BUFFER_LEVEL_PRIMARY))) { 4.183 + fprintf(stderr, "failed to create primary command buffer\n"); 4.184 + return -1; 4.185 + } 4.186 + 4.187 return 0; 4.188 } 4.189 4.190 @@ -145,15 +232,75 @@ 4.191 { 4.192 if(vk) { 4.193 vkDeviceWaitIdle(vkdev); 4.194 + vkDestroyCommandPool(vkdev, vkcmdpool, 0); 4.195 vkDestroyDevice(vkdev, 0); 4.196 vkDestroyInstance(vk, 0); 4.197 vk = 0; 4.198 } 4.199 + 4.200 + free(phys_devices); 4.201 + phys_devices = 0; 4.202 } 4.203 4.204 -struct vk_buffer *vku_create_buffer(int sz, unsigned int usage) 4.205 +VkCommandBuffer vku_alloc_cmdbuf(VkCommandPool pool, VkCommandBufferLevel level) 4.206 { 4.207 - struct vk_buffer *buf; 4.208 + VkCommandBuffer cmdbuf; 4.209 + VkCommandBufferAllocateInfo inf; 4.210 + 4.211 + memset(&inf, 0, sizeof inf); 4.212 + inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 4.213 + inf.commandPool = pool; 4.214 + inf.level = level; 4.215 + inf.commandBufferCount = 1; 4.216 + 4.217 + if(vkAllocateCommandBuffers(vkdev, &inf, &cmdbuf) != 0) { 4.218 + return 0; 4.219 + } 4.220 + return cmdbuf; 4.221 +} 4.222 + 4.223 +void vku_free_cmdbuf(VkCommandPool pool, VkCommandBuffer buf) 4.224 +{ 4.225 + vkFreeCommandBuffers(vkdev, pool, 1, &buf); 4.226 +} 4.227 + 4.228 +void vku_begin_cmdbuf(VkCommandBuffer buf, unsigned int flags) 4.229 +{ 4.230 + VkCommandBufferBeginInfo inf; 4.231 + 4.232 + memset(&inf, 0, sizeof inf); 4.233 + inf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 4.234 + inf.flags = flags; 4.235 + 4.236 + vkBeginCommandBuffer(buf, &inf); 4.237 +} 4.238 + 4.239 + 4.240 +void vku_end_cmdbuf(VkCommandBuffer buf) 4.241 +{ 4.242 + vkEndCommandBuffer(buf); 4.243 +} 4.244 + 4.245 +void vku_reset_cmdbuf(VkCommandBuffer buf) 4.246 +{ 4.247 + vkResetCommandBuffer(buf, 0); 4.248 +} 4.249 + 4.250 +void vku_submit_cmdbuf(VkQueue q, VkCommandBuffer buf, VkFence done_fence) 4.251 +{ 4.252 + VkSubmitInfo info; 4.253 + 4.254 + memset(&info, 0, sizeof info); 4.255 + info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 4.256 + info.commandBufferCount = 1; 4.257 + info.pCommandBuffers = &buf; 4.258 + 4.259 + vkQueueSubmit(q, 1, &info, done_fence); 4.260 +} 4.261 + 4.262 +struct vku_buffer *vku_create_buffer(int sz, unsigned int usage) 4.263 +{ 4.264 + struct vku_buffer *buf; 4.265 VkBufferCreateInfo binfo; 4.266 4.267 if(!(buf = malloc(sizeof *buf))) { 4.268 @@ -175,7 +322,7 @@ 4.269 return buf; 4.270 } 4.271 4.272 -void vku_destroy_buffer(struct vk_buffer *buf) 4.273 +void vku_destroy_buffer(struct vku_buffer *buf) 4.274 { 4.275 if(buf) { 4.276 vkDestroyBuffer(vkdev, buf->buf, 0); 4.277 @@ -183,6 +330,25 @@ 4.278 } 4.279 } 4.280 4.281 +void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs, 4.282 + VkBuffer src, int soffs, int size) 4.283 +{ 4.284 + VkBufferCopy copy; 4.285 + copy.size = size; 4.286 + copy.srcOffset = soffs; 4.287 + copy.dstOffset = doffs; 4.288 + 4.289 + vkCmdCopyBuffer(cmdbuf, src, dest, 1, ©); 4.290 +} 4.291 + 4.292 +#ifdef VK_USE_PLATFORM_XLIB_KHR 4.293 +int vku_xlib_usable_visual(Display *dpy, VisualID vid) 4.294 +{ 4.295 + return vkGetPhysicalDeviceXlibPresentationSupportKHR(phys_devices[sel_dev], 4.296 + sel_qfamily, dpy, vid); 4.297 +} 4.298 +#endif /* VK_USE_PLATFORM_XLIB_KHR */ 4.299 + 4.300 static const char *get_device_name(VkPhysicalDeviceType type) 4.301 { 4.302 switch(type) {
5.1 --- a/src/vku.h Fri Sep 22 01:01:10 2017 +0300 5.2 +++ b/src/vku.h Fri Sep 22 15:26:29 2017 +0300 5.3 @@ -1,24 +1,49 @@ 5.4 #ifndef VKU_H_ 5.5 #define VKU_H_ 5.6 5.7 +#ifdef __unix__ 5.8 +#define VK_USE_PLATFORM_XLIB_KHR 5.9 +#endif 5.10 + 5.11 #include <vulkan/vulkan.h> 5.12 5.13 VkInstance vk; 5.14 VkDevice vkdev; 5.15 VkQueue vkq; 5.16 VkCommandPool vkcmdpool; 5.17 +VkCommandBuffer vkcmdbuf; /* primary command buffer */ 5.18 5.19 -struct vk_buffer { 5.20 +struct vku_buffer { 5.21 VkBuffer buf; 5.22 VkDeviceMemory mem_pool; 5.23 int mem_start, mem_size; 5.24 }; 5.25 5.26 +int vku_have_extension(const char *name); 5.27 +int vku_have_device_extension(const char *name); 5.28 + 5.29 int vku_create_dev(void); 5.30 void vku_cleanup(void); 5.31 5.32 +VkCommandBuffer vku_alloc_cmdbuf(VkCommandPool pool, VkCommandBufferLevel level); 5.33 +void vku_free_cmdbuf(VkCommandPool pool, VkCommandBuffer buf); 5.34 5.35 -struct vk_buffer *vku_create_buffer(int sz, unsigned int usage); 5.36 -void vku_destroy_buffer(struct vk_buffer *buf); 5.37 +void vku_begin_cmdbuf(VkCommandBuffer buf, unsigned int flags); 5.38 +void vku_end_cmdbuf(VkCommandBuffer buf); 5.39 +void vku_reset_cmdbuf(VkCommandBuffer buf); 5.40 + 5.41 +void vku_submit_cmdbuf(VkQueue q, VkCommandBuffer buf, VkFence done_fence); 5.42 + 5.43 +struct vku_buffer *vku_create_buffer(int sz, unsigned int usage); 5.44 +void vku_destroy_buffer(struct vku_buffer *buf); 5.45 + 5.46 +void vku_cmd_copybuf(VkCommandBuffer cmdbuf, VkBuffer dest, int doffs, 5.47 + VkBuffer src, int soffs, int size); 5.48 + 5.49 +/* platform-specific */ 5.50 +#ifdef VK_USE_PLATFORM_XLIB_KHR 5.51 +#include <X11/Xlib.h> 5.52 +int vku_xlib_usable_visual(Display *dpy, VisualID vid); 5.53 +#endif 5.54 5.55 #endif /* VKU_H_ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/wsys.h Fri Sep 22 15:26:29 2017 +0300 6.3 @@ -0,0 +1,31 @@ 6.4 +#ifndef WSYS_H_ 6.5 +#define WSYS_H_ 6.6 + 6.7 +/* pass to wsys_process_events */ 6.8 +enum { 6.9 + WSYS_BLOCKING = 0, 6.10 + WSYS_NONBLOCK = 1 6.11 +}; 6.12 + 6.13 +int wsys_create_window(int xsz, int ysz); 6.14 +void wsys_destroy_window(void); 6.15 + 6.16 +void wsys_set_window_title(const char *title); 6.17 +void wsys_get_window_size(int *xsz, int *ysz); 6.18 + 6.19 +void wsys_display_callback(void (*func)(void)); 6.20 +void wsys_reshape_callback(void (*func)(int, int)); 6.21 +void wsys_keyboard_callback(void (*func)(int, int)); 6.22 +void wsys_mouse_callback(void (*func)(int, int, int, int)); 6.23 +void wsys_motion_callback(void (*func)(int, int)); 6.24 +void wsys_passive_motion_callback(void (*func)(int, int)); 6.25 + 6.26 +void wsys_swap_buffers(void); 6.27 +void wsys_redisplay(void); 6.28 +void wsys_quit(void); 6.29 + 6.30 +/* mode: WSYS_BLOCKING or WSYS_NONBLOCK */ 6.31 +int wsys_process_events(int mode); 6.32 + 6.33 + 6.34 +#endif /* WSYS_H_ */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/wsys_x11.c Fri Sep 22 15:26:29 2017 +0300 7.3 @@ -0,0 +1,298 @@ 7.4 +#include <stdio.h> 7.5 +#include <stdlib.h> 7.6 +#include <X11/Xlib.h> 7.7 +#include <X11/Xutil.h> 7.8 +#include "wsys.h" 7.9 +#include "vku.h" 7.10 + 7.11 +struct callbacks { 7.12 + void (*display)(void); 7.13 + void (*reshape)(int, int); 7.14 + void (*keyboard)(int, int); 7.15 + void (*mouse)(int, int, int, int); 7.16 + void (*motion)(int, int); 7.17 + void (*passive)(int, int); 7.18 +}; 7.19 + 7.20 +enum { 7.21 + QUIT = 1, 7.22 + RESHAPE = 2, 7.23 + REDISPLAY = 4 7.24 +}; 7.25 + 7.26 +static void proc_event(XEvent *ev); 7.27 + 7.28 +static Display *dpy; 7.29 +static Window win; 7.30 +static Atom xa_wm_delete; 7.31 +static int win_width, win_height; 7.32 +static int win_mapped; 7.33 +static unsigned int evmask = StructureNotifyMask | ExposureMask; 7.34 +static unsigned int pending; 7.35 +static struct callbacks cb; 7.36 + 7.37 +int wsys_create_window(int xsz, int ysz) 7.38 +{ 7.39 + int i, scr, num_visuals; 7.40 + Window root_win; 7.41 + Visual *vis = 0; 7.42 + XSetWindowAttributes xattr; 7.43 + unsigned int xattr_mask; 7.44 + XVisualInfo *vinf, vinf_match; 7.45 + 7.46 + if(!(dpy = XOpenDisplay(0))) { 7.47 + fprintf(stderr, "failed to open connection to the X server\n"); 7.48 + return -1; 7.49 + } 7.50 + scr = DefaultScreen(dpy); 7.51 + root_win = RootWindow(dpy, scr); 7.52 + 7.53 + xa_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 7.54 + 7.55 + vinf_match.screen = scr; 7.56 + vinf_match.depth = 24; 7.57 + vinf_match.class = TrueColor; 7.58 + 7.59 + if(!(vinf = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask | VisualClassMask, &vinf_match, &num_visuals))) { 7.60 + fprintf(stderr, "failed to retrieve matching visuals\n"); 7.61 + XCloseDisplay(dpy); 7.62 + return -1; 7.63 + } 7.64 + 7.65 + for(i=0; i<num_visuals; i++) { 7.66 + if(vku_xlib_usable_visual(dpy, vinf[i].visualid)) { 7.67 + vis = vinf[i].visual; 7.68 + break; 7.69 + } 7.70 + } 7.71 + if(!vis) { 7.72 + fprintf(stderr, "failed to find approprate visual\n"); 7.73 + XFree(vinf); 7.74 + XCloseDisplay(dpy); 7.75 + return -1; 7.76 + } 7.77 + 7.78 + xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr); 7.79 + xattr.colormap = XCreateColormap(dpy, root_win, vis, AllocNone); 7.80 + xattr_mask = CWBackPixel | CWBorderPixel | CWColormap; 7.81 + 7.82 + if(!(win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, 24, InputOutput, vis, xattr_mask, &xattr))) { 7.83 + fprintf(stderr, "failed to create X window\n"); 7.84 + XFree(vinf); 7.85 + XCloseDisplay(dpy); 7.86 + return -1; 7.87 + } 7.88 + XFree(vinf); 7.89 + 7.90 + XSelectInput(dpy, win, evmask); 7.91 + XSetWMProtocols(dpy, win, &xa_wm_delete, 1); 7.92 + 7.93 + wsys_set_window_title("X11 window"); 7.94 + XMapWindow(dpy, win); 7.95 + 7.96 + win_width = xsz; 7.97 + win_height = ysz; 7.98 + pending = RESHAPE | REDISPLAY; 7.99 + 7.100 + return 0; 7.101 +} 7.102 + 7.103 +void wsys_destroy_window(void) 7.104 +{ 7.105 + if(dpy) { 7.106 + if(win) { 7.107 + XDestroyWindow(dpy, win); 7.108 + win = 0; 7.109 + } 7.110 + XCloseDisplay(dpy); 7.111 + dpy = 0; 7.112 + } 7.113 +} 7.114 + 7.115 +void wsys_get_window_size(int *xsz, int *ysz) 7.116 +{ 7.117 + *xsz = win_width; 7.118 + *ysz = win_height; 7.119 +} 7.120 + 7.121 +void wsys_set_window_title(const char *title) 7.122 +{ 7.123 + XTextProperty text; 7.124 + XStringListToTextProperty((char**)&title, 1, &text); 7.125 + XSetWMName(dpy, win, &text); 7.126 + XSetWMIconName(dpy, win, &text); 7.127 + XFree(text.value); 7.128 +} 7.129 + 7.130 +void wsys_display_callback(void (*func)(void)) 7.131 +{ 7.132 + cb.display = func; 7.133 +} 7.134 + 7.135 +void wsys_reshape_callback(void (*func)(int, int)) 7.136 +{ 7.137 + cb.reshape = func; 7.138 +} 7.139 + 7.140 +void wsys_keyboard_callback(void (*func)(int, int)) 7.141 +{ 7.142 + cb.keyboard = func; 7.143 + if(func) { 7.144 + evmask |= KeyPressMask | KeyReleaseMask; 7.145 + } else { 7.146 + evmask &= ~(KeyPressMask | KeyReleaseMask); 7.147 + } 7.148 + if(win) { 7.149 + XSelectInput(dpy, win, evmask); 7.150 + } 7.151 +} 7.152 + 7.153 +void wsys_mouse_callback(void (*func)(int, int, int, int)) 7.154 +{ 7.155 + cb.mouse = func; 7.156 + if(func) { 7.157 + evmask |= ButtonPressMask | ButtonReleaseMask; 7.158 + } else { 7.159 + evmask &= ~(ButtonPressMask | ButtonReleaseMask); 7.160 + } 7.161 + if(win) { 7.162 + XSelectInput(dpy, win, evmask); 7.163 + } 7.164 +} 7.165 + 7.166 +void wsys_motion_callback(void (*func)(int, int)) 7.167 +{ 7.168 + cb.motion = func; 7.169 + if(func) { 7.170 + evmask |= ButtonMotionMask; 7.171 + } else { 7.172 + evmask &= ~ButtonMotionMask; 7.173 + } 7.174 + if(win) { 7.175 + XSelectInput(dpy, win, evmask); 7.176 + } 7.177 +} 7.178 + 7.179 +void wsys_passive_motion_callback(void (*func)(int, int)) 7.180 +{ 7.181 + cb.passive = func; 7.182 + if(func) { 7.183 + evmask |= PointerMotionMask; 7.184 + } else { 7.185 + evmask &= ~PointerMotionMask; 7.186 + } 7.187 + if(win) { 7.188 + XSelectInput(dpy, win, evmask); 7.189 + } 7.190 +} 7.191 + 7.192 +void wsys_swap_buffers(void) 7.193 +{ 7.194 + /* TODO */ 7.195 +} 7.196 + 7.197 +void wsys_redisplay(void) 7.198 +{ 7.199 + pending |= REDISPLAY; 7.200 +} 7.201 + 7.202 +void wsys_quit(void) 7.203 +{ 7.204 + pending |= QUIT; 7.205 +} 7.206 + 7.207 +int wsys_process_events(int mode) 7.208 +{ 7.209 + XEvent xev; 7.210 + 7.211 + if(pending & RESHAPE) { 7.212 + if(cb.reshape) { 7.213 + cb.reshape(win_width, win_height); 7.214 + } 7.215 + pending &= ~RESHAPE; 7.216 + } 7.217 + 7.218 + if(mode == WSYS_BLOCKING) { 7.219 + XNextEvent(dpy, &xev); 7.220 + proc_event(&xev); 7.221 + if(pending & QUIT) return -1; 7.222 + } 7.223 + 7.224 + while(XPending(dpy)) { 7.225 + XNextEvent(dpy, &xev); 7.226 + proc_event(&xev); 7.227 + if(pending & QUIT) return -1; 7.228 + } 7.229 + 7.230 + if(pending & REDISPLAY && win_mapped) { 7.231 + pending &= ~REDISPLAY; 7.232 + if(cb.display) { 7.233 + cb.display(); 7.234 + } 7.235 + } 7.236 + return 0; 7.237 +} 7.238 + 7.239 +static void proc_event(XEvent *ev) 7.240 +{ 7.241 + switch(ev->type) { 7.242 + case MapNotify: 7.243 + win_mapped = 1; 7.244 + break; 7.245 + 7.246 + case UnmapNotify: 7.247 + win_mapped = 0; 7.248 + break; 7.249 + 7.250 + case ClientMessage: 7.251 + if(ev->xclient.data.l[0] == xa_wm_delete) { 7.252 + pending |= QUIT; 7.253 + } 7.254 + break; 7.255 + 7.256 + case ConfigureNotify: 7.257 + if(ev->xconfigure.width != win_width || ev->xconfigure.height != win_height) { 7.258 + win_width = ev->xconfigure.width; 7.259 + win_height = ev->xconfigure.height; 7.260 + pending |= RESHAPE; 7.261 + } 7.262 + break; 7.263 + 7.264 + case Expose: 7.265 + if(ev->xexpose.count == 0) { 7.266 + pending |= REDISPLAY; 7.267 + } 7.268 + break; 7.269 + 7.270 + case KeyPress: 7.271 + case KeyRelease: 7.272 + if(cb.keyboard) { 7.273 + KeySym sym; 7.274 + char str[16]; 7.275 + XLookupString(&ev->xkey, str, sizeof str, &sym, 0); 7.276 + cb.keyboard(sym & 0xff, ev->type == KeyPress ? 1 : 0); 7.277 + } 7.278 + break; 7.279 + 7.280 + case ButtonPress: 7.281 + case ButtonRelease: 7.282 + if(cb.mouse) { 7.283 + int bn = ev->xbutton.button - Button1; 7.284 + int pressed = ev->type == ButtonPress ? 1 : 0; 7.285 + cb.mouse(bn, pressed, ev->xbutton.x, ev->xbutton.y); 7.286 + } 7.287 + break; 7.288 + 7.289 + case MotionNotify: 7.290 + if(ev->xmotion.state & 0x1f00) { 7.291 + if(cb.motion) { 7.292 + cb.motion(ev->xmotion.x, ev->xmotion.y); 7.293 + } 7.294 + } else { 7.295 + if(cb.passive) { 7.296 + cb.passive(ev->xmotion.x, ev->xmotion.y); 7.297 + } 7.298 + } 7.299 + break; 7.300 + } 7.301 +}