1/* 2 * Copyright © 2020 Raspberry Pi 3 * based on intel anv code: 4 * Copyright © 2015 Intel Corporation 5 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 * IN THE SOFTWARE. 24 */ 25 26#include "v3dv_private.h" 27#include "drm-uapi/drm_fourcc.h" 28#include "wsi_common_entrypoints.h" 29#include "vk_format_info.h" 30#include "vk_util.h" 31#include "wsi_common.h" 32 33static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 34v3dv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName) 35{ 36 V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice); 37 PFN_vkVoidFunction func; 38 39 func = vk_instance_dispatch_table_get(&pdevice->vk.instance->dispatch_table, pName); 40 if (func != NULL) 41 return func; 42 43 func = vk_physical_device_dispatch_table_get(&pdevice->vk.dispatch_table, pName); 44 if (func != NULL) 45 return func; 46 47 return vk_device_dispatch_table_get(&vk_device_trampolines, pName); 48} 49 50static bool 51v3dv_wsi_can_present_on_device(VkPhysicalDevice _pdevice, int fd) 52{ 53 V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, _pdevice); 54 55 drmDevicePtr fd_devinfo, display_devinfo; 56 int ret; 57 58 ret = drmGetDevice2(fd, 0, &fd_devinfo); 59 if (ret) 60 return false; 61 62 ret = drmGetDevice2(pdevice->display_fd, 0, &display_devinfo); 63 if (ret) { 64 drmFreeDevice(&fd_devinfo); 65 return false; 66 } 67 68 bool result = drmDevicesEqual(fd_devinfo, display_devinfo); 69 70 drmFreeDevice(&fd_devinfo); 71 drmFreeDevice(&display_devinfo); 72 return result; 73} 74 75VkResult 76v3dv_wsi_init(struct v3dv_physical_device *physical_device) 77{ 78 VkResult result; 79 80 result = wsi_device_init(&physical_device->wsi_device, 81 v3dv_physical_device_to_handle(physical_device), 82 v3dv_wsi_proc_addr, 83 &physical_device->vk.instance->alloc, 84 physical_device->master_fd, NULL, false); 85 86 if (result != VK_SUCCESS) 87 return result; 88 89 physical_device->wsi_device.supports_modifiers = true; 90 physical_device->wsi_device.can_present_on_device = 91 v3dv_wsi_can_present_on_device; 92 93 physical_device->vk.wsi_device = &physical_device->wsi_device; 94 95 return VK_SUCCESS; 96} 97 98void 99v3dv_wsi_finish(struct v3dv_physical_device *physical_device) 100{ 101 physical_device->vk.wsi_device = NULL; 102 wsi_device_finish(&physical_device->wsi_device, 103 &physical_device->vk.instance->alloc); 104} 105 106static void 107constraint_surface_capabilities(VkSurfaceCapabilitiesKHR *caps) 108{ 109 /* Our display pipeline requires that images are linear, so we cannot 110 * ensure that our swapchain images can be sampled. If we are running under 111 * a compositor in windowed mode, the DRM modifier negotiation should 112 * probably end up selecting an UIF layout for the swapchain images but it 113 * may still choose linear and send images directly for scanout if the 114 * surface is in fullscreen mode for example. If we are not running under 115 * a compositor, then we would always need them to be linear anyway. 116 */ 117 caps->supportedUsageFlags &= ~VK_IMAGE_USAGE_SAMPLED_BIT; 118} 119 120VKAPI_ATTR VkResult VKAPI_CALL 121v3dv_GetPhysicalDeviceSurfaceCapabilitiesKHR( 122 VkPhysicalDevice physicalDevice, 123 VkSurfaceKHR surface, 124 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) 125{ 126 VkResult result; 127 result = wsi_GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, 128 surface, 129 pSurfaceCapabilities); 130 constraint_surface_capabilities(pSurfaceCapabilities); 131 return result; 132} 133 134VKAPI_ATTR VkResult VKAPI_CALL 135v3dv_GetPhysicalDeviceSurfaceCapabilities2KHR( 136 VkPhysicalDevice physicalDevice, 137 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, 138 VkSurfaceCapabilities2KHR* pSurfaceCapabilities) 139{ 140 VkResult result; 141 result = wsi_GetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, 142 pSurfaceInfo, 143 pSurfaceCapabilities); 144 constraint_surface_capabilities(&pSurfaceCapabilities->surfaceCapabilities); 145 return result; 146} 147 148VKAPI_ATTR VkResult VKAPI_CALL 149v3dv_CreateSwapchainKHR( 150 VkDevice _device, 151 const VkSwapchainCreateInfoKHR* pCreateInfo, 152 const VkAllocationCallbacks* pAllocator, 153 VkSwapchainKHR* pSwapchain) 154{ 155 V3DV_FROM_HANDLE(v3dv_device, device, _device); 156 struct v3dv_instance *instance = device->instance; 157 struct v3dv_physical_device *pdevice = &instance->physicalDevice; 158 159 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface); 160 VkResult result = 161 v3dv_physical_device_acquire_display(instance, pdevice, surface); 162 if (result != VK_SUCCESS) 163 return result; 164 165 return wsi_CreateSwapchainKHR(_device, pCreateInfo, pAllocator, pSwapchain); 166} 167 168struct v3dv_image * 169v3dv_wsi_get_image_from_swapchain(VkSwapchainKHR swapchain, uint32_t index) 170{ 171 uint32_t n_images = index + 1; 172 VkImage *images = malloc(sizeof(*images) * n_images); 173 VkResult result = wsi_common_get_images(swapchain, &n_images, images); 174 175 if (result != VK_SUCCESS && result != VK_INCOMPLETE) { 176 free(images); 177 return NULL; 178 } 179 180 V3DV_FROM_HANDLE(v3dv_image, image, images[index]); 181 free(images); 182 183 return image; 184} 185 186VKAPI_ATTR VkResult VKAPI_CALL 187v3dv_AcquireNextImage2KHR( 188 VkDevice _device, 189 const VkAcquireNextImageInfoKHR* pAcquireInfo, 190 uint32_t* pImageIndex) 191{ 192 V3DV_FROM_HANDLE(v3dv_device, device, _device); 193 V3DV_FROM_HANDLE(v3dv_fence, fence, pAcquireInfo->fence); 194 V3DV_FROM_HANDLE(v3dv_semaphore, semaphore, pAcquireInfo->semaphore); 195 196 struct v3dv_physical_device *pdevice = &device->instance->physicalDevice; 197 198 VkResult result; 199 result = wsi_common_acquire_next_image2(&pdevice->wsi_device, _device, 200 pAcquireInfo, pImageIndex); 201 202 if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { 203 if (fence) 204 drmSyncobjSignal(pdevice->render_fd, &fence->sync, 1); 205 if (semaphore) 206 drmSyncobjSignal(pdevice->render_fd, &semaphore->sync, 1); 207 } 208 209 return result; 210} 211