1 /* 2 * Copyright 2016 Red Hat 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 "radv_private.h" 27 #include "wsi_common.h" 28 29 static const struct wsi_callbacks wsi_cbs = { 30 .get_phys_device_format_properties = radv_GetPhysicalDeviceFormatProperties, 31 }; 32 33 VkResult 34 radv_init_wsi(struct radv_physical_device *physical_device) 35 { 36 VkResult result; 37 38 memset(physical_device->wsi_device.wsi, 0, sizeof(physical_device->wsi_device.wsi)); 39 40 #ifdef VK_USE_PLATFORM_XCB_KHR 41 result = wsi_x11_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc); 42 if (result != VK_SUCCESS) 43 return result; 44 #endif 45 46 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 47 result = wsi_wl_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc, 48 radv_physical_device_to_handle(physical_device), 49 &wsi_cbs); 50 if (result != VK_SUCCESS) { 51 #ifdef VK_USE_PLATFORM_XCB_KHR 52 wsi_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc); 53 #endif 54 return result; 55 } 56 #endif 57 58 return VK_SUCCESS; 59 } 60 61 void 62 radv_finish_wsi(struct radv_physical_device *physical_device) 63 { 64 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 65 wsi_wl_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc); 66 #endif 67 #ifdef VK_USE_PLATFORM_XCB_KHR 68 wsi_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc); 69 #endif 70 } 71 72 void radv_DestroySurfaceKHR( 73 VkInstance _instance, 74 VkSurfaceKHR _surface, 75 const VkAllocationCallbacks* pAllocator) 76 { 77 RADV_FROM_HANDLE(radv_instance, instance, _instance); 78 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 79 80 vk_free2(&instance->alloc, pAllocator, surface); 81 } 82 83 VkResult radv_GetPhysicalDeviceSurfaceSupportKHR( 84 VkPhysicalDevice physicalDevice, 85 uint32_t queueFamilyIndex, 86 VkSurfaceKHR _surface, 87 VkBool32* pSupported) 88 { 89 RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); 90 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 91 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform]; 92 93 return iface->get_support(surface, &device->wsi_device, 94 &device->instance->alloc, 95 queueFamilyIndex, pSupported); 96 } 97 98 VkResult radv_GetPhysicalDeviceSurfaceCapabilitiesKHR( 99 VkPhysicalDevice physicalDevice, 100 VkSurfaceKHR _surface, 101 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) 102 { 103 RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); 104 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 105 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform]; 106 107 return iface->get_capabilities(surface, pSurfaceCapabilities); 108 } 109 110 VkResult radv_GetPhysicalDeviceSurfaceFormatsKHR( 111 VkPhysicalDevice physicalDevice, 112 VkSurfaceKHR _surface, 113 uint32_t* pSurfaceFormatCount, 114 VkSurfaceFormatKHR* pSurfaceFormats) 115 { 116 RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); 117 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 118 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform]; 119 120 return iface->get_formats(surface, &device->wsi_device, pSurfaceFormatCount, 121 pSurfaceFormats); 122 } 123 124 VkResult radv_GetPhysicalDeviceSurfacePresentModesKHR( 125 VkPhysicalDevice physicalDevice, 126 VkSurfaceKHR _surface, 127 uint32_t* pPresentModeCount, 128 VkPresentModeKHR* pPresentModes) 129 { 130 RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); 131 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 132 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform]; 133 134 return iface->get_present_modes(surface, pPresentModeCount, 135 pPresentModes); 136 } 137 138 static VkResult 139 radv_wsi_image_create(VkDevice device_h, 140 const VkSwapchainCreateInfoKHR *pCreateInfo, 141 const VkAllocationCallbacks* pAllocator, 142 VkImage *image_p, 143 VkDeviceMemory *memory_p, 144 uint32_t *size, 145 uint32_t *offset, 146 uint32_t *row_pitch, int *fd_p) 147 { 148 struct radv_device *device = radv_device_from_handle(device_h); 149 VkResult result = VK_SUCCESS; 150 struct radeon_surf *surface; 151 VkImage image_h; 152 struct radv_image *image; 153 bool bret; 154 int fd; 155 156 result = radv_image_create(device_h, 157 &(struct radv_image_create_info) { 158 .vk_info = 159 &(VkImageCreateInfo) { 160 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 161 .imageType = VK_IMAGE_TYPE_2D, 162 .format = pCreateInfo->imageFormat, 163 .extent = { 164 .width = pCreateInfo->imageExtent.width, 165 .height = pCreateInfo->imageExtent.height, 166 .depth = 1 167 }, 168 .mipLevels = 1, 169 .arrayLayers = 1, 170 .samples = 1, 171 /* FIXME: Need a way to use X tiling to allow scanout */ 172 .tiling = VK_IMAGE_TILING_OPTIMAL, 173 .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 174 .flags = 0, 175 }, 176 .scanout = true}, 177 NULL, 178 &image_h); 179 if (result != VK_SUCCESS) 180 return result; 181 182 image = radv_image_from_handle(image_h); 183 184 VkDeviceMemory memory_h; 185 struct radv_device_memory *memory; 186 result = radv_AllocateMemory(device_h, 187 &(VkMemoryAllocateInfo) { 188 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 189 .allocationSize = image->size, 190 .memoryTypeIndex = 0, 191 }, 192 NULL /* XXX: pAllocator */, 193 &memory_h); 194 if (result != VK_SUCCESS) 195 goto fail_create_image; 196 197 memory = radv_device_memory_from_handle(memory_h); 198 199 radv_BindImageMemory(VK_NULL_HANDLE, image_h, memory_h, 0); 200 201 bret = device->ws->buffer_get_fd(device->ws, 202 memory->bo, &fd); 203 if (bret == false) 204 goto fail_alloc_memory; 205 206 { 207 struct radeon_bo_metadata metadata; 208 radv_init_metadata(device, image, &metadata); 209 device->ws->buffer_set_metadata(memory->bo, &metadata); 210 } 211 surface = &image->surface; 212 213 *image_p = image_h; 214 *memory_p = memory_h; 215 *fd_p = fd; 216 *size = image->size; 217 *offset = image->offset; 218 *row_pitch = surface->level[0].pitch_bytes; 219 return VK_SUCCESS; 220 fail_alloc_memory: 221 radv_FreeMemory(device_h, memory_h, pAllocator); 222 223 fail_create_image: 224 radv_DestroyImage(device_h, image_h, pAllocator); 225 226 return result; 227 } 228 229 static void 230 radv_wsi_image_free(VkDevice device, 231 const VkAllocationCallbacks* pAllocator, 232 VkImage image_h, 233 VkDeviceMemory memory_h) 234 { 235 radv_DestroyImage(device, image_h, pAllocator); 236 237 radv_FreeMemory(device, memory_h, pAllocator); 238 } 239 240 static const struct wsi_image_fns radv_wsi_image_fns = { 241 .create_wsi_image = radv_wsi_image_create, 242 .free_wsi_image = radv_wsi_image_free, 243 }; 244 245 VkResult radv_CreateSwapchainKHR( 246 VkDevice _device, 247 const VkSwapchainCreateInfoKHR* pCreateInfo, 248 const VkAllocationCallbacks* pAllocator, 249 VkSwapchainKHR* pSwapchain) 250 { 251 RADV_FROM_HANDLE(radv_device, device, _device); 252 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface); 253 struct wsi_interface *iface = 254 device->physical_device->wsi_device.wsi[surface->platform]; 255 struct wsi_swapchain *swapchain; 256 const VkAllocationCallbacks *alloc; 257 if (pAllocator) 258 alloc = pAllocator; 259 else 260 alloc = &device->alloc; 261 VkResult result = iface->create_swapchain(surface, _device, 262 &device->physical_device->wsi_device, 263 pCreateInfo, 264 alloc, &radv_wsi_image_fns, 265 &swapchain); 266 if (result != VK_SUCCESS) 267 return result; 268 269 if (pAllocator) 270 swapchain->alloc = *pAllocator; 271 else 272 swapchain->alloc = device->alloc; 273 274 for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) 275 swapchain->fences[i] = VK_NULL_HANDLE; 276 277 *pSwapchain = wsi_swapchain_to_handle(swapchain); 278 279 return VK_SUCCESS; 280 } 281 282 void radv_DestroySwapchainKHR( 283 VkDevice _device, 284 VkSwapchainKHR _swapchain, 285 const VkAllocationCallbacks* pAllocator) 286 { 287 RADV_FROM_HANDLE(radv_device, device, _device); 288 RADV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 289 const VkAllocationCallbacks *alloc; 290 291 if (!_swapchain) 292 return; 293 294 if (pAllocator) 295 alloc = pAllocator; 296 else 297 alloc = &device->alloc; 298 299 for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) { 300 if (swapchain->fences[i] != VK_NULL_HANDLE) 301 radv_DestroyFence(_device, swapchain->fences[i], pAllocator); 302 } 303 304 swapchain->destroy(swapchain, alloc); 305 } 306 307 VkResult radv_GetSwapchainImagesKHR( 308 VkDevice device, 309 VkSwapchainKHR _swapchain, 310 uint32_t* pSwapchainImageCount, 311 VkImage* pSwapchainImages) 312 { 313 RADV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 314 315 return swapchain->get_images(swapchain, pSwapchainImageCount, 316 pSwapchainImages); 317 } 318 319 VkResult radv_AcquireNextImageKHR( 320 VkDevice device, 321 VkSwapchainKHR _swapchain, 322 uint64_t timeout, 323 VkSemaphore semaphore, 324 VkFence _fence, 325 uint32_t* pImageIndex) 326 { 327 RADV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 328 RADV_FROM_HANDLE(radv_fence, fence, _fence); 329 330 VkResult result = swapchain->acquire_next_image(swapchain, timeout, semaphore, 331 pImageIndex); 332 333 if (fence && result == VK_SUCCESS) { 334 fence->submitted = true; 335 fence->signalled = true; 336 } 337 338 return result; 339 } 340 341 VkResult radv_QueuePresentKHR( 342 VkQueue _queue, 343 const VkPresentInfoKHR* pPresentInfo) 344 { 345 RADV_FROM_HANDLE(radv_queue, queue, _queue); 346 VkResult result = VK_SUCCESS; 347 348 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 349 RADV_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]); 350 351 assert(radv_device_from_handle(swapchain->device) == queue->device); 352 if (swapchain->fences[0] == VK_NULL_HANDLE) { 353 result = radv_CreateFence(radv_device_to_handle(queue->device), 354 &(VkFenceCreateInfo) { 355 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 356 .flags = 0, 357 }, &swapchain->alloc, &swapchain->fences[0]); 358 if (result != VK_SUCCESS) 359 return result; 360 } else { 361 radv_ResetFences(radv_device_to_handle(queue->device), 362 1, &swapchain->fences[0]); 363 } 364 365 RADV_FROM_HANDLE(radv_fence, fence, swapchain->fences[0]); 366 struct radeon_winsys_fence *base_fence = fence->fence; 367 struct radeon_winsys_ctx *ctx = queue->hw_ctx; 368 queue->device->ws->cs_submit(ctx, queue->queue_idx, 369 &queue->device->empty_cs[queue->queue_family_index], 370 1, 371 (struct radeon_winsys_sem **)pPresentInfo->pWaitSemaphores, 372 pPresentInfo->waitSemaphoreCount, NULL, 0, false, base_fence); 373 fence->submitted = true; 374 375 result = swapchain->queue_present(swapchain, 376 pPresentInfo->pImageIndices[i]); 377 /* TODO: What if one of them returns OUT_OF_DATE? */ 378 if (result != VK_SUCCESS) 379 return result; 380 381 VkFence last = swapchain->fences[2]; 382 swapchain->fences[2] = swapchain->fences[1]; 383 swapchain->fences[1] = swapchain->fences[0]; 384 swapchain->fences[0] = last; 385 386 if (last != VK_NULL_HANDLE) { 387 radv_WaitForFences(radv_device_to_handle(queue->device), 388 1, &last, true, 1); 389 } 390 391 } 392 393 return VK_SUCCESS; 394 } 395