vulkan: Add KHR_display extension using DRM [v10]

This adds support for the KHR_display extension support to the vulkan
WSI layer. Driver support will be added separately.

v2:
	* fix double ;; in wsi_common_display.c

	* Move mode list from wsi_display to wsi_display_connector

	* Fix scope for wsi_display_mode andwsi_display_connector
          allocs

	* Switch all allocations to vk_zalloc instead of vk_alloc.

	* Fix DRM failure in
          wsi_display_get_physical_device_display_properties

	  When DRM fails, or when we don't have a master fd
	  (presumably due to application errors), just return 0
	  properties from this function, which is at least a valid
	  response.

	* Use vk_outarray for all property queries

	  This is a bit less error-prone than open-coding the same
	  stuff.

	* Remove VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR from surface caps

	  Until we have multi-plane support, we shouldn't pretend to
	  have any multi-plane semantics, even if undefined.

	Suggested-by: Jason Ekstrand <jason@jlekstrand.net>

	* Simplify addition of VK_USE_PLATFORM_DISPLAY_KHR to
          vulkan_wsi_args

	Suggested-by: Eric Engestrom <eric.engestrom@imgtec.com>

v3:
	Add separate 'display_fd' and 'render_fd' arguments to
	wsi_device_init API. This allows drivers to use different FDs
	for the different aspects of the device.

	Use largest mode as display size when no preferred mode.

	If the display doesn't provide a preferred mode, we'll assume
	that the largest supported mode is the "physical size" of the
	device and report that.

v4:
	Make wsi_image_state enumeration values uppercase.
	Follow more common mesa conventions.

	Remove 'render_fd' from wsi_device_init API.  The
	wsi_common_display code doesn't use this fd at all, so stop
	passing it in. This avoids any potential confusion over which
	fd to use when creating display-relative object handles.

	Remove call to wsi_create_prime_image which would never have
	been reached as the necessary condition (use_prime_blit) is
	never set.

	whitespace cleanups in wsi_common_display.c

	Suggested-by: Jason Ekstrand <jason@jlekstrand.net>

	Add depth/bpp info to available surface formats.  Instead of
	hard-coding depth 24 bpp 32 in the drmModeAddFB call, use the
	requested format to find suitable values.

	Destroy kernel buffers and FBs when swapchain is destroyed. We
	were leaking both of these kernel objects across swapchain
	destruction.

	Note that wsi_display_wait_for_event waits for anything to
	happen.  wsi_display_wait_for_event is simply a yield so that
	the caller can then check to see if the desired state change
	has occurred.

	Record swapchain failures in chain for later return. If some
	asynchronous swapchain activity fails, we need to tell the
	application eventually. Record the failure in the swapchain
	and report it at the next acquire_next_image or queue_present
	call.

	Fix error returns from wsi_display_setup_connector.  If a
	malloc failed, then the result should be
	VK_ERROR_OUT_OF_HOST_MEMORY. Otherwise, the associated ioctl
	failed and we're either VT switched away, or our lease has
	been revoked, in which case we should return
	VK_ERROR_OUT_OF_DATE_KHR.

	Make sure both sides of if/else brace use matches

	Note that we assume drmModeSetCrtc is synchronous. Add a
	comment explaining why we can idle any previous displayed
	image as soon as the mode set returns.

	Note that EACCES from drmModePageFlip means VT inactive.  When
	vt switched away drmModePageFlip returns EACCES. Poll once a
	second waiting until we get some other return value back.

	Clean up after alloc failure in
	wsi_display_surface_create_swapchain. Destroy any created
	images, free the swapchain.

	Remove physical_device from wsi_display_init_wsi. We never
	need this value, so remove it from the API and from the
	internal wsi_display structure.

	Use drmModeAddFB2 in wsi_display_image_init.  This takes a drm
	format instead of depth/bpp, which provides more control over
	the format of the data.

v5:
	Set the 'currentStackIndex' member of the
	VkDisplayPlanePropertiesKHR record to zero, instead of
	indexing across all displays. This value is the stack depth of
	the plane within an individual display, and as the current
	code supports only a single plane per display, should be set
	to zero for all elements

	Discovered-by: David Mao <David.Mao@amd.com>

v6:
	Remove 'platform_display' bits from the build and use the
	existing 'platform_drm' instead.

v7:
	Ensure VK_ICD_WSI_PLATFORM_MAX is large enough by
	setting to VK_ICD_WSI_PLATFORM_DISPLAY + 1

v8:
	Simplify wsi_device_init failure from wsi_display_init_wsi
	by using the same pattern as the other wsi layers.

    Adopt Jason Ekstrand's white space and variable declaration
	suggestions. Declare variables at first use, eliminate extra
	whitespace between types and names, add list iterator helpers,
	switch to lower-case list_ macros.

    Respond to Jason's April 8 review:

	* Create a function to convert relative to absolute timeouts
          to catch overflow issues in one place

	* use VK_NULL_HANDLE to clear prop->currentDisplay

	* Get rid of available_present_modes array.

	* return OUT_OF_DATE_KHR when display_queue_next called after
	  display has been released.

	* Make errors from mode setting fatal in display_queue_next

	* Remove duplicate pthread_mutex_init call

	* Add wsi_init_pthread_cond_monotonic helper function to
	  isolate pthread error handling from wsi_display_init_wsi

	Suggested-by: Jason Ekstrand <jason.ekstrand@intel.com>

