* IN THE SOFTWARE.
*/
-#include "anv_wsi.h"
+#include "anv_private.h"
+#include "wsi_common.h"
#include "vk_format_info.h"
+#include "vk_util.h"
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+static const struct wsi_callbacks wsi_cbs = {
+ .get_phys_device_format_properties = anv_GetPhysicalDeviceFormatProperties,
+};
+#endif
+
VkResult
anv_init_wsi(struct anv_physical_device *physical_device)
{
memset(physical_device->wsi_device.wsi, 0, sizeof(physical_device->wsi_device.wsi));
#ifdef VK_USE_PLATFORM_XCB_KHR
- result = anv_x11_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
+ result = wsi_x11_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
if (result != VK_SUCCESS)
return result;
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
- result = anv_wl_init_wsi(physical_device);
+ result = wsi_wl_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc,
+ anv_physical_device_to_handle(physical_device),
+ &wsi_cbs);
if (result != VK_SUCCESS) {
#ifdef VK_USE_PLATFORM_XCB_KHR
- anv_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
+ wsi_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
#endif
return result;
}
anv_finish_wsi(struct anv_physical_device *physical_device)
{
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
- anv_wl_finish_wsi(physical_device);
+ wsi_wl_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
- anv_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
+ wsi_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
#endif
}
const VkAllocationCallbacks* pAllocator)
{
ANV_FROM_HANDLE(anv_instance, instance, _instance);
- ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+
+ if (!surface)
+ return;
vk_free2(&instance->alloc, pAllocator, surface);
}
VkBool32* pSupported)
{
ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
- ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
- struct anv_wsi_interface *iface = device->wsi_device.wsi[surface->platform];
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
return iface->get_support(surface, &device->wsi_device,
&device->instance->alloc,
- queueFamilyIndex, pSupported);
+ queueFamilyIndex, device->local_fd, false, pSupported);
}
VkResult anv_GetPhysicalDeviceSurfaceCapabilitiesKHR(
VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
{
ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
- ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
- struct anv_wsi_interface *iface = device->wsi_device.wsi[surface->platform];
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
return iface->get_capabilities(surface, pSurfaceCapabilities);
}
+VkResult anv_GetPhysicalDeviceSurfaceCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ VkSurfaceCapabilities2KHR* pSurfaceCapabilities)
+{
+ ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
+ struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
+
+ return iface->get_capabilities2(surface, pSurfaceInfo->pNext,
+ pSurfaceCapabilities);
+}
+
VkResult anv_GetPhysicalDeviceSurfaceFormatsKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR _surface,
VkSurfaceFormatKHR* pSurfaceFormats)
{
ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
- ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
- struct anv_wsi_interface *iface = device->wsi_device.wsi[surface->platform];
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
return iface->get_formats(surface, &device->wsi_device, pSurfaceFormatCount,
pSurfaceFormats);
}
+VkResult anv_GetPhysicalDeviceSurfaceFormats2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats)
+{
+ ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
+ struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
+
+ return iface->get_formats2(surface, &device->wsi_device, pSurfaceInfo->pNext,
+ pSurfaceFormatCount, pSurfaceFormats);
+}
+
VkResult anv_GetPhysicalDeviceSurfacePresentModesKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR _surface,
VkPresentModeKHR* pPresentModes)
{
ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
- ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
- struct anv_wsi_interface *iface = device->wsi_device.wsi[surface->platform];
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
return iface->get_present_modes(surface, pPresentModeCount,
pPresentModes);
static VkResult
-x11_anv_wsi_image_create(VkDevice device_h,
- const VkSwapchainCreateInfoKHR *pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkImage *image_p,
- VkDeviceMemory *memory_p,
- uint32_t *size,
- uint32_t *offset,
- uint32_t *row_pitch, int *fd_p)
+anv_wsi_image_create(VkDevice device_h,
+ const VkSwapchainCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ bool different_gpu,
+ bool linear,
+ VkImage *image_p,
+ VkDeviceMemory *memory_p,
+ uint32_t *size,
+ uint32_t *offset,
+ uint32_t *row_pitch, int *fd_p)
{
struct anv_device *device = anv_device_from_handle(device_h);
VkImage image_h;
goto fail_create_image;
memory = anv_device_memory_from_handle(memory_h);
- memory->bo.is_winsys_bo = true;
- anv_BindImageMemory(VK_NULL_HANDLE, image_h, memory_h, 0);
+ /* We need to set the WRITE flag on window system buffers so that GEM will
+ * know we're writing to them and synchronize uses on other rings (eg if
+ * the display server uses the blitter ring).
+ */
+ memory->bo->flags &= ~EXEC_OBJECT_ASYNC;
+ memory->bo->flags |= EXEC_OBJECT_WRITE;
+
+ anv_BindImageMemory(device_h, image_h, memory_h, 0);
+ assert(image->size == 0);
- struct anv_surface *surface = &image->color_surface;
+ struct anv_surface *surface = &image->planes[0].surface;
assert(surface->isl.tiling == ISL_TILING_X);
*row_pitch = surface->isl.row_pitch;
- int ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
+ int ret = anv_gem_set_tiling(device, memory->bo->gem_handle,
surface->isl.row_pitch, I915_TILING_X);
if (ret) {
/* FINISHME: Choose a better error. */
- result = vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY,
+ result = vk_errorf(device->instance, device,
+ VK_ERROR_OUT_OF_DEVICE_MEMORY,
"set_tiling failed: %m");
goto fail_alloc_memory;
}
- int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
+ int fd = anv_gem_handle_to_fd(device, memory->bo->gem_handle);
if (fd == -1) {
/* FINISHME: Choose a better error. */
- result = vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY,
+ result = vk_errorf(device->instance, device,
+ VK_ERROR_OUT_OF_DEVICE_MEMORY,
"handle_to_fd failed: %m");
goto fail_alloc_memory;
}
*memory_p = memory_h;
*fd_p = fd;
*size = image->size;
- *offset = image->offset;
+ *offset = 0;
return VK_SUCCESS;
fail_alloc_memory:
anv_FreeMemory(device_h, memory_h, pAllocator);
}
static void
-x11_anv_wsi_image_free(VkDevice device,
- const VkAllocationCallbacks* pAllocator,
- VkImage image_h,
- VkDeviceMemory memory_h)
+anv_wsi_image_free(VkDevice device,
+ const VkAllocationCallbacks* pAllocator,
+ VkImage image_h,
+ VkDeviceMemory memory_h)
{
anv_DestroyImage(device, image_h, pAllocator);
anv_FreeMemory(device, memory_h, pAllocator);
}
-static const struct anv_wsi_image_fns anv_wsi_image_fns = {
- .create_wsi_image = x11_anv_wsi_image_create,
- .free_wsi_image = x11_anv_wsi_image_free,
+static const struct wsi_image_fns anv_wsi_image_fns = {
+ .create_wsi_image = anv_wsi_image_create,
+ .free_wsi_image = anv_wsi_image_free,
};
VkResult anv_CreateSwapchainKHR(
VkSwapchainKHR* pSwapchain)
{
ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, pCreateInfo->surface);
- struct anv_wsi_interface *iface =
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
+ struct wsi_interface *iface =
device->instance->physicalDevice.wsi_device.wsi[surface->platform];
- struct anv_swapchain *swapchain;
+ struct wsi_swapchain *swapchain;
+ const VkAllocationCallbacks *alloc;
- VkResult result = iface->create_swapchain(surface, device, pCreateInfo,
- pAllocator, &anv_wsi_image_fns,
+ if (pAllocator)
+ alloc = pAllocator;
+ else
+ alloc = &device->alloc;
+ VkResult result = iface->create_swapchain(surface, _device,
+ &device->instance->physicalDevice.wsi_device,
+ device->instance->physicalDevice.local_fd,
+ pCreateInfo,
+ alloc, &anv_wsi_image_fns,
&swapchain);
if (result != VK_SUCCESS)
return result;
- if (pAllocator)
- swapchain->alloc = *pAllocator;
- else
- swapchain->alloc = device->alloc;
+ swapchain->alloc = *alloc;
for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++)
swapchain->fences[i] = VK_NULL_HANDLE;
- *pSwapchain = anv_swapchain_to_handle(swapchain);
+ *pSwapchain = wsi_swapchain_to_handle(swapchain);
return VK_SUCCESS;
}
void anv_DestroySwapchainKHR(
- VkDevice device,
+ VkDevice _device,
VkSwapchainKHR _swapchain,
const VkAllocationCallbacks* pAllocator)
{
- ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
+ const VkAllocationCallbacks *alloc;
+
+ if (!swapchain)
+ return;
+ if (pAllocator)
+ alloc = pAllocator;
+ else
+ alloc = &device->alloc;
for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) {
if (swapchain->fences[i] != VK_NULL_HANDLE)
- anv_DestroyFence(device, swapchain->fences[i], pAllocator);
+ anv_DestroyFence(_device, swapchain->fences[i], pAllocator);
}
- swapchain->destroy(swapchain, pAllocator);
+ swapchain->destroy(swapchain, alloc);
}
VkResult anv_GetSwapchainImagesKHR(
uint32_t* pSwapchainImageCount,
VkImage* pSwapchainImages)
{
- ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
+ ANV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
return swapchain->get_images(swapchain, pSwapchainImageCount,
pSwapchainImages);
}
VkResult anv_AcquireNextImageKHR(
- VkDevice device,
+ VkDevice _device,
VkSwapchainKHR _swapchain,
uint64_t timeout,
VkSemaphore semaphore,
- VkFence fence,
+ VkFence _fence,
uint32_t* pImageIndex)
{
- ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
+ ANV_FROM_HANDLE(anv_fence, fence, _fence);
+
+ VkResult result = swapchain->acquire_next_image(swapchain, timeout,
+ semaphore, pImageIndex);
+
+ /* Thanks to implicit sync, the image is ready immediately. However, we
+ * should wait for the current GPU state to finish.
+ */
+ if (fence)
+ anv_QueueSubmit(anv_queue_to_handle(&device->queue), 0, NULL, _fence);
- return swapchain->acquire_next_image(swapchain, timeout, semaphore,
- pImageIndex);
+ return result;
}
VkResult anv_QueuePresentKHR(
const VkPresentInfoKHR* pPresentInfo)
{
ANV_FROM_HANDLE(anv_queue, queue, _queue);
- VkResult result;
+ VkResult result = VK_SUCCESS;
+
+ const VkPresentRegionsKHR *regions =
+ vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
- ANV_FROM_HANDLE(anv_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
+ ANV_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
+ VkResult item_result;
+
+ const VkPresentRegionKHR *region = NULL;
+ if (regions && regions->pRegions)
+ region = ®ions->pRegions[i];
assert(anv_device_from_handle(swapchain->device) == queue->device);
if (swapchain->fences[0] == VK_NULL_HANDLE) {
- result = anv_CreateFence(anv_device_to_handle(queue->device),
+ item_result = anv_CreateFence(anv_device_to_handle(queue->device),
&(VkFenceCreateInfo) {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.flags = 0,
}, &swapchain->alloc, &swapchain->fences[0]);
- if (result != VK_SUCCESS)
- return result;
+ if (pPresentInfo->pResults != NULL)
+ pPresentInfo->pResults[i] = item_result;
+ result = result == VK_SUCCESS ? item_result : result;
+ if (item_result != VK_SUCCESS)
+ continue;
} else {
anv_ResetFences(anv_device_to_handle(queue->device),
1, &swapchain->fences[0]);
anv_QueueSubmit(_queue, 0, NULL, swapchain->fences[0]);
- result = swapchain->queue_present(swapchain,
- pPresentInfo->pImageIndices[i]);
+ item_result = swapchain->queue_present(swapchain,
+ pPresentInfo->pImageIndices[i],
+ region);
/* TODO: What if one of them returns OUT_OF_DATE? */
- if (result != VK_SUCCESS)
- return result;
+ if (pPresentInfo->pResults != NULL)
+ pPresentInfo->pResults[i] = item_result;
+ result = result == VK_SUCCESS ? item_result : result;
+ if (item_result != VK_SUCCESS)
+ continue;
VkFence last = swapchain->fences[2];
swapchain->fences[2] = swapchain->fences[1];