From 080d5d2bf7a043eedd7be1963fafb10308d68dc1 Mon Sep 17 00:00:00 2001 From: Dennis Tsiang Date: Wed, 3 Nov 2021 11:25:48 +0000 Subject: [PATCH] Set default visiblity of functions to hidden Reduce the number of functions that are exported by the layer. This helps resolve dynamic linking issues where multiple functions are named the same in different shared libraries. Also add function specifiers and calling conventions to all extern "C" functions. Change-Id: I07b33ff8d066e33c5dbdf0cbc13aa7835a78220b Signed-off-by: Dennis Tsiang --- CMakeLists.txt | 2 + layer/VkLayer_window_system_integration.json | 3 + layer/layer.cpp | 42 ++++----- layer/surface_api.cpp | 36 ++++---- layer/surface_api.hpp | 36 ++++---- layer/swapchain_api.cpp | 59 +++++++------ layer/swapchain_api.hpp | 61 +++++++------ util/custom_allocator.cpp | 16 ++-- util/macros.hpp | 45 ++++++++++ wsi/headless/surface_properties.cpp | 8 +- wsi/wayland/surface.cpp | 13 +-- wsi/wayland/surface.hpp | 8 +- wsi/wayland/surface_properties.cpp | 11 ++- wsi/wayland/swapchain.cpp | 9 +- wsi/wayland/wl_helpers.cpp | 127 +++++++++++++-------------- wsi/wayland/wl_helpers.hpp | 34 ++++--- 16 files changed, 287 insertions(+), 223 deletions(-) create mode 100644 util/macros.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 665c092..1dc13b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,8 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") set(CMAKE_CXX_STANDARD 11) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_C_VISIBILITY_PRESET hidden) if(NOT DEFINED VULKAN_CXX_INCLUDE) set(VULKAN_CXX_INCLUDE ${VULKAN_PKG_CONFIG_INCLUDEDIR}) diff --git a/layer/VkLayer_window_system_integration.json b/layer/VkLayer_window_system_integration.json index c6e3703..71bfac0 100644 --- a/layer/VkLayer_window_system_integration.json +++ b/layer/VkLayer_window_system_integration.json @@ -7,6 +7,9 @@ "api_version": "1.2.191", "implementation_version": "1", "description": "Window system integration layer", + "functions": { + "vkNegotiateLoaderLayerInterfaceVersion": "wsi_layer_vkNegotiateLoaderLayerInterfaceVersion" + }, "instance_extensions": [ {"name" : "VK_EXT_headless_surface", "spec_version" : "1"}, {"name" : "VK_KHR_wayland_surface", "spec_version" : "6"}, diff --git a/layer/layer.cpp b/layer/layer.cpp index e4208f1..a90a336 100644 --- a/layer/layer.cpp +++ b/layer/layer.cpp @@ -35,6 +35,7 @@ #include "util/custom_allocator.hpp" #include "wsi/wsi_factory.hpp" #include "util/log.hpp" +#include "util/macros.hpp" #define VK_LAYER_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) @@ -263,15 +264,15 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic } /* namespace layer */ -extern "C" { -VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName); +VWL_VKAPI_CALL(PFN_vkVoidFunction) +wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) VWL_API_POST; -VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wsi_layer_vkGetInstanceProcAddr(VkInstance instance, - const char *funcName); +VWL_VKAPI_CALL(PFN_vkVoidFunction) +wsi_layer_vkGetInstanceProcAddr(VkInstance instance, const char *funcName) VWL_API_POST; /* Clean up the dispatch table for this instance. */ -VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL wsi_layer_vkDestroyInstance(VkInstance instance, - const VkAllocationCallbacks *pAllocator) +VWL_VKAPI_CALL(void) +wsi_layer_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) VWL_API_POST { if (instance == VK_NULL_HANDLE) { @@ -289,8 +290,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL wsi_layer_vkDestroyInstance(VkInstanc fn_destroy_instance(instance, pAllocator); } -VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL wsi_layer_vkDestroyDevice(VkDevice device, - const VkAllocationCallbacks *pAllocator) +VWL_VKAPI_CALL(void) +wsi_layer_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) VWL_API_POST { if (device == VK_NULL_HANDLE) { @@ -308,23 +309,22 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL wsi_layer_vkDestroyDevice(VkDevice de fn_destroy_device(device, pAllocator); } -VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL wsi_layer_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkInstance *pInstance) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, + VkInstance *pInstance) VWL_API_POST { return layer::create_instance(pCreateInfo, pAllocator, pInstance); } -VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL wsi_layer_vkCreateDevice(VkPhysicalDevice physicalDevice, - const VkDeviceCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkDevice *pDevice) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) VWL_API_POST { return layer::create_device(physicalDevice, pCreateInfo, pAllocator, pDevice); } -VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL -vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) +VWL_VKAPI_CALL(VkResult) +VK_LAYER_EXPORT wsi_layer_vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) VWL_API_POST { assert(pVersionStruct); assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT); @@ -347,7 +347,8 @@ vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct if (!strcmp(funcName, #func)) \ return (PFN_vkVoidFunction)&wsi_layer_##func; -VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) +VWL_VKAPI_CALL(PFN_vkVoidFunction) +wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) VWL_API_POST { GET_PROC_ADDR(vkCreateSwapchainKHR); GET_PROC_ADDR(vkDestroySwapchainKHR); @@ -365,8 +366,8 @@ VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL wsi_layer_vkGetDeviceProcAddr(VkDe return layer::device_private_data::get(device).disp.GetDeviceProcAddr(device, funcName); } -VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wsi_layer_vkGetInstanceProcAddr(VkInstance instance, - const char *funcName) +VWL_VKAPI_CALL(PFN_vkVoidFunction) +wsi_layer_vkGetInstanceProcAddr(VkInstance instance, const char *funcName) VWL_API_POST { PFN_vkVoidFunction wsi_func = wsi::get_proc_addr(funcName); if (wsi_func) @@ -389,4 +390,3 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wsi_layer_vkGetInstance return layer::instance_private_data::get(instance).disp.GetInstanceProcAddr(instance, funcName); } -} /* extern "C" */ diff --git a/layer/surface_api.cpp b/layer/surface_api.cpp index 7ee582a..bf9aca6 100644 --- a/layer/surface_api.cpp +++ b/layer/surface_api.cpp @@ -27,14 +27,12 @@ #include "private_data.hpp" #include "surface_api.hpp" -extern "C" { - /** * @brief Implements vkGetPhysicalDeviceSurfaceCapabilitiesKHR Vulkan entrypoint. */ -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) VWL_API_POST { auto &instance = layer::instance_private_data::get(physicalDevice); if (instance.should_layer_handle_surface(physicalDevice, surface)) @@ -54,9 +52,10 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysic /** * @brief Implements vkGetPhysicalDeviceSurfaceFormatsKHR Vulkan entrypoint. */ -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, - VkSurfaceFormatKHR *pSurfaceFormats) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, + uint32_t *pSurfaceFormatCount, + VkSurfaceFormatKHR *pSurfaceFormats) VWL_API_POST { auto &instance = layer::instance_private_data::get(physicalDevice); if (instance.should_layer_handle_surface(physicalDevice, surface)) @@ -73,10 +72,10 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDev /** * @brief Implements vkGetPhysicalDeviceSurfacePresentModesKHR Vulkan entrypoint. */ -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - uint32_t *pPresentModeCount, - VkPresentModeKHR *pPresentModes) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, + uint32_t *pPresentModeCount, + VkPresentModeKHR *pPresentModes) VWL_API_POST { auto &instance = layer::instance_private_data::get(physicalDevice); if (instance.should_layer_handle_surface(physicalDevice, surface)) @@ -93,9 +92,9 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysic /** * @brief Implements vkGetPhysicalDeviceSurfaceSupportKHR Vulkan entrypoint. */ -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, VkSurfaceKHR surface, - VkBool32 *pSupported) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, + VkSurfaceKHR surface, VkBool32 *pSupported) VWL_API_POST { auto &instance = layer::instance_private_data::get(physicalDevice); if (instance.should_layer_handle_surface(physicalDevice, surface)) @@ -107,8 +106,9 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDev return instance.disp.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported); } -VKAPI_ATTR void wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, - const VkAllocationCallbacks *pAllocator) +VWL_VKAPI_CALL(void) +wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, + const VkAllocationCallbacks *pAllocator) VWL_API_POST { auto &instance_data = layer::instance_private_data::get(instance); @@ -117,5 +117,3 @@ VKAPI_ATTR void wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR instance_data.remove_surface( surface, util::allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator }); } - -} /* extern "C" */ diff --git a/layer/surface_api.hpp b/layer/surface_api.hpp index b514260..b155b39 100644 --- a/layer/surface_api.hpp +++ b/layer/surface_api.hpp @@ -30,41 +30,41 @@ #pragma once #include - -extern "C" { +#include "util/macros.hpp" /** * @brief Implements vkGetPhysicalDeviceSurfaceCapabilitiesKHR Vulkan entrypoint. */ -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - VkSurfaceCapabilitiesKHR *pSurfaceCapabilities); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) VWL_API_POST; /** * @brief Implements vkGetPhysicalDeviceSurfaceFormatsKHR Vulkan entrypoint. */ -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, - VkSurfaceFormatKHR *pSurfaceFormats); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, + uint32_t *pSurfaceFormatCount, + VkSurfaceFormatKHR *pSurfaceFormats) VWL_API_POST; /** * @brief Implements vkGetPhysicalDeviceSurfacePresentModesKHR Vulkan entrypoint. */ -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, - uint32_t *pPresentModeCount, - VkPresentModeKHR *pPresentModes); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, + uint32_t *pPresentModeCount, + VkPresentModeKHR *pPresentModes) VWL_API_POST; /** * @brief Implements vkGetPhysicalDeviceSurfaceSupportKHR Vulkan entrypoint. */ -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, - uint32_t queueFamilyIndex, VkSurfaceKHR surface, - VkBool32 *pSupported); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, + VkSurfaceKHR surface, VkBool32 *pSupported) VWL_API_POST; /** * @brief Implements vkDestroySurfaceKHR Vulkan entrypoint. */ -VKAPI_ATTR void wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, - const VkAllocationCallbacks *pAllocator); -} +VWL_VKAPI_CALL(void) +wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, + const VkAllocationCallbacks *pAllocator) VWL_API_POST; diff --git a/layer/swapchain_api.cpp b/layer/swapchain_api.cpp index 8ee59a8..3ccbb73 100644 --- a/layer/swapchain_api.cpp +++ b/layer/swapchain_api.cpp @@ -38,11 +38,9 @@ #include "swapchain_api.hpp" #include -extern "C" { - -VKAPI_ATTR VkResult wsi_layer_vkCreateSwapchainKHR(VkDevice device, - const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo, - const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) VWL_API_POST { assert(pSwapchain != nullptr); layer::device_private_data &device_data = layer::device_private_data::get(device); @@ -79,8 +77,9 @@ VKAPI_ATTR VkResult wsi_layer_vkCreateSwapchainKHR(VkDevice device, return result; } -VKAPI_ATTR void wsi_layer_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapc, - const VkAllocationCallbacks *pAllocator) +VWL_VKAPI_CALL(void) +wsi_layer_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapc, + const VkAllocationCallbacks *pAllocator) VWL_API_POST { layer::device_private_data &device_data = layer::device_private_data::get(device); @@ -94,8 +93,9 @@ VKAPI_ATTR void wsi_layer_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR wsi::destroy_surface_swapchain(sc, device_data, pAllocator); } -VKAPI_ATTR VkResult wsi_layer_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapc, - uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapc, uint32_t *pSwapchainImageCount, + VkImage *pSwapchainImages) VWL_API_POST { layer::device_private_data &device_data = layer::device_private_data::get(device); @@ -110,8 +110,9 @@ VKAPI_ATTR VkResult wsi_layer_vkGetSwapchainImagesKHR(VkDevice device, VkSwapcha return sc->get_swapchain_images(pSwapchainImageCount, pSwapchainImages); } -VKAPI_ATTR VkResult wsi_layer_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapc, uint64_t timeout, - VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapc, uint64_t timeout, VkSemaphore semaphore, + VkFence fence, uint32_t *pImageIndex) VWL_API_POST { layer::device_private_data &device_data = layer::device_private_data::get(device); @@ -127,7 +128,8 @@ VKAPI_ATTR VkResult wsi_layer_vkAcquireNextImageKHR(VkDevice device, VkSwapchain return sc->acquire_next_image(timeout, semaphore, fence, pImageIndex); } -VKAPI_ATTR VkResult wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) VWL_API_POST { assert(queue != VK_NULL_HANDLE); assert(pPresentInfo != nullptr); @@ -163,8 +165,9 @@ VKAPI_ATTR VkResult wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentIn return ret; } -VKAPI_ATTR VkResult wsi_layer_vkGetDeviceGroupPresentCapabilitiesKHR( - VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pDeviceGroupPresentCapabilities) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetDeviceGroupPresentCapabilitiesKHR( + VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pDeviceGroupPresentCapabilities) VWL_API_POST { assert(pDeviceGroupPresentCapabilities != nullptr); @@ -179,8 +182,9 @@ VKAPI_ATTR VkResult wsi_layer_vkGetDeviceGroupPresentCapabilitiesKHR( return VK_SUCCESS; } -VKAPI_ATTR VkResult wsi_layer_vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, - VkDeviceGroupPresentModeFlagsKHR *pModes) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, + VkDeviceGroupPresentModeFlagsKHR *pModes) VWL_API_POST { assert(pModes != nullptr); @@ -196,9 +200,9 @@ VKAPI_ATTR VkResult wsi_layer_vkGetDeviceGroupSurfacePresentModesKHR(VkDevice de return VK_SUCCESS; } -VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, uint32_t *pRectCount, - VkRect2D *pRects) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, + uint32_t *pRectCount, VkRect2D *pRects) VWL_API_POST { assert(surface); assert(pRectCount != nullptr); @@ -243,8 +247,9 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysical return result; } -VKAPI_ATTR VkResult wsi_layer_vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo, - uint32_t *pImageIndex) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo, + uint32_t *pImageIndex) VWL_API_POST { assert(pAcquireInfo != VK_NULL_HANDLE); assert(pAcquireInfo->swapchain != VK_NULL_HANDLE); @@ -263,8 +268,9 @@ VKAPI_ATTR VkResult wsi_layer_vkAcquireNextImage2KHR(VkDevice device, const VkAc return sc->acquire_next_image(pAcquireInfo->timeout, pAcquireInfo->semaphore, pAcquireInfo->fence, pImageIndex); } -VKAPI_ATTR VkResult wsi_layer_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkImage *pImage) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, + VkImage *pImage) VWL_API_POST { auto &device_data = layer::device_private_data::get(device); @@ -281,8 +287,9 @@ VKAPI_ATTR VkResult wsi_layer_vkCreateImage(VkDevice device, const VkImageCreate return sc->create_aliased_image_handle(pCreateInfo, pImage); } -VKAPI_ATTR VkResult wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, - const VkBindImageMemoryInfo *pBindInfos) +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, + const VkBindImageMemoryInfo *pBindInfos) VWL_API_POST { auto &device_data = layer::device_private_data::get(device); @@ -312,5 +319,3 @@ VKAPI_ATTR VkResult wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindI } return VK_SUCCESS; } - -} /* extern "C" */ diff --git a/layer/swapchain_api.hpp b/layer/swapchain_api.hpp index 155b3fa..36f1467 100644 --- a/layer/swapchain_api.hpp +++ b/layer/swapchain_api.hpp @@ -31,41 +31,48 @@ #pragma once #include +#include "util/macros.hpp" -extern "C" -{ +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) VWL_API_POST; - VKAPI_ATTR VkResult wsi_layer_vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo, - const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain); +VWL_VKAPI_CALL(void) +wsi_layer_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapc, + const VkAllocationCallbacks *pAllocator) VWL_API_POST; - VKAPI_ATTR void wsi_layer_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapc, - const VkAllocationCallbacks *pAllocator); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapc, uint32_t *pSwapchainImageCount, + VkImage *pSwapchainImages) VWL_API_POST; - VKAPI_ATTR VkResult wsi_layer_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapc, - uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapc, uint64_t timeout, VkSemaphore semaphore, + VkFence fence, uint32_t *pImageIndex) VWL_API_POST; - VKAPI_ATTR VkResult wsi_layer_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapc, uint64_t timeout, - VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) VWL_API_POST; - VKAPI_ATTR VkResult wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo); +/* 1.1 entrypoints */ +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetDeviceGroupPresentCapabilitiesKHR( + VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pDeviceGroupPresentCapabilities) VWL_API_POST; - /* 1.1 entrypoints */ - VKAPI_ATTR VkResult wsi_layer_vkGetDeviceGroupPresentCapabilitiesKHR( - VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pDeviceGroupPresentCapabilities); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, + VkDeviceGroupPresentModeFlagsKHR *pModes) VWL_API_POST; - VKAPI_ATTR VkResult wsi_layer_vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, - VkDeviceGroupPresentModeFlagsKHR *pModes); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, + uint32_t *pRectCount, VkRect2D *pRects) VWL_API_POST; - VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, - VkSurfaceKHR surface, uint32_t *pRectCount, - VkRect2D *pRects); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo, + uint32_t *pImageIndex) VWL_API_POST; - VKAPI_ATTR VkResult wsi_layer_vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo, - uint32_t *pImageIndex); +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, + VkImage *pImage) VWL_API_POST; - VKAPI_ATTR VkResult wsi_layer_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkImage *pImage); - - VKAPI_ATTR VkResult wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, - const VkBindImageMemoryInfo *pBindInfos); -} +VWL_VKAPI_CALL(VkResult) +wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, + const VkBindImageMemoryInfo *pBindInfos) VWL_API_POST; diff --git a/util/custom_allocator.cpp b/util/custom_allocator.cpp index 9e12d65..53ae716 100644 --- a/util/custom_allocator.cpp +++ b/util/custom_allocator.cpp @@ -23,27 +23,27 @@ */ #include "custom_allocator.hpp" +#include "macros.hpp" +#include -extern "C" { +namespace util +{ -static void *default_allocation(void *, size_t size, size_t, VkSystemAllocationScope) +VWL_VKAPI_CALL(void *) default_allocation(void *, size_t size, size_t, VkSystemAllocationScope) VWL_API_POST { return malloc(size); } -static void *default_reallocation(void *, void *pOriginal, size_t size, size_t, VkSystemAllocationScope) +VWL_VKAPI_CALL(void *) +default_reallocation(void *, void *pOriginal, size_t size, size_t, VkSystemAllocationScope) VWL_API_POST { return realloc(pOriginal, size); } -static void default_free(void *, void *pMemory) +VWL_VKAPI_CALL(void) default_free(void *, void *pMemory) VWL_API_POST { free(pMemory); } -} - -namespace util -{ const allocator& allocator::get_generic() { diff --git a/util/macros.hpp b/util/macros.hpp new file mode 100644 index 0000000..058b5be --- /dev/null +++ b/util/macros.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file macros.hpp + * + * @brief Contains useful utility macros used across the project. + */ +#include + +/* + * Macros that are used to mark functions signatures. + * + * VWL_VKAPI_CALL - Replaces the return type of the function. Use to mark functions to use the expected + * Vulkan calling conventions. + * VWL_CAPI_CALL - Replaces the return type of the function. Use to mark other non-Vulkan functions + * that should use the C calling convention, such as callbacks implemented in C++ that + * are used by C code. + * VWL_API_POST - Placed at the end of the function signature. These will typically be + * functions that need to be callable from C. + */ +#define VWL_VKAPI_CALL(ret_type) extern "C" VKAPI_ATTR ret_type VKAPI_CALL +#define VWL_CAPI_CALL(ret_type) extern "C" ret_type +#define VWL_API_POST noexcept diff --git a/wsi/headless/surface_properties.cpp b/wsi/headless/surface_properties.cpp index 663e516..326216b 100644 --- a/wsi/headless/surface_properties.cpp +++ b/wsi/headless/surface_properties.cpp @@ -37,6 +37,7 @@ #include "surface_properties.hpp" #include "surface.hpp" +#include "util/macros.hpp" #define UNUSED(x) ((void)(x)) @@ -169,10 +170,9 @@ VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical return res; } -extern "C" VKAPI_ATTR VkResult VKAPI_CALL CreateHeadlessSurfaceEXT(VkInstance instance, - const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkSurfaceKHR *pSurface) +VWL_VKAPI_CALL(VkResult) +CreateHeadlessSurfaceEXT(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) VWL_API_POST { auto &instance_data = layer::instance_private_data::get(instance); util::allocator allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator }; diff --git a/wsi/wayland/surface.cpp b/wsi/wayland/surface.cpp index c55db21..acf0a6b 100644 --- a/wsi/wayland/surface.cpp +++ b/wsi/wayland/surface.cpp @@ -47,13 +47,15 @@ struct formats_vector namespace { /* Handler for format event of the zwp_linux_dmabuf_v1 interface. */ -extern "C" void zwp_linux_dmabuf_v1_format_impl(void *data, struct zwp_linux_dmabuf_v1 *dma_buf, uint32_t drm_format) +VWL_CAPI_CALL(void) +zwp_linux_dmabuf_v1_format_impl(void *data, struct zwp_linux_dmabuf_v1 *dma_buf, uint32_t drm_format) VWL_API_POST { } /* Handler for modifier event of the zwp_linux_dmabuf_v1 interface. */ -extern "C" void zwp_linux_dmabuf_v1_modifier_impl(void *data, struct zwp_linux_dmabuf_v1 *dma_buf, uint32_t drm_format, - uint32_t modifier_hi, uint32_t modifier_low) +VWL_CAPI_CALL(void) +zwp_linux_dmabuf_v1_modifier_impl(void *data, struct zwp_linux_dmabuf_v1 *dma_buf, uint32_t drm_format, + uint32_t modifier_hi, uint32_t modifier_low) VWL_API_POST { auto *drm_supported_formats = reinterpret_cast(data); @@ -133,8 +135,9 @@ surface::surface(const init_parameters ¶ms) { } -void surface_registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, - uint32_t version) +VWL_CAPI_CALL(void) +surface_registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, + uint32_t version) VWL_API_POST { auto wsi_surface = reinterpret_cast(data); diff --git a/wsi/wayland/surface.hpp b/wsi/wayland/surface.hpp index 164e683..4d72d8d 100644 --- a/wsi/wayland/surface.hpp +++ b/wsi/wayland/surface.hpp @@ -33,6 +33,7 @@ #include "wsi/surface.hpp" #include "surface_properties.hpp" #include "wl_object_owner.hpp" +#include "util/macros.hpp" namespace wsi { @@ -48,8 +49,9 @@ struct drm_format_pair /** * Wayland callback for global wl_registry events to handle global objects required by @ref wsi::wayland::surface */ -extern "C" void surface_registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, - const char *interface, uint32_t version); +VWL_CAPI_CALL(void) +surface_registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, + uint32_t version) VWL_API_POST; class surface : public wsi::surface { @@ -131,7 +133,7 @@ private: bool init(); friend void surface_registry_handler(void *data, struct wl_registry *wl_registry, uint32_t name, - const char *interface, uint32_t version); + const char *interface, uint32_t version) VWL_API_POST; /** The native Wayland display */ wl_display *wayland_display; diff --git a/wsi/wayland/surface_properties.cpp b/wsi/wayland/surface_properties.cpp index 41f237e..60f550c 100644 --- a/wsi/wayland/surface_properties.cpp +++ b/wsi/wayland/surface_properties.cpp @@ -39,6 +39,7 @@ #include "wl_object_owner.hpp" #include "util/drm/drm_utils.hpp" #include "util/log.hpp" +#include "util/macros.hpp" #define NELEMS(x) (sizeof(x) / sizeof(x[0])) @@ -222,8 +223,9 @@ VkResult surface_properties::get_required_device_extensions(util::extension_list } /* TODO: Check for zwp_linux_dmabuf_v1 protocol in display */ -VkBool32 GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physical_device, uint32_t queue_index, - struct wl_display *display) +VWL_VKAPI_CALL(VkBool32) +GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physical_device, uint32_t queue_index, + struct wl_display *display) { bool dev_supports_sync = sync_fd_fence_sync::is_supported(layer::instance_private_data::get(physical_device), physical_device); @@ -235,8 +237,9 @@ VkBool32 GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physica return VK_TRUE; } -extern "C" VkResult CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) +VWL_VKAPI_CALL(VkResult) +CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) VWL_API_POST { auto &instance_data = layer::instance_private_data::get(instance); util::allocator allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator }; diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index 52ace6f..8f33da3 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -41,6 +41,7 @@ #include "util/drm/drm_utils.hpp" #include "util/log.hpp" #include "util/helpers.hpp" +#include "util/macros.hpp" #define MAX_PLANES 4 @@ -144,8 +145,8 @@ VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKH return VK_SUCCESS; } -extern "C" void create_succeeded(void *data, struct zwp_linux_buffer_params_v1 *params, - struct wl_buffer *buffer) +VWL_CAPI_CALL(void) +create_succeeded(void *data, struct zwp_linux_buffer_params_v1 *params, struct wl_buffer *buffer) VWL_API_POST { auto wayland_buffer = reinterpret_cast(data); *wayland_buffer = buffer; @@ -153,14 +154,14 @@ extern "C" void create_succeeded(void *data, struct zwp_linux_buffer_params_v1 * zwp_linux_buffer_params_v1_destroy(params); } -extern "C" void create_failed(void *data, struct zwp_linux_buffer_params_v1 *params) +VWL_CAPI_CALL(void) create_failed(void *data, struct zwp_linux_buffer_params_v1 *params) { zwp_linux_buffer_params_v1_destroy(params); } static const struct zwp_linux_buffer_params_v1_listener params_listener = { create_succeeded, create_failed }; -extern "C" void buffer_release(void *data, struct wl_buffer *wayl_buffer) +VWL_CAPI_CALL(void) buffer_release(void *data, struct wl_buffer *wayl_buffer) VWL_API_POST { auto sc = reinterpret_cast(data); sc->release_buffer(wayl_buffer); diff --git a/wsi/wayland/wl_helpers.cpp b/wsi/wayland/wl_helpers.cpp index b1e417e..5b324a1 100644 --- a/wsi/wayland/wl_helpers.cpp +++ b/wsi/wayland/wl_helpers.cpp @@ -34,87 +34,84 @@ #include "util/log.hpp" -extern "C" { +int dispatch_queue(struct wl_display *display, struct wl_event_queue *queue, int timeout) +{ + int err; + struct pollfd pfd = {}; + int retval; - int dispatch_queue(struct wl_display *display, struct wl_event_queue *queue, int timeout) + /* Before we sleep, dispatch any pending events. prepare_read_queue will return 0 whilst there are pending + * events to dispatch on the queue. */ + while (0 != wl_display_prepare_read_queue(display, queue)) { - int err; - struct pollfd pfd = {}; - int retval; - - /* Before we sleep, dispatch any pending events. prepare_read_queue will return 0 whilst there are pending - * events to dispatch on the queue. */ - while (0 != wl_display_prepare_read_queue(display, queue)) + /* dispatch_queue_pending returns -1 on error, or the number of events dispatched otherwise. If we + * already dispatched some events, then we might not need to sleep, as we might have just dispatched + * the event we want, so return immediately. */ + err = wl_display_dispatch_queue_pending(display, queue); + if (err) { - /* dispatch_queue_pending returns -1 on error, or the number of events dispatched otherwise. If we - * already dispatched some events, then we might not need to sleep, as we might have just dispatched - * the event we want, so return immediately. */ - err = wl_display_dispatch_queue_pending(display, queue); - if (err) - { - return (0 > err) ? -1 : 1; - } + return (0 > err) ? -1 : 1; } + } - /* wl_display_read_events performs a non-blocking read. */ - pfd.fd = wl_display_get_fd(display); - pfd.events = POLLIN; - while (true) + /* wl_display_read_events performs a non-blocking read. */ + pfd.fd = wl_display_get_fd(display); + pfd.events = POLLIN; + while (true) + { + /* Timeout is given in milliseconds. A return value of 0, or -1 with errno set to EINTR means that we + * should retry as the timeout was exceeded or we were interrupted by a signal, respectively. A + * return value of 1 means that something happened, and we should inspect the pollfd structure to see + * just what that was. + */ + err = poll(&pfd, 1, timeout); + if (0 == err) { - /* Timeout is given in milliseconds. A return value of 0, or -1 with errno set to EINTR means that we - * should retry as the timeout was exceeded or we were interrupted by a signal, respectively. A - * return value of 1 means that something happened, and we should inspect the pollfd structure to see - * just what that was. - */ - err = poll(&pfd, 1, timeout); - if (0 == err) + /* Timeout. */ + wl_display_cancel_read(display); + return 0; + } + else if (-1 == err) + { + if (EINTR == errno) + { + /* Interrupted by a signal; restart. This resets the timeout. */ + continue; + } + else { - /* Timeout. */ + /* Something else bad happened; abort. */ wl_display_cancel_read(display); - return 0; + return -1; } - else if (-1 == err) + } + else + { + if (POLLIN == pfd.revents) { - if (EINTR == errno) - { - /* Interrupted by a signal; restart. This resets the timeout. */ - continue; - } - else - { - /* Something else bad happened; abort. */ - wl_display_cancel_read(display); - return -1; - } + /* We have data to read, and no errors; proceed to read_events. */ + break; } else { - if (POLLIN == pfd.revents) - { - /* We have data to read, and no errors; proceed to read_events. */ - break; - } - else - { - /* An error occurred, e.g. file descriptor was closed from underneath us. */ - wl_display_cancel_read(display); - return -1; - } + /* An error occurred, e.g. file descriptor was closed from underneath us. */ + wl_display_cancel_read(display); + return -1; } } + } - /* Actually read the events from the display. A failure in read_events calls cancel_read internally for us, - * so we don't need to do that here. */ - err = wl_display_read_events(display); - if (0 != err) - { - return -1; - } + /* Actually read the events from the display. A failure in read_events calls cancel_read internally for us, + * so we don't need to do that here. */ + err = wl_display_read_events(display); + if (0 != err) + { + return -1; + } - /* Finally, if we read any events relevant to our queue, we can dispatch them. */ - err = wl_display_dispatch_queue_pending(display, queue); - retval = err < 0 ? -1 : 1; + /* Finally, if we read any events relevant to our queue, we can dispatch them. */ + err = wl_display_dispatch_queue_pending(display, queue); + retval = err < 0 ? -1 : 1; - return retval; - } + return retval; } diff --git a/wsi/wayland/wl_helpers.hpp b/wsi/wayland/wl_helpers.hpp index 785c0c6..8c6d548 100644 --- a/wsi/wayland/wl_helpers.hpp +++ b/wsi/wayland/wl_helpers.hpp @@ -28,21 +28,19 @@ #include #include "util/custom_allocator.hpp" -extern "C" { - /** - * @brief Dispatch events from a Wayland event queue - * - * Dispatch events from a given Wayland display event queue, including calling event handlers, and flush out any - * requests the event handlers may have written. Specification of a timeout allows the wait to be bounded. If any - * events are already pending dispatch (have been read from the display by another thread or event queue), they - * will be dispatched and the function will return immediately, without waiting for new events to arrive. - * - * @param display Wayland display to dispatch events from - * @param queue Event queue to dispatch events from; other event queues will not have their handlers called from - * within this function - * @param timeout Maximum time to wait for events to arrive, in milliseconds - * @return 1 if one or more events were dispatched on this queue, 0 if the timeout was reached without any - * events being dispatched, or -1 on error. - */ - int dispatch_queue(struct wl_display *display, struct wl_event_queue *queue, int timeout); -} +/** + * @brief Dispatch events from a Wayland event queue + * + * Dispatch events from a given Wayland display event queue, including calling event handlers, and flush out any + * requests the event handlers may have written. Specification of a timeout allows the wait to be bounded. If any + * events are already pending dispatch (have been read from the display by another thread or event queue), they + * will be dispatched and the function will return immediately, without waiting for new events to arrive. + * + * @param display Wayland display to dispatch events from + * @param queue Event queue to dispatch events from; other event queues will not have their handlers called from + * within this function + * @param timeout Maximum time to wait for events to arrive, in milliseconds + * @return 1 if one or more events were dispatched on this queue, 0 if the timeout was reached without any + * events being dispatched, or -1 on error. + */ +int dispatch_queue(struct wl_display *display, struct wl_event_queue *queue, int timeout); -- 2.7.4