X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fvulkan%2Fwsi%2Fwsi_common_display.c;h=0f9a1ffe8d3af271f0ee5848e1c6090b75efc6b1;hp=ac932d4368a0293fe97eeb8096fc3e5d252aa24c;hb=51de5d5ac65ebeaaebe716291be19fd36692f5cb;hpb=dc1d10b396179766227dfc6389b3b5541365b1dc diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c index ac932d4368a..0f9a1ffe8d3 100644 --- a/src/vulkan/wsi/wsi_common_display.c +++ b/src/vulkan/wsi/wsi_common_display.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include "drm-uapi/drm_fourcc.h" #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT #include #include @@ -96,7 +96,7 @@ struct wsi_display { pthread_cond_t wait_cond; pthread_t wait_thread; - struct list_head connectors; + struct list_head connectors; /* list of all discovered connectors */ }; #define wsi_for_each_display_mode(_mode, _conn) \ @@ -171,17 +171,9 @@ wsi_display_mode_refresh(struct wsi_display_mode *wsi) (double) MAX2(wsi->vscan, 1)); } -static uint64_t wsi_get_current_monotonic(void) -{ - struct timespec tv; - - clock_gettime(CLOCK_MONOTONIC, &tv); - return tv.tv_nsec + tv.tv_sec*1000000000ull; -} - static uint64_t wsi_rel_to_abs_time(uint64_t rel_time) { - uint64_t current_time = wsi_get_current_monotonic(); + uint64_t current_time = wsi_common_get_current_time(); /* check for overflow */ if (rel_time > UINT64_MAX - current_time) @@ -619,7 +611,7 @@ wsi_display_fill_in_display_mode_properties( struct wsi_display_mode *display_mode, VkDisplayModeProperties2KHR *properties) { - assert(properties->sType = VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR); + assert(properties->sType == VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR); VkDisplayModePropertiesKHR *prop = &properties->displayModeProperties; prop->displayMode = wsi_display_mode_to_handle(display_mode); @@ -763,13 +755,30 @@ wsi_get_display_plane_capabilities2( const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo, VkDisplayPlaneCapabilities2KHR *capabilities) { - assert(capabilities->sType = + assert(capabilities->sType == VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR); - return wsi_get_display_plane_capabilities(physical_device, wsi_device, - pDisplayPlaneInfo->mode, - pDisplayPlaneInfo->planeIndex, - &capabilities->capabilities); + VkResult result = + wsi_get_display_plane_capabilities(physical_device, wsi_device, + pDisplayPlaneInfo->mode, + pDisplayPlaneInfo->planeIndex, + &capabilities->capabilities); + + vk_foreach_struct(ext, capabilities->pNext) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: { + VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext; + protected->supportsProtected = VK_FALSE; + break; + } + + default: + /* Ignored */ + break; + } + } + + return result; } VkResult @@ -802,9 +811,7 @@ wsi_create_display_surface(VkInstance instance, static VkResult wsi_display_surface_get_support(VkIcdSurfaceBase *surface, struct wsi_device *wsi_device, - const VkAllocationCallbacks *allocator, uint32_t queueFamilyIndex, - int local_fd, VkBool32* pSupported) { *pSupported = VK_TRUE; @@ -813,6 +820,7 @@ wsi_display_surface_get_support(VkIcdSurfaceBase *surface, static VkResult wsi_display_surface_get_capabilities(VkIcdSurfaceBase *surface_base, + struct wsi_device *wsi_device, VkSurfaceCapabilitiesKHR* caps) { VkIcdSurfaceDisplay *surface = (VkIcdSurfaceDisplay *) surface_base; @@ -821,8 +829,11 @@ wsi_display_surface_get_capabilities(VkIcdSurfaceBase *surface_base, caps->currentExtent.width = mode->hdisplay; caps->currentExtent.height = mode->vdisplay; - /* XXX Figure out extents based on driver capabilities */ - caps->maxImageExtent = caps->minImageExtent = caps->currentExtent; + caps->minImageExtent = (VkExtent2D) { 1, 1 }; + caps->maxImageExtent = (VkExtent2D) { + wsi_device->maxImageDimension2D, + wsi_device->maxImageDimension2D, + }; caps->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; @@ -836,6 +847,7 @@ wsi_display_surface_get_capabilities(VkIcdSurfaceBase *surface_base, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; return VK_SUCCESS; @@ -852,13 +864,14 @@ wsi_display_surface_get_surface_counters( static VkResult wsi_display_surface_get_capabilities2(VkIcdSurfaceBase *icd_surface, + struct wsi_device *wsi_device, const void *info_next, VkSurfaceCapabilities2KHR *caps) { assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR); VkResult result; - result = wsi_display_surface_get_capabilities(icd_surface, + result = wsi_display_surface_get_capabilities(icd_surface, wsi_device, &caps->surfaceCapabilities); if (result != VK_SUCCESS) return result; @@ -883,6 +896,23 @@ static const struct { { .format = VK_FORMAT_B8G8R8A8_UNORM, .drm_format = DRM_FORMAT_XRGB8888 }, }; +static void +get_sorted_vk_formats(struct wsi_device *wsi_device, VkFormat *sorted_formats) +{ + for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) + sorted_formats[i] = available_surface_formats[i].format; + + if (wsi_device->force_bgra8_unorm_first) { + for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) { + if (sorted_formats[i] == VK_FORMAT_B8G8R8A8_UNORM) { + sorted_formats[i] = sorted_formats[0]; + sorted_formats[0] = VK_FORMAT_B8G8R8A8_UNORM; + break; + } + } + } +} + static VkResult wsi_display_surface_get_formats(VkIcdSurfaceBase *icd_surface, struct wsi_device *wsi_device, @@ -891,9 +921,12 @@ wsi_display_surface_get_formats(VkIcdSurfaceBase *icd_surface, { VK_OUTARRAY_MAKE(out, surface_formats, surface_format_count); - for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) { + VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)]; + get_sorted_vk_formats(wsi_device, sorted_formats); + + for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { vk_outarray_append(&out, f) { - f->format = available_surface_formats[i].format; + f->format = sorted_formats[i]; f->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; } } @@ -910,10 +943,13 @@ wsi_display_surface_get_formats2(VkIcdSurfaceBase *surface, { VK_OUTARRAY_MAKE(out, surface_formats, surface_format_count); - for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) { + VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)]; + get_sorted_vk_formats(wsi_device, sorted_formats); + + for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { vk_outarray_append(&out, f) { assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR); - f->surfaceFormat.format = available_surface_formats[i].format; + f->surfaceFormat.format = sorted_formats[i]; f->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; } } @@ -935,12 +971,34 @@ wsi_display_surface_get_present_modes(VkIcdSurfaceBase *surface, return vk_outarray_status(&conn); } +static VkResult +wsi_display_surface_get_present_rectangles(VkIcdSurfaceBase *surface_base, + struct wsi_device *wsi_device, + uint32_t* pRectCount, + VkRect2D* pRects) +{ + VkIcdSurfaceDisplay *surface = (VkIcdSurfaceDisplay *) surface_base; + wsi_display_mode *mode = wsi_display_mode_from_handle(surface->displayMode); + VK_OUTARRAY_MAKE(out, pRects, pRectCount); + + if (wsi_device_matches_drm_fd(wsi_device, mode->connector->wsi->fd)) { + vk_outarray_append(&out, rect) { + *rect = (VkRect2D) { + .offset = { 0, 0 }, + .extent = { mode->hdisplay, mode->vdisplay }, + }; + } + } + + return vk_outarray_status(&out); +} + static void wsi_display_destroy_buffer(struct wsi_display *wsi, uint32_t buffer) { - (void) drmIoctl(wsi->fd, DRM_IOCTL_MODE_DESTROY_DUMB, - &((struct drm_mode_destroy_dumb) { .handle = buffer })); + (void) drmIoctl(wsi->fd, DRM_IOCTL_GEM_CLOSE, + &((struct drm_gem_close) { .handle = buffer })); } static VkResult @@ -1042,6 +1100,8 @@ wsi_display_swapchain_destroy(struct wsi_swapchain *drv_chain, for (uint32_t i = 0; i < chain->base.image_count; i++) wsi_display_image_finish(drv_chain, allocator, &chain->images[i]); + + wsi_swapchain_finish(&chain->base); vk_free(allocator, chain); return VK_SUCCESS; } @@ -1197,8 +1257,7 @@ wsi_display_wait_for_event(struct wsi_display *wsi, static VkResult wsi_display_acquire_next_image(struct wsi_swapchain *drv_chain, - uint64_t timeout, - VkSemaphore semaphore, + const VkAcquireNextImageInfoKHR *info, uint32_t *image_index) { struct wsi_display_swapchain *chain = @@ -1211,6 +1270,7 @@ wsi_display_acquire_next_image(struct wsi_swapchain *drv_chain, if (chain->status != VK_SUCCESS) return chain->status; + uint64_t timeout = info->timeout; if (timeout != 0 && timeout != UINT64_MAX) timeout = wsi_rel_to_abs_time(timeout); @@ -1297,7 +1357,7 @@ wsi_display_crtc_solo(struct wsi_display *wsi, * which is currently idle. */ static uint32_t -wsi_display_select_crtc(struct wsi_display_connector *connector, +wsi_display_select_crtc(const struct wsi_display_connector *connector, drmModeResPtr mode_res, drmModeConnectorPtr drm_connector) { @@ -1408,8 +1468,8 @@ wsi_display_fence_wait(struct wsi_fence *fence_wsi, uint64_t timeout) wsi_display_debug("%9lu wait fence %lu %ld\n", pthread_self(), fence->sequence, - (int64_t) (timeout - wsi_get_current_monotonic())); - wsi_display_debug_code(uint64_t start_ns = wsi_get_current_monotonic()); + (int64_t) (timeout - wsi_common_get_current_time())); + wsi_display_debug_code(uint64_t start_ns = wsi_common_get_current_time()); pthread_mutex_lock(&wsi->wait_mutex); VkResult result; @@ -1441,7 +1501,7 @@ wsi_display_fence_wait(struct wsi_fence *fence_wsi, uint64_t timeout) pthread_mutex_unlock(&wsi->wait_mutex); wsi_display_debug("%9lu fence wait %f ms\n", pthread_self(), - ((int64_t) (wsi_get_current_monotonic() - start_ns)) / + ((int64_t) (wsi_common_get_current_time() - start_ns)) / 1.0e6); return result; } @@ -1517,7 +1577,7 @@ wsi_register_vblank_event(struct wsi_display_fence *fence, flags, frame_requested, frame_queued, - (uint64_t) fence); + (uintptr_t) fence); if (!ret) return VK_SUCCESS; @@ -1627,6 +1687,15 @@ _wsi_display_queue_next(struct wsi_swapchain *drv_chain) &connector->id, 1, &connector->current_drm_mode); if (ret == 0) { + /* Disable the HW cursor as the app doesn't have a mechanism + * to control it. + * Refer to question 12 of the VK_KHR_display spec. + */ + ret = drmModeSetCursor(wsi->fd, connector->crtc_id, 0, 0, 0 ); + if (ret != 0) { + wsi_display_debug("failed to hide cursor err %d %s\n", ret, strerror(-ret)); + } + /* Assume that the mode set is synchronous and that any * previous image is now idle. */ @@ -1691,7 +1760,6 @@ wsi_display_surface_create_swapchain( VkIcdSurfaceBase *icd_surface, VkDevice device, struct wsi_device *wsi_device, - int local_fd, const VkSwapchainCreateInfoKHR *create_info, const VkAllocationCallbacks *allocator, struct wsi_swapchain **swapchain_out) @@ -1712,12 +1780,16 @@ wsi_display_surface_create_swapchain( VkResult result = wsi_swapchain_init(wsi_device, &chain->base, device, create_info, allocator); + if (result != VK_SUCCESS) { + vk_free(allocator, chain); + return result; + } chain->base.destroy = wsi_display_swapchain_destroy; chain->base.get_wsi_image = wsi_display_get_wsi_image; chain->base.acquire_next_image = wsi_display_acquire_next_image; chain->base.queue_present = wsi_display_queue_present; - chain->base.present_mode = create_info->presentMode; + chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, create_info); chain->base.image_count = num_images; chain->wsi = wsi; @@ -1772,6 +1844,30 @@ fail_attr_init: return ret; } + +/* + * Local version fo the libdrm helper. Added to avoid depending on bleeding + * edge version of the library. + */ +static int +local_drmIsMaster(int fd) +{ + /* Detect master by attempting something that requires master. + * + * Authenticating magic tokens requires master and 0 is an + * internal kernel detail which we could use. Attempting this on + * a master fd would fail therefore fail with EINVAL because 0 + * is invalid. + * + * A non-master fd will fail with EACCES, as the kernel checks + * for master before attempting to do anything else. + * + * Since we don't want to leak implementation details, use + * EACCES. + */ + return drmAuthMagic(fd, 0) != -EACCES; +} + VkResult wsi_display_init_wsi(struct wsi_device *wsi_device, const VkAllocationCallbacks *alloc, @@ -1787,6 +1883,9 @@ wsi_display_init_wsi(struct wsi_device *wsi_device, } wsi->fd = display_fd; + if (wsi->fd != -1 && !local_drmIsMaster(wsi->fd)) + wsi->fd = -1; + wsi->alloc = alloc; list_inithead(&wsi->connectors); @@ -1807,6 +1906,7 @@ wsi_display_init_wsi(struct wsi_device *wsi_device, wsi->base.get_formats = wsi_display_surface_get_formats; wsi->base.get_formats2 = wsi_display_surface_get_formats2; wsi->base.get_present_modes = wsi_display_surface_get_present_modes; + wsi->base.get_present_rectangles = wsi_display_surface_get_present_rectangles; wsi->base.create_swapchain = wsi_display_surface_create_swapchain; wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY] = &wsi->base; @@ -2304,6 +2404,7 @@ wsi_acquire_xlib_display(VkPhysicalDevice physical_device, if (!crtc) return VK_ERROR_INITIALIZATION_FAILED; +#ifdef HAVE_DRI3_MODIFIERS xcb_randr_lease_t lease = xcb_generate_id(connection); xcb_randr_create_lease_cookie_t cl_c = xcb_randr_create_lease(connection, root, lease, 1, 1, @@ -2324,6 +2425,7 @@ wsi_acquire_xlib_display(VkPhysicalDevice physical_device, return VK_ERROR_INITIALIZATION_FAILED; wsi->fd = fd; +#endif return VK_SUCCESS; } @@ -2342,7 +2444,7 @@ wsi_get_randr_output_display(VkPhysicalDevice physical_device, if (connector) *display = wsi_display_connector_to_handle(connector); else - *display = NULL; + *display = VK_NULL_HANDLE; return VK_SUCCESS; }