v9:
	Fix vscan handling by using MAX2(vscan, 1) everywhere. Vscan
	can be zero anywhere, which is treated the same as 1.

	Suggested-by: Jason Ekstrand <jason.ekstrand@intel.com>

v10:
	Respond to Vulkan CTS failures.

	1. Initialize planeReorderPossible in display_properties code

	2. Only report connected displays in
	   get_display_plane_supported_displays

	3. Return VK_ERROR_OUT_OF_HOST_MEMORY when pthread cond
	   initialization fails.

	Signed-off-by: Jason Ekstrand <jason.ekstrand@intel.com>

	4. Add vkCreateDisplayModeKHR. This doesn't actually create
	   new modes, it only looks to see if the requested parameters
	   matches an existing mode and returns that.

	Suggested-by: Jason Ekstrand <jason.ekstrand@intel.com>

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Keith Packard 2018-02-07 10:31:44 -08:00
parent ef79457004
commit da997ebec9
14 changed files with 1622 additions and 5 deletions

View File

@ -225,6 +225,7 @@ radv_physical_device_init(struct radv_physical_device *device,
VkResult result;
drmVersionPtr version;
int fd;
int master_fd = -1;
fd = open(path, O_RDWR | O_CLOEXEC);
if (fd < 0) {
@ -247,6 +248,8 @@ radv_physical_device_init(struct radv_physical_device *device,
if (strcmp(version->name, "amdgpu")) {
drmFreeVersion(version);
if (master_fd != -1)
close(master_fd);
close(fd);
if (instance->debug_flags & RADV_DEBUG_STARTUP)
@ -271,6 +274,7 @@ radv_physical_device_init(struct radv_physical_device *device,
goto fail;
}
device->master_fd = master_fd;
device->local_fd = fd;
device->ws->query_info(device->ws, &device->rad_info);
@ -349,6 +353,8 @@ radv_physical_device_init(struct radv_physical_device *device,
fail:
close(fd);
if (master_fd != -1)
close(master_fd);
return result;
}
@ -359,6 +365,8 @@ radv_physical_device_finish(struct radv_physical_device *device)
device->ws->destroy(device->ws);
disk_cache_destroy(device->disk_cache);
close(device->local_fd);
if (device->master_fd != -1)
close(device->master_fd);
}
static void *

View File

@ -285,6 +285,7 @@ struct radv_physical_device {
uint8_t cache_uuid[VK_UUID_SIZE];
int local_fd;
int master_fd;
struct wsi_device wsi_device;
bool has_rbplus; /* if RB+ register exist */

View File

@ -41,7 +41,8 @@ radv_init_wsi(struct radv_physical_device *physical_device)
return wsi_device_init(&physical_device->wsi_device,
radv_physical_device_to_handle(physical_device),
radv_wsi_proc_addr,
&physical_device->instance->alloc);
&physical_device->instance->alloc,
physical_device->master_fd);
}
void

View File

@ -278,6 +278,7 @@ anv_physical_device_init(struct anv_physical_device *device,
{
VkResult result;
int fd;
int master_fd = -1;
brw_process_intel_debug_variable();
@ -449,10 +450,13 @@ anv_physical_device_init(struct anv_physical_device *device,
&device->supported_extensions);
device->local_fd = fd;
device->master_fd = master_fd;
return VK_SUCCESS;
fail:
close(fd);
if (master_fd != -1)
close(master_fd);
return result;
}

View File

@ -876,6 +876,7 @@ struct anv_physical_device {
struct wsi_device wsi_device;
int local_fd;
int master_fd;
};
struct anv_instance {

View File

@ -48,7 +48,8 @@ anv_init_wsi(struct anv_physical_device *physical_device)
result = wsi_device_init(&physical_device->wsi_device,
anv_physical_device_to_handle(physical_device),
anv_wsi_proc_addr,
&physical_device->instance->alloc);
&physical_device->instance->alloc,
physical_device->master_fd);
if (result != VK_SUCCESS)
return result;

View File

@ -54,6 +54,13 @@ AM_CPPFLAGS += \
VULKAN_WSI_SOURCES += $(VULKAN_WSI_X11_FILES)
endif
if HAVE_PLATFORM_DRM
AM_CPPFLAGS += \
-DVK_USE_PLATFORM_DISPLAY_KHR
VULKAN_WSI_SOURCES += $(VULKAN_WSI_DISPLAY_FILES)
endif
CLEANFILES = \
$(VULKAN_UTIL_GENERATED_FILES) \
$(VULKAN_WSI_WAYLAND_GENERATED_FILES)

View File

@ -19,6 +19,10 @@ VULKAN_WSI_X11_FILES := \
wsi/wsi_common_x11.c \
wsi/wsi_common_x11.h
VULKAN_WSI_DISPLAY_FILES := \
wsi/wsi_common_display.c \
wsi/wsi_common_display.h
VULKAN_UTIL_FILES := \
util/vk_alloc.h \
util/vk_debug_report.c \

View File

@ -59,6 +59,14 @@ if with_platform_wayland
]
endif
if with_platform_drm
vulkan_wsi_args += '-DVK_USE_PLATFORM_DISPLAY_KHR'
files_vulkan_wsi += files(
'wsi_common_display.c',
'wsi_common_display.h',
)
endif
libvulkan_wsi = static_library(
'vulkan_wsi',
files_vulkan_wsi,

View File

@ -32,7 +32,8 @@ VkResult
wsi_device_init(struct wsi_device *wsi,
VkPhysicalDevice pdevice,
WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
const VkAllocationCallbacks *alloc)
const VkAllocationCallbacks *alloc,
int display_fd)
{
VkResult result;
@ -91,6 +92,12 @@ wsi_device_init(struct wsi_device *wsi,
goto fail;
#endif
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
result = wsi_display_init_wsi(wsi, alloc, display_fd);
if (result != VK_SUCCESS)
goto fail;
#endif
return VK_SUCCESS;
fail:
@ -102,6 +109,9 @@ void
wsi_device_finish(struct wsi_device *wsi,
const VkAllocationCallbacks *alloc)
{
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
wsi_display_finish_wsi(wsi, alloc);
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
wsi_wl_finish_wsi(wsi, alloc);
#endif

View File

@ -68,7 +68,7 @@ struct wsi_format_modifier_properties_list {
struct wsi_interface;
#define VK_ICD_WSI_PLATFORM_MAX 5
#define VK_ICD_WSI_PLATFORM_MAX (VK_ICD_WSI_PLATFORM_DISPLAY + 1)
struct wsi_device {
VkPhysicalDevice pdevice;
@ -116,7 +116,8 @@ VkResult
wsi_device_init(struct wsi_device *wsi,
VkPhysicalDevice pdevice,
WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
const VkAllocationCallbacks *alloc);
const VkAllocationCallbacks *alloc,
int display_fd);
void
wsi_device_finish(struct wsi_device *wsi,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
/*
* Copyright © 2017 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef WSI_COMMON_DISPLAY_H
#define WSI_COMMON_DISPLAY_H
#include "wsi_common.h"
#include <xf86drm.h>
#include <xf86drmMode.h>
#define typed_memcpy(dest, src, count) ({ \
STATIC_ASSERT(sizeof(*src) == sizeof(*dest)); \
memcpy((dest), (src), (count) * sizeof(*(src))); \
})
VkResult
wsi_display_get_physical_device_display_properties(
VkPhysicalDevice physical_device,
struct wsi_device *wsi_device,
uint32_t *property_count,
VkDisplayPropertiesKHR *properties);
VkResult
wsi_display_get_physical_device_display_plane_properties(
VkPhysicalDevice physical_device,
struct wsi_device *wsi_device,
uint32_t *property_count,
VkDisplayPlanePropertiesKHR *properties);
VkResult
wsi_display_get_display_plane_supported_displays(
VkPhysicalDevice physical_device,
struct wsi_device *wsi_device,
uint32_t plane_index,
uint32_t *display_count,
VkDisplayKHR *displays);
VkResult
wsi_display_get_display_mode_properties(VkPhysicalDevice physical_device,
struct wsi_device *wsi_device,
VkDisplayKHR display,
uint32_t *property_count,
VkDisplayModePropertiesKHR *properties);
VkResult
wsi_display_create_display_mode(VkPhysicalDevice physical_device,
struct wsi_device *wsi_device,
VkDisplayKHR display,
const VkDisplayModeCreateInfoKHR *create_info,
const VkAllocationCallbacks *allocator,
VkDisplayModeKHR *mode);
VkResult
wsi_get_display_plane_capabilities(VkPhysicalDevice physical_device,
struct wsi_device *wsi_device,
VkDisplayModeKHR mode_khr,
uint32_t plane_index,
VkDisplayPlaneCapabilitiesKHR *capabilities);
VkResult
wsi_create_display_surface(VkInstance instance,
const VkAllocationCallbacks *pAllocator,
const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
VkSurfaceKHR *pSurface);
#endif

View File

@ -141,6 +141,15 @@ void wsi_wl_finish_wsi(struct wsi_device *wsi_device,
const VkAllocationCallbacks *alloc);
VkResult
wsi_display_init_wsi(struct wsi_device *wsi_device,
const VkAllocationCallbacks *alloc,
int display_fd);
void
wsi_display_finish_wsi(struct wsi_device *wsi_device,
const VkAllocationCallbacks *alloc);
#define WSI_DEFINE_NONDISP_HANDLE_CASTS(__wsi_type, __VkType) \
\
static inline struct __wsi_type * \