2 * Copyright 2016 Józef Kucia for CodeWeavers
3 * Copyright 2016, 2017 Henri Verbeet for CodeWeavers
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 #define VK_USE_PLATFORM_XCB_KHR
27 #include <xcb/xcb_icccm.h>
28 #include "xinput/xinput.h"
38 VkSurfaceKHR vk_surface
;
39 VkSwapchainKHR vk_swapchain
;
42 VkInstance vk_instance
;
44 ID3D12CommandQueue
*command_queue
;
46 uint32_t current_buffer
;
47 unsigned int buffer_count
;
48 ID3D12Resource
*buffers
[1];
51 static xcb_atom_t
port_get_atom(xcb_connection_t
*c
, const char *name
)
53 xcb_intern_atom_cookie_t cookie
;
54 xcb_intern_atom_reply_t
*reply
;
55 xcb_atom_t atom
= XCB_NONE
;
57 cookie
= xcb_intern_atom(c
, 0, strlen(name
), name
);
58 if ((reply
= xcb_intern_atom_reply(c
, cookie
, NULL
)))
67 static bool port_add_window(struct port
*port
, struct port_window
*window
)
69 if (port
->window_count
== port
->windows_size
)
74 new_capacity
= max(port
->windows_size
* 2, (size_t)4);
75 if (!(new_elements
= realloc(port
->windows
, new_capacity
* sizeof(*port
->windows
))))
77 port
->windows
= (struct port_window
**)new_elements
;
78 port
->windows_size
= new_capacity
;
81 port
->windows
[port
->window_count
++] = window
;
86 static void port_remove_window(struct port
*port
, const struct port_window
*window
)
90 for (i
= 0; i
< port
->window_count
; ++i
)
92 if (port
->windows
[i
] != window
)
96 memmove(&port
->windows
[i
], &port
->windows
[i
+ 1], (port
->window_count
- i
) * sizeof(*port
->windows
));
101 static struct port_window
*port_find_window(struct port
*port
, xcb_window_t window
)
105 for (i
= 0; i
< port
->window_count
; ++i
)
107 if (port
->windows
[i
]->window
== window
)
108 return port
->windows
[i
];
114 static xcb_screen_t
*port_get_screen(xcb_connection_t
*c
, int idx
)
116 xcb_screen_iterator_t iter
;
118 iter
= xcb_setup_roots_iterator(xcb_get_setup(c
));
119 for (; iter
.rem
; xcb_screen_next(&iter
), --idx
)
128 struct port_window
*port_window_create(struct port
*port
, const char *title
,
129 unsigned int width
, unsigned int height
, void *user_data
)
131 static const uint32_t window_events
= XCB_EVENT_MASK_KEY_PRESS
| XCB_EVENT_MASK_KEY_RELEASE
;
133 struct port_window
*window
;
134 xcb_size_hints_t hints
;
135 xcb_screen_t
*screen
;
137 if (!(screen
= port_get_screen(port
->connection
, port
->screen
)))
140 if (!(window
= (struct port_window
*)malloc(sizeof(*window
))))
143 if (!port_add_window(port
, window
))
149 window
->window
= xcb_generate_id(port
->connection
);
151 xcb_create_window(port
->connection
, XCB_COPY_FROM_PARENT
, window
->window
, screen
->root
, 0, 0,
152 width
, height
, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT
, screen
->root_visual
,
153 XCB_CW_EVENT_MASK
, &window_events
);
154 xcb_change_property(port
->connection
, XCB_PROP_MODE_REPLACE
, window
->window
, XCB_ATOM_WM_NAME
,
155 XCB_ATOM_STRING
, 8, strlen(title
), title
);
156 xcb_change_property(port
->connection
, XCB_PROP_MODE_REPLACE
, window
->window
, port
->wm_protocols_atom
,
157 XCB_ATOM_ATOM
, 32, 1, &port
->wm_delete_window_atom
);
158 hints
.flags
= XCB_ICCCM_SIZE_HINT_P_MIN_SIZE
| XCB_ICCCM_SIZE_HINT_P_MAX_SIZE
;
159 hints
.min_width
= width
;
160 hints
.min_height
= height
;
161 hints
.max_width
= width
;
162 hints
.max_height
= height
;
163 xcb_change_property(port
->connection
, XCB_PROP_MODE_REPLACE
, window
->window
, XCB_ATOM_WM_NORMAL_HINTS
,
164 XCB_ATOM_WM_SIZE_HINTS
, 32, sizeof(hints
) >> 2, &hints
);
166 xcb_map_window(port
->connection
, window
->window
);
168 xcb_flush(port
->connection
);
173 void port_window_destroy(struct port_window
*window
)
175 xcb_destroy_window(window
->port
->connection
, window
->window
);
176 xcb_flush(window
->port
->connection
);
177 port_remove_window(window
->port
, window
);
181 static void port_update_mouse_axes(struct port
*port
, xcb_input_device_class_iterator_t
*it
)
183 unsigned int idx
= 0;
185 port
->mouse_axes
.x
= ~0u;
186 port
->mouse_axes
.y
= ~0u;
188 for (; it
->rem
; xcb_input_device_class_next(it
))
190 xcb_input_valuator_class_t
*v
= (xcb_input_valuator_class_t
*)it
->data
;
192 if (v
->type
!= XCB_INPUT_INPUT_CLASS_VALUATOR
|| v
->mode
!= XCB_INPUT_VALUATOR_MODE_RELATIVE
)
198 port
->mouse_axes
.x
= v
->number
;
202 port
->mouse_axes
.y
= v
->number
;
211 static void port_process_xi_raw_motion_event(struct port
*port
, const xcb_input_raw_motion_event_t
*motion_event
)
213 const xcb_input_fp3232_t
*values
;
214 unsigned int i
, j
, k
, idx
;
218 if (!port
->xi_client_pointer
)
220 xcb_input_xi_get_client_pointer_cookie_t gcp_cookie
;
221 xcb_input_xi_get_client_pointer_reply_t
*gcp_reply
;
222 xcb_input_xi_query_device_cookie_t query_cookie
;
223 xcb_input_xi_query_device_reply_t
*query_reply
;
224 xcb_input_xi_device_info_iterator_t it
;
225 xcb_input_device_id_t client_pointer
;
227 gcp_cookie
= xcb_input_xi_get_client_pointer(port
->connection
, XCB_WINDOW_NONE
);
228 if (!(gcp_reply
= xcb_input_xi_get_client_pointer_reply(port
->connection
, gcp_cookie
, NULL
))
235 client_pointer
= gcp_reply
->deviceid
;
238 query_cookie
= xcb_input_xi_query_device(port
->connection
, XCB_INPUT_DEVICE_ALL
);
239 if (!(query_reply
= xcb_input_xi_query_device_reply(port
->connection
, query_cookie
, NULL
)))
242 it
= xcb_input_xi_query_device_infos_iterator(query_reply
);
243 for (; it
.rem
; xcb_input_xi_device_info_next(&it
))
245 xcb_input_device_class_iterator_t class_it
;
246 xcb_input_xi_device_info_t
*info
= it
.data
;
248 if (info
->deviceid
!= motion_event
->deviceid
)
250 if (info
->type
!= XCB_INPUT_DEVICE_TYPE_SLAVE_POINTER
)
252 if (info
->attachment
!= client_pointer
)
254 port
->xi_current_slave
= info
->deviceid
;
256 class_it
= xcb_input_xi_device_info_classes_iterator(info
);
257 port_update_mouse_axes(port
, &class_it
);
263 if (!port
->xi_current_slave
)
265 port
->xi_client_pointer
= client_pointer
;
268 if (motion_event
->deviceid
!= port
->xi_current_slave
)
271 mask
= (uint32_t *)(motion_event
+ 1);
272 values
= (const xcb_input_fp3232_t
*)(&mask
[motion_event
->valuators_len
]);
273 for (i
= 0, idx
= 0; i
< motion_event
->valuators_len
; ++i
)
275 uint32_t m
= mask
[i
];
279 j
= __builtin_ctz(m
);
282 v
= values
[idx
].integral
+ (double)values
[idx
].frac
/ ~0u;
284 if (k
== port
->mouse_axes
.x
)
286 else if (k
== port
->mouse_axes
.y
)
293 static void port_process_xi_event(struct port
*port
, const xcb_ge_generic_event_t
*event
)
295 const xcb_input_device_changed_event_t
*change_event
;
296 xcb_input_device_class_iterator_t class_it
;
298 switch (event
->event_type
)
300 case XCB_INPUT_DEVICE_CHANGED
:
301 change_event
= (const xcb_input_device_changed_event_t
*)event
;
302 if (change_event
->deviceid
!= port
->xi_client_pointer
303 || change_event
->reason
!= XCB_INPUT_CHANGE_REASON_SLAVE_SWITCH
)
305 class_it
.data
= (xcb_input_device_class_t
*)&change_event
[1];
306 class_it
.rem
= change_event
->num_classes
;
307 class_it
.index
= (char *)class_it
.data
- (char *)change_event
;
308 port_update_mouse_axes(port
, &class_it
);
309 port
->xi_current_slave
= change_event
->sourceid
;
312 case XCB_INPUT_RAW_MOTION
:
313 port_process_xi_raw_motion_event(port
, (const xcb_input_raw_motion_event_t
*)event
);
317 fprintf(stderr
, "Unhandled X Input event type %#x.\n", event
->event_type
);
322 void port_process_events(struct port
*port
)
324 const struct xcb_client_message_event_t
*client_message
;
325 const xcb_ge_generic_event_t
*generic_event
;
326 const xcb_key_release_event_t
*key_release
;
327 const xcb_key_press_event_t
*key_press
;
328 xcb_generic_event_t
*event
;
329 struct port_window
*window
;
331 xcb_flush(port
->connection
);
333 while (port
->window_count
)
335 if (!port
->idle_func
)
337 if (!(event
= xcb_wait_for_event(port
->connection
)))
340 else if (!(event
= xcb_poll_for_event(port
->connection
)))
342 port
->idle_func(port
, port
->user_data
);
346 switch (XCB_EVENT_RESPONSE_TYPE(event
))
348 case XCB_CLIENT_MESSAGE
:
349 client_message
= (xcb_client_message_event_t
*)event
;
350 if (client_message
->type
== port
->wm_protocols_atom
351 && client_message
->data
.data32
[0] == port
->wm_delete_window_atom
352 && (window
= port_find_window(port
, client_message
->window
)))
353 port_window_destroy(window
);
357 key_press
= (xcb_key_press_event_t
*)event
;
358 port
->keys
[key_press
->detail
>> 3] |= 1 << (key_press
->detail
& 0x7);
361 case XCB_KEY_RELEASE
:
362 key_release
= (xcb_key_release_event_t
*)event
;
363 port
->keys
[key_release
->detail
>> 3] &= ~(1 << (key_release
->detail
& 0x7));
367 generic_event
= (xcb_ge_generic_event_t
*)event
;
368 if (generic_event
->extension
== port
->xi_opcode
)
369 port_process_xi_event(port
, generic_event
);
371 fprintf(stderr
, "Unhandled generic event %#x/%#x.\n",
372 generic_event
->extension
, generic_event
->event_type
);
376 fprintf(stderr
, "Unhandled event type %#x.\n", XCB_EVENT_RESPONSE_TYPE(event
));
384 static bool port_init_xi2(struct port
*port
)
386 xcb_input_xi_query_version_cookie_t version_cookie
;
387 xcb_input_xi_query_version_reply_t
*version_reply
;
388 xcb_query_extension_cookie_t extension_cookie
;
389 xcb_query_extension_reply_t
*extension_reply
;
390 xcb_screen_t
*screen
;
393 xcb_input_event_mask_t header
;
396 static const char ext_name
[] = "XInputExtension";
398 if (!(screen
= port_get_screen(port
->connection
, port
->screen
)))
401 extension_cookie
= xcb_query_extension(port
->connection
, sizeof(ext_name
) - 1, ext_name
);
402 if (!(extension_reply
= xcb_query_extension_reply(port
->connection
, extension_cookie
, NULL
))
403 || !extension_reply
->present
)
405 free(extension_reply
);
408 port
->xi_opcode
= extension_reply
->major_opcode
;
409 free(extension_reply
);
411 version_cookie
= xcb_input_xi_query_version(port
->connection
, 2, 0);
412 if (!(version_reply
= xcb_input_xi_query_version_reply(port
->connection
, version_cookie
, NULL
))
413 || version_reply
->major_version
!= 2)
420 mask
.header
.deviceid
= XCB_INPUT_DEVICE_ALL
;
421 mask
.header
.mask_len
= 1;
422 mask
.bits
= XCB_INPUT_XI_EVENT_MASK_DEVICE_CHANGED
| XCB_INPUT_XI_EVENT_MASK_RAW_MOTION
;
423 xcb_input_xi_select_events(port
->connection
, screen
->root
, 1, &mask
.header
);
425 port
->xi_client_pointer
= 0;
426 port
->xi_current_slave
= 0;
427 memset(&port
->mouse
, 0, sizeof(port
->mouse
));
432 bool port_init(struct port
*port
, void *user_data
)
434 if (!(port
->connection
= xcb_connect(NULL
, &port
->screen
)))
436 if (xcb_connection_has_error(port
->connection
) > 0)
438 if ((port
->wm_delete_window_atom
= port_get_atom(port
->connection
, "WM_DELETE_WINDOW")) == XCB_NONE
)
440 if ((port
->wm_protocols_atom
= port_get_atom(port
->connection
, "WM_PROTOCOLS")) == XCB_NONE
)
442 if (!port_init_xi2(port
))
445 port
->windows
= NULL
;
446 port
->windows_size
= 0;
447 port
->window_count
= 0;
448 port
->user_data
= user_data
;
449 port
->idle_func
= NULL
;
450 memset(port
->keys
, 0, sizeof(port
->keys
));
455 xcb_disconnect(port
->connection
);
459 void port_grab_pointer(struct port
*port
, struct port_window
*window
)
461 xcb_grab_pointer_cookie_t cookie
;
462 xcb_cursor_t cursor_id
;
463 xcb_pixmap_t pixmap_id
;
464 xcb_screen_t
*screen
;
466 if (!(screen
= port_get_screen(port
->connection
, port
->screen
)))
469 cursor_id
= xcb_generate_id(port
->connection
);
470 pixmap_id
= xcb_generate_id(port
->connection
);
472 xcb_create_pixmap(port
->connection
, 1, pixmap_id
, screen
->root
, 1, 1);
473 xcb_create_cursor(port
->connection
, cursor_id
, pixmap_id
, pixmap_id
, 0, 0, 0, 0, 0, 0, 0, 0);
474 xcb_free_pixmap(port
->connection
, pixmap_id
);
475 xcb_change_window_attributes(port
->connection
, window
->window
, XCB_CW_CURSOR
, &cursor_id
);
476 xcb_free_cursor(port
->connection
, cursor_id
);
478 cookie
= xcb_grab_pointer(port
->connection
, 1, window
->window
, 0,
479 XCB_GRAB_MODE_ASYNC
, XCB_GRAB_MODE_ASYNC
, window
->window
, XCB_NONE
, XCB_CURRENT_TIME
);
480 xcb_discard_reply(port
->connection
, cookie
.sequence
);
483 void port_ungrab_pointer(struct port
*port
, struct port_window
*window
)
485 xcb_cursor_t cursor_id
= XCB_NONE
;
487 xcb_change_window_attributes(port
->connection
, window
->window
, XCB_CW_CURSOR
, &cursor_id
);
488 xcb_ungrab_pointer(port
->connection
, XCB_CURRENT_TIME
);
491 void port_cleanup(struct port
*port
)
494 xcb_disconnect(port
->connection
);
497 void port_set_idle_func(struct port
*port
,
498 void (*idle_func
)(struct port
*port
, void *user_data
))
500 port
->idle_func
= idle_func
;
503 static DXGI_FORMAT
port_get_srgb_format(DXGI_FORMAT format
)
507 case DXGI_FORMAT_B8G8R8A8_UNORM
:
508 return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
;
510 return DXGI_FORMAT_UNKNOWN
;
514 struct port_swapchain
*port_swapchain_create(ID3D12CommandQueue
*command_queue
,
515 struct port_window
*window
, const struct port_swapchain_desc
*desc
)
517 struct VkSwapchainCreateInfoKHR vk_swapchain_desc
;
518 struct VkXcbSurfaceCreateInfoKHR surface_desc
;
519 VkSwapchainKHR vk_swapchain
= VK_NULL_HANDLE
;
520 uint32_t format_count
, queue_family_index
;
521 VkSurfaceCapabilitiesKHR surface_caps
;
522 VkPhysicalDevice vk_physical_device
;
523 D3D12_RESOURCE_DESC resource_desc
;
524 VkFence vk_fence
= VK_NULL_HANDLE
;
525 struct port_swapchain
*swapchain
;
526 unsigned int image_count
, i
, j
;
527 VkFenceCreateInfo fence_desc
;
528 VkSurfaceFormatKHR
*formats
;
529 ID3D12Device
*d3d12_device
;
530 VkSurfaceKHR vk_surface
;
531 VkInstance vk_instance
;
537 if ((format
= vkd3d_get_vk_format(port_get_srgb_format(desc
->format
))) == VK_FORMAT_UNDEFINED
)
540 if (FAILED(command_queue
->GetDevice(IID_PPV_ARGS(&d3d12_device
))))
543 vk_instance
= vkd3d_get_vk_instance(d3d12_device
);
544 vk_physical_device
= vkd3d_get_vk_physical_device(d3d12_device
);
545 vk_device
= vkd3d_get_vk_device(d3d12_device
);
547 surface_desc
.sType
= VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR
;
548 surface_desc
.pNext
= NULL
;
549 surface_desc
.flags
= 0;
550 surface_desc
.connection
= window
->port
->connection
;
551 surface_desc
.window
= window
->window
;
552 if (vkCreateXcbSurfaceKHR(vk_instance
, &surface_desc
, NULL
, &vk_surface
) < 0)
554 d3d12_device
->Release();
558 queue_family_index
= vkd3d_get_vk_queue_family_index(command_queue
);
559 if (vkGetPhysicalDeviceSurfaceSupportKHR(vk_physical_device
,
560 queue_family_index
, vk_surface
, &supported
) < 0 || !supported
)
563 if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical_device
, vk_surface
, &surface_caps
) < 0)
566 if ((surface_caps
.maxImageCount
&& desc
->buffer_count
> surface_caps
.maxImageCount
)
567 || desc
->buffer_count
< surface_caps
.minImageCount
568 || desc
->width
> surface_caps
.maxImageExtent
.width
|| desc
->width
< surface_caps
.minImageExtent
.width
569 || desc
->height
> surface_caps
.maxImageExtent
.height
|| desc
->height
< surface_caps
.minImageExtent
.height
570 || !(surface_caps
.supportedCompositeAlpha
& VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
))
573 if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device
, vk_surface
, &format_count
, NULL
) < 0
574 || !format_count
|| !(formats
= (VkSurfaceFormatKHR
*)calloc(format_count
, sizeof(*formats
))))
577 if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device
, vk_surface
, &format_count
, formats
) < 0)
583 if (format_count
!= 1 || formats
->format
!= VK_FORMAT_UNDEFINED
584 || formats
->colorSpace
!= VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
)
586 for (i
= 0; i
< format_count
; ++i
)
588 if (formats
[i
].format
== format
&& formats
[i
].colorSpace
== VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
)
592 if (i
== format_count
)
602 vk_swapchain_desc
.sType
= VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
;
603 vk_swapchain_desc
.pNext
= NULL
;
604 vk_swapchain_desc
.flags
= 0;
605 vk_swapchain_desc
.surface
= vk_surface
;
606 vk_swapchain_desc
.minImageCount
= desc
->buffer_count
;
607 vk_swapchain_desc
.imageFormat
= format
;
608 vk_swapchain_desc
.imageColorSpace
= VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
;
609 vk_swapchain_desc
.imageExtent
.width
= desc
->width
;
610 vk_swapchain_desc
.imageExtent
.height
= desc
->height
;
611 vk_swapchain_desc
.imageArrayLayers
= 1;
612 vk_swapchain_desc
.imageUsage
= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
613 vk_swapchain_desc
.imageSharingMode
= VK_SHARING_MODE_EXCLUSIVE
;
614 vk_swapchain_desc
.queueFamilyIndexCount
= 0;
615 vk_swapchain_desc
.pQueueFamilyIndices
= NULL
;
616 vk_swapchain_desc
.preTransform
= surface_caps
.currentTransform
;
617 vk_swapchain_desc
.compositeAlpha
= VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
;
618 vk_swapchain_desc
.presentMode
= VK_PRESENT_MODE_FIFO_KHR
;
619 vk_swapchain_desc
.clipped
= VK_TRUE
;
620 vk_swapchain_desc
.oldSwapchain
= VK_NULL_HANDLE
;
621 if (vkCreateSwapchainKHR(vk_device
, &vk_swapchain_desc
, NULL
, &vk_swapchain
) < 0)
624 fence_desc
.sType
= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
;
625 fence_desc
.pNext
= NULL
;
626 fence_desc
.flags
= 0;
627 if (vkCreateFence(vk_device
, &fence_desc
, NULL
, &vk_fence
) < 0)
630 if (vkGetSwapchainImagesKHR(vk_device
, vk_swapchain
, &image_count
, NULL
) < 0
631 || !(vk_images
= (VkImage
*)calloc(image_count
, sizeof(*vk_images
))))
634 if (vkGetSwapchainImagesKHR(vk_device
, vk_swapchain
, &image_count
, vk_images
) < 0)
640 if (!(swapchain
= (struct port_swapchain
*)malloc(offsetof(struct port_swapchain
,
641 buffers
) + image_count
* sizeof(*swapchain
->buffers
))))
646 swapchain
->vk_surface
= vk_surface
;
647 swapchain
->vk_swapchain
= vk_swapchain
;
648 swapchain
->vk_fence
= vk_fence
;
649 swapchain
->vk_instance
= vk_instance
;
650 swapchain
->vk_device
= vk_device
;
652 vkAcquireNextImageKHR(vk_device
, vk_swapchain
, UINT64_MAX
,
653 VK_NULL_HANDLE
, vk_fence
, &swapchain
->current_buffer
);
654 vkWaitForFences(vk_device
, 1, &vk_fence
, VK_TRUE
, UINT64_MAX
);
655 vkResetFences(vk_device
, 1, &vk_fence
);
657 resource_desc
.Dimension
= D3D12_RESOURCE_DIMENSION_TEXTURE2D
;
658 resource_desc
.Alignment
= 0;
659 resource_desc
.Width
= desc
->width
;
660 resource_desc
.Height
= desc
->height
;
661 resource_desc
.DepthOrArraySize
= 1;
662 resource_desc
.MipLevels
= 1;
663 resource_desc
.Format
= desc
->format
;
664 resource_desc
.SampleDesc
.Count
= 1;
665 resource_desc
.SampleDesc
.Quality
= 0;
666 resource_desc
.Layout
= D3D12_TEXTURE_LAYOUT_UNKNOWN
;
667 resource_desc
.Flags
= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET
;
668 for (i
= 0; i
< image_count
; ++i
)
670 if (FAILED(vkd3d_create_image_resource(d3d12_device
, &resource_desc
, vk_images
[i
],
671 VKD3D_RESOURCE_INITIAL_STATE_TRANSITION
| VKD3D_RESOURCE_SWAPCHAIN_IMAGE
,
672 &swapchain
->buffers
[i
])))
674 for (j
= 0; j
< i
; ++j
)
676 swapchain
->buffers
[j
]->Release();
683 swapchain
->buffer_count
= image_count
;
685 d3d12_device
->Release();
687 swapchain
->command_queue
= command_queue
;
688 swapchain
->command_queue
->AddRef();
693 if (vk_fence
!= VK_NULL_HANDLE
)
694 vkDestroyFence(vk_device
, vk_fence
, NULL
);
695 if (vk_swapchain
!= VK_NULL_HANDLE
)
696 vkDestroySwapchainKHR(vk_device
, vk_swapchain
, NULL
);
697 vkDestroySurfaceKHR(vk_instance
, vk_surface
, NULL
);
698 d3d12_device
->Release();
702 ID3D12Resource
*port_swapchain_get_back_buffer(struct port_swapchain
*swapchain
, unsigned int index
)
704 ID3D12Resource
*resource
= NULL
;
706 if (index
< swapchain
->buffer_count
&& (resource
= swapchain
->buffers
[index
]))
712 void port_swapchain_present(struct port_swapchain
*swapchain
)
714 VkPresentInfoKHR present_desc
;
717 present_desc
.sType
= VK_STRUCTURE_TYPE_PRESENT_INFO_KHR
;
718 present_desc
.pNext
= NULL
;
719 present_desc
.waitSemaphoreCount
= 0;
720 present_desc
.pWaitSemaphores
= NULL
;
721 present_desc
.swapchainCount
= 1;
722 present_desc
.pSwapchains
= &swapchain
->vk_swapchain
;
723 present_desc
.pImageIndices
= &swapchain
->current_buffer
;
724 present_desc
.pResults
= NULL
;
726 vk_queue
= vkd3d_acquire_vk_queue(swapchain
->command_queue
);
727 vkQueuePresentKHR(vk_queue
, &present_desc
);
728 vkd3d_release_vk_queue(swapchain
->command_queue
);
730 vkAcquireNextImageKHR(swapchain
->vk_device
, swapchain
->vk_swapchain
, UINT64_MAX
,
731 VK_NULL_HANDLE
, swapchain
->vk_fence
, &swapchain
->current_buffer
);
732 vkWaitForFences(swapchain
->vk_device
, 1, &swapchain
->vk_fence
, VK_TRUE
, UINT64_MAX
);
733 vkResetFences(swapchain
->vk_device
, 1, &swapchain
->vk_fence
);
736 void port_swapchain_destroy(struct port_swapchain
*swapchain
)
740 swapchain
->command_queue
->Release();
741 for (i
= 0; i
< swapchain
->buffer_count
; ++i
)
743 swapchain
->buffers
[i
]->Release();
745 vkDestroyFence(swapchain
->vk_device
, swapchain
->vk_fence
, NULL
);
746 vkDestroySwapchainKHR(swapchain
->vk_device
, swapchain
->vk_swapchain
, NULL
);
747 vkDestroySurfaceKHR(swapchain
->vk_instance
, swapchain
->vk_surface
, NULL
);
751 struct port_key_map
*port_get_key_map(struct port
*port
)
753 xcb_get_keyboard_mapping_cookie_t cookie
;
754 xcb_get_keyboard_mapping_reply_t
*reply
;
755 const xcb_keysym_t
*keysyms
;
756 struct port_key_map
*map
;
757 const xcb_setup_t
*setup
;
760 setup
= xcb_get_setup(port
->connection
);
761 count
= setup
->max_keycode
- setup
->min_keycode
+ 1;
762 if (!(map
= (typeof(map
))malloc(offsetof(typeof(*map
), symbols
) + count
* sizeof(*map
->symbols
))))
765 cookie
= xcb_get_keyboard_mapping(port
->connection
, setup
->min_keycode
, count
);
766 if (!(reply
= xcb_get_keyboard_mapping_reply(port
->connection
, cookie
, NULL
)))
769 map
->base
= setup
->min_keycode
;
772 keysyms
= xcb_get_keyboard_mapping_keysyms(reply
);
773 for (i
= 0; i
< map
->count
; ++i
)
775 map
->symbols
[i
] = keysyms
[i
* reply
->keysyms_per_keycode
];
782 bool port_get_key_state(const struct port
*port
, unsigned int key
)
784 return port
->keys
[key
>> 3] & (1 << (key
& 0x7));
787 void port_get_mouse_state(struct port
*port
, struct port_mouse_state
*s
)
790 memset(&port
->mouse
, 0, sizeof(port
->mouse
));