*/
#include <wayland-client.h>
-#include <wayland-drm-client-protocol.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
+#include "util/vk_util.h"
#include "wsi_common_wayland.h"
+#include "wayland-drm-client-protocol.h"
#include <util/hash_table.h>
#include <util/u_vector.h>
struct wl_registry *registry = wl_display_get_registry(wl_display);
if (!registry)
- return NULL;
+ goto fail;
wl_registry_add_listener(registry, ®istry_listener, display);
wl_display_roundtrip(wl_display);
if (!display->drm)
- goto fail;
+ goto fail_registry;
/* Round-rip to get wl_drm formats and capabilities */
wl_display_roundtrip(wl_display);
/* We need prime support */
if (!(display->capabilities & WL_DRM_CAPABILITY_PRIME))
- goto fail;
+ goto fail_registry;
/* We don't need this anymore */
wl_registry_destroy(registry);
return display;
-fail:
+fail_registry:
if (registry)
wl_registry_destroy(registry);
+fail:
wsi_wl_display_destroy(wsi, display);
return NULL;
}
struct wsi_device *wsi_device,
const VkAllocationCallbacks *alloc,
uint32_t queueFamilyIndex,
+ int local_fd,
+ bool can_handle_different_gpu,
VkBool32* pSupported)
{
*pSupported = true;
caps->currentExtent = (VkExtent2D) { -1, -1 };
caps->minImageExtent = (VkExtent2D) { 1, 1 };
- caps->maxImageExtent = (VkExtent2D) { INT16_MAX, INT16_MAX };
+ /* This is the maximum supported size on Intel */
+ caps->maxImageExtent = (VkExtent2D) { 1 << 14, 1 << 14 };
caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
caps->maxImageArrayLayers = 1;
return VK_SUCCESS;
}
+static VkResult
+wsi_wl_surface_get_capabilities2(VkIcdSurfaceBase *surface,
+ const void *info_next,
+ VkSurfaceCapabilities2KHR* caps)
+{
+ assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR);
+
+ return wsi_wl_surface_get_capabilities(surface, &caps->surfaceCapabilities);
+}
+
static VkResult
wsi_wl_surface_get_formats(VkIcdSurfaceBase *icd_surface,
struct wsi_device *wsi_device,
if (!display)
return VK_ERROR_OUT_OF_HOST_MEMORY;
- uint32_t count = u_vector_length(&display->formats);
+ VK_OUTARRAY_MAKE(out, pSurfaceFormats, pSurfaceFormatCount);
- if (pSurfaceFormats == NULL) {
- *pSurfaceFormatCount = count;
- return VK_SUCCESS;
+ VkFormat *disp_fmt;
+ u_vector_foreach(disp_fmt, &display->formats) {
+ vk_outarray_append(&out, out_fmt) {
+ out_fmt->format = *disp_fmt;
+ out_fmt->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ }
}
- assert(*pSurfaceFormatCount >= count);
- *pSurfaceFormatCount = count;
+ return vk_outarray_status(&out);
+}
- VkFormat *f;
- u_vector_foreach(f, &display->formats) {
- *(pSurfaceFormats++) = (VkSurfaceFormatKHR) {
- .format = *f,
- /* TODO: We should get this from the compositor somehow */
- .colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR,
- };
+static VkResult
+wsi_wl_surface_get_formats2(VkIcdSurfaceBase *icd_surface,
+ struct wsi_device *wsi_device,
+ const void *info_next,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats)
+{
+ VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface;
+ struct wsi_wl_display *display =
+ wsi_wl_get_display(wsi_device, surface->display);
+ if (!display)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ VK_OUTARRAY_MAKE(out, pSurfaceFormats, pSurfaceFormatCount);
+
+ VkFormat *disp_fmt;
+ u_vector_foreach(disp_fmt, &display->formats) {
+ vk_outarray_append(&out, out_fmt) {
+ out_fmt->surfaceFormat.format = *disp_fmt;
+ out_fmt->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ }
}
- return VK_SUCCESS;
+ return vk_outarray_status(&out);
}
static VkResult
return VK_SUCCESS;
}
- assert(*pPresentModeCount >= ARRAY_SIZE(present_modes));
+ *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes));
typed_memcpy(pPresentModes, present_modes, *pPresentModeCount);
- *pPresentModeCount = ARRAY_SIZE(present_modes);
- return VK_SUCCESS;
+ if (*pPresentModeCount < ARRAY_SIZE(present_modes))
+ return VK_INCOMPLETE;
+ else
+ return VK_SUCCESS;
}
VkResult wsi_create_wl_surface(const VkAllocationCallbacks *pAllocator,
struct wsi_wl_display * display;
struct wl_event_queue * queue;
struct wl_surface * surface;
+ uint32_t surface_version;
VkExtent2D extent;
VkFormat vk_format;
VkPresentModeKHR present_mode;
bool fifo_ready;
- uint32_t image_count;
struct wsi_wl_image images[0];
};
VkResult result;
if (pSwapchainImages == NULL) {
- *pCount = chain->image_count;
+ *pCount = chain->base.image_count;
return VK_SUCCESS;
}
result = VK_SUCCESS;
- ret_count = chain->image_count;
- if (chain->image_count > *pCount) {
+ ret_count = chain->base.image_count;
+ if (chain->base.image_count > *pCount) {
ret_count = *pCount;
result = VK_INCOMPLETE;
}
return VK_ERROR_OUT_OF_DATE_KHR;
while (1) {
- for (uint32_t i = 0; i < chain->image_count; i++) {
+ for (uint32_t i = 0; i < chain->base.image_count; i++) {
if (!chain->images[i].busy) {
/* We found a non-busy image */
*image_index = i;
static VkResult
wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
- uint32_t image_index)
+ uint32_t image_index,
+ const VkPresentRegionKHR *damage)
{
struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
}
}
- assert(image_index < chain->image_count);
+ assert(image_index < chain->base.image_count);
wl_surface_attach(chain->surface, chain->images[image_index].buffer, 0, 0);
- wl_surface_damage(chain->surface, 0, 0, INT32_MAX, INT32_MAX);
+
+ if (chain->surface_version >= 4 && damage &&
+ damage->pRectangles && damage->rectangleCount > 0) {
+ for (unsigned i = 0; i < damage->rectangleCount; i++) {
+ const VkRectLayerKHR *rect = &damage->pRectangles[i];
+ assert(rect->layer == 0);
+ wl_surface_damage_buffer(chain->surface,
+ rect->offset.x, rect->offset.y,
+ rect->extent.width, rect->extent.height);
+ }
+ } else {
+ wl_surface_damage(chain->surface, 0, 0, INT32_MAX, INT32_MAX);
+ }
if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
struct wl_callback *frame = wl_surface_frame(chain->surface);
result = chain->base.image_fns->create_wsi_image(vk_device,
pCreateInfo,
pAllocator,
+ false,
+ false,
&image->image,
&image->memory,
&size,
offset,
row_pitch,
0, 0, 0, 0 /* unused */);
- wl_display_roundtrip(chain->display->display);
close(fd);
if (!image->buffer)
{
struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
- for (uint32_t i = 0; i < chain->image_count; i++) {
+ for (uint32_t i = 0; i < chain->base.image_count; i++) {
if (chain->images[i].buffer)
chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator,
chain->images[i].image,
wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
VkDevice device,
struct wsi_device *wsi_device,
+ int local_fd,
const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
const struct wsi_image_fns *image_fns,
chain->base.queue_present = wsi_wl_swapchain_queue_present;
chain->base.image_fns = image_fns;
chain->base.present_mode = pCreateInfo->presentMode;
+ chain->base.image_count = num_images;
+ chain->base.needs_linear_copy = false;
chain->surface = surface->surface;
+ chain->surface_version = wl_proxy_get_version((void *)surface->surface);
chain->extent = pCreateInfo->imageExtent;
chain->vk_format = pCreateInfo->imageFormat;
chain->drm_format = wl_drm_format_for_vk_format(chain->vk_format, alpha);
chain->fifo_ready = true;
- chain->image_count = num_images;
-
/* Mark a bunch of stuff as NULL. This way we can just call
* destroy_swapchain for cleanup.
*/
- for (uint32_t i = 0; i < chain->image_count; i++)
+ for (uint32_t i = 0; i < chain->base.image_count; i++)
chain->images[i].buffer = NULL;
chain->queue = NULL;
goto fail;
}
- for (uint32_t i = 0; i < chain->image_count; i++) {
+ for (uint32_t i = 0; i < chain->base.image_count; i++) {
result = wsi_wl_image_init(chain, &chain->images[i],
pCreateInfo, pAllocator);
if (result != VK_SUCCESS)
wsi->base.get_support = wsi_wl_surface_get_support;
wsi->base.get_capabilities = wsi_wl_surface_get_capabilities;
+ wsi->base.get_capabilities2 = wsi_wl_surface_get_capabilities2;
wsi->base.get_formats = wsi_wl_surface_get_formats;
+ wsi->base.get_formats2 = wsi_wl_surface_get_formats2;
wsi->base.get_present_modes = wsi_wl_surface_get_present_modes;
wsi->base.create_swapchain = wsi_wl_surface_create_swapchain;