mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 08:58:02 +02:00
wsi/wayland: Implement EXT_swapchain_maintenance1.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no> Reviewed-by: Joshua Ashton <joshua@froggi.es> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20235>
This commit is contained in:
parent
ad71d584cf
commit
07ac177c3f
1 changed files with 116 additions and 15 deletions
|
|
@ -963,18 +963,56 @@ static const VkPresentModeKHR present_modes[] = {
|
|||
VK_PRESENT_MODE_FIFO_KHR,
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
wsi_wl_surface_get_min_image_count(const VkSurfacePresentModeEXT *present_mode)
|
||||
{
|
||||
if (present_mode && (present_mode->presentMode == VK_PRESENT_MODE_FIFO_KHR ||
|
||||
present_mode->presentMode == VK_PRESENT_MODE_FIFO_RELAXED_KHR)) {
|
||||
/* If we receive a FIFO present mode, only 2 images is required for forward progress.
|
||||
* Performance with 2 images will be questionable, but we only allow it for applications
|
||||
* using the new API, so we don't risk breaking any existing apps this way.
|
||||
* Other ICDs expose 2 images here already. */
|
||||
return 2;
|
||||
} else {
|
||||
/* For true mailbox mode, we need at least 4 images:
|
||||
* 1) One to scan out from
|
||||
* 2) One to have queued for scan-out
|
||||
* 3) One to be currently held by the Wayland compositor
|
||||
* 4) One to render to
|
||||
*/
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
wsi_wl_surface_get_min_image_count_for_mode_group(const VkSwapchainPresentModesCreateInfoEXT *modes)
|
||||
{
|
||||
/* If we don't provide the PresentModeCreateInfo struct, we must be backwards compatible,
|
||||
* and assume that minImageCount is the default one, i.e. 4, which supports both FIFO and MAILBOX. */
|
||||
if (!modes) {
|
||||
return wsi_wl_surface_get_min_image_count(NULL);
|
||||
}
|
||||
|
||||
uint32_t max_required = 0;
|
||||
for (uint32_t i = 0; i < modes->presentModeCount; i++) {
|
||||
const VkSurfacePresentModeEXT mode = {
|
||||
VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT,
|
||||
NULL,
|
||||
modes->pPresentModes[i]
|
||||
};
|
||||
max_required = MAX2(max_required, wsi_wl_surface_get_min_image_count(&mode));
|
||||
}
|
||||
|
||||
return max_required;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
wsi_wl_surface_get_capabilities(VkIcdSurfaceBase *surface,
|
||||
struct wsi_device *wsi_device,
|
||||
const VkSurfacePresentModeEXT *present_mode,
|
||||
VkSurfaceCapabilitiesKHR* caps)
|
||||
{
|
||||
/* For true mailbox mode, we need at least 4 images:
|
||||
* 1) One to scan out from
|
||||
* 2) One to have queued for scan-out
|
||||
* 3) One to be currently held by the Wayland compositor
|
||||
* 4) One to render to
|
||||
*/
|
||||
caps->minImageCount = 4;
|
||||
caps->minImageCount = wsi_wl_surface_get_min_image_count(present_mode);
|
||||
/* There is no real maximum */
|
||||
caps->maxImageCount = 0;
|
||||
|
||||
|
|
@ -1012,8 +1050,10 @@ wsi_wl_surface_get_capabilities2(VkIcdSurfaceBase *surface,
|
|||
{
|
||||
assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR);
|
||||
|
||||
const VkSurfacePresentModeEXT *present_mode = vk_find_struct_const(info_next, SURFACE_PRESENT_MODE_EXT);
|
||||
|
||||
VkResult result =
|
||||
wsi_wl_surface_get_capabilities(surface, wsi_device,
|
||||
wsi_wl_surface_get_capabilities(surface, wsi_device, present_mode,
|
||||
&caps->surfaceCapabilities);
|
||||
|
||||
vk_foreach_struct(ext, caps->pNext) {
|
||||
|
|
@ -1024,6 +1064,40 @@ wsi_wl_surface_get_capabilities2(VkIcdSurfaceBase *surface,
|
|||
break;
|
||||
}
|
||||
|
||||
case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT: {
|
||||
/* Unsupported. */
|
||||
VkSurfacePresentScalingCapabilitiesEXT *scaling = (void *)ext;
|
||||
scaling->supportedPresentScaling = 0;
|
||||
scaling->supportedPresentGravityX = 0;
|
||||
scaling->supportedPresentGravityY = 0;
|
||||
scaling->minScaledImageExtent = caps->surfaceCapabilities.minImageExtent;
|
||||
scaling->maxScaledImageExtent = caps->surfaceCapabilities.maxImageExtent;
|
||||
break;
|
||||
}
|
||||
|
||||
case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT: {
|
||||
/* Can easily toggle between FIFO and MAILBOX on Wayland. */
|
||||
assert(present_mode);
|
||||
VkSurfacePresentModeCompatibilityEXT *compat = (void *)ext;
|
||||
if (compat->pPresentModes) {
|
||||
VK_OUTARRAY_MAKE_TYPED(VkPresentModeKHR, modes, compat->pPresentModes, &compat->presentModeCount);
|
||||
/* Must always return queried present mode even when truncating. */
|
||||
vk_outarray_append_typed(VkPresentModeKHR, &modes, mode) {
|
||||
*mode = present_mode->presentMode;
|
||||
}
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(present_modes); i++) {
|
||||
if (present_modes[i] != present_mode->presentMode) {
|
||||
vk_outarray_append_typed(VkPresentModeKHR, &modes, mode) {
|
||||
*mode = present_modes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
compat->presentModeCount = ARRAY_SIZE(present_modes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Ignored */
|
||||
break;
|
||||
|
|
@ -1460,6 +1534,27 @@ wsi_wl_swapchain_get_wsi_image(struct wsi_swapchain *wsi_chain,
|
|||
return &chain->images[image_index].base;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
wsi_wl_swapchain_release_images(struct wsi_swapchain *wsi_chain,
|
||||
uint32_t count, const uint32_t *indices)
|
||||
{
|
||||
struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
uint32_t index = indices[i];
|
||||
assert(chain->images[index].busy);
|
||||
chain->images[index].busy = false;
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
wsi_wl_swapchain_set_present_mode(struct wsi_swapchain *wsi_chain,
|
||||
VkPresentModeKHR mode)
|
||||
{
|
||||
struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
|
||||
chain->base.present_mode = mode;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
wsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
|
||||
const VkAcquireNextImageInfoKHR *info,
|
||||
|
|
@ -1565,13 +1660,14 @@ wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
|
|||
memcpy(image->shm_ptr, image->base.cpu_map,
|
||||
image->base.row_pitches[0] * chain->extent.height);
|
||||
}
|
||||
if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
|
||||
while (!chain->fifo_ready) {
|
||||
int ret = wl_display_dispatch_queue(wsi_wl_surface->display->wl_display,
|
||||
wsi_wl_surface->display->queue);
|
||||
if (ret < 0)
|
||||
return VK_ERROR_OUT_OF_DATE_KHR;
|
||||
}
|
||||
|
||||
/* For EXT_swapchain_maintenance1. We might have transitioned from FIFO to MAILBOX.
|
||||
* In this case we need to let the FIFO request complete, before presenting MAILBOX. */
|
||||
while (!chain->fifo_ready) {
|
||||
int ret = wl_display_dispatch_queue(wsi_wl_surface->display->wl_display,
|
||||
wsi_wl_surface->display->queue);
|
||||
if (ret < 0)
|
||||
return VK_ERROR_OUT_OF_DATE_KHR;
|
||||
}
|
||||
|
||||
assert(image_index < chain->base.image_count);
|
||||
|
|
@ -1594,6 +1690,9 @@ wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
|
|||
chain->frame = wl_surface_frame(wsi_wl_surface->surface);
|
||||
wl_callback_add_listener(chain->frame, &frame_listener, chain);
|
||||
chain->fifo_ready = false;
|
||||
} else {
|
||||
/* If we present MAILBOX, any subsequent presentation in FIFO can replace this image. */
|
||||
chain->fifo_ready = true;
|
||||
}
|
||||
|
||||
chain->images[image_index].busy = true;
|
||||
|
|
@ -1871,6 +1970,8 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
|
|||
chain->base.get_wsi_image = wsi_wl_swapchain_get_wsi_image;
|
||||
chain->base.acquire_next_image = wsi_wl_swapchain_acquire_next_image;
|
||||
chain->base.queue_present = wsi_wl_swapchain_queue_present;
|
||||
chain->base.release_images = wsi_wl_swapchain_release_images;
|
||||
chain->base.set_present_mode = wsi_wl_swapchain_set_present_mode;
|
||||
chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, pCreateInfo);
|
||||
chain->base.image_count = num_images;
|
||||
chain->extent = pCreateInfo->imageExtent;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue