From 600c3059ed5d88dce66da65363e6f5bffce5db9b Mon Sep 17 00:00:00 2001 From: Damien Leone Date: Tue, 31 Jan 2017 10:26:07 -0700 Subject: cube: Add direct to display support Although this extension is platform agnostic, this commit only enables it on Linux because this is the only platform I am able to test. Direct to display is enabled by passing '-DDEMOS_WSI_SELECTION=DISPLAY' to cmake. Change-Id: I5f23019d4b0c87104e1f834d3a6901850bfda7a3 --- CMakeLists.txt | 2 +- demos/CMakeLists.txt | 2 + demos/cube.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++ demos/cube.cpp | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 318 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c01f73a..d3037f82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") option(BUILD_WSI_XLIB_SUPPORT "Build Xlib WSI support" ON) option(BUILD_WSI_WAYLAND_SUPPORT "Build Wayland WSI support" ON) option(BUILD_WSI_MIR_SUPPORT "Build Mir WSI support" ON) - set(DEMOS_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for demos") + set(DEMOS_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for demos (XCB, XLIB, WAYLAND, MIR, DISPLAY)") if (BUILD_WSI_XCB_SUPPORT) find_package(XCB REQUIRED) diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt index 9bf07e53..917ea884 100644 --- a/demos/CMakeLists.txt +++ b/demos/CMakeLists.txt @@ -36,6 +36,8 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_definitions(-DVK_USE_PLATFORM_MIR_KHR) include_directories(${MIR_INCLUDE_DIR}) # TODO - Add Mir support + elseif(DEMOS_WSI_SELECTION STREQUAL "DISPLAY") + add_definitions(-DVK_USE_PLATFORM_DISPLAY_KHR) else() message( FATAL_ERROR "Unrecognized value for DEMOS_WSI_SELECTION: ${DEMOS_WSI_SELECTION}" ) endif() diff --git a/demos/cube.c b/demos/cube.c index a55c603f..2efbfb08 100644 --- a/demos/cube.c +++ b/demos/cube.c @@ -2495,6 +2495,141 @@ static void demo_run(struct demo *demo) { demo->curFrame++; } #elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) +static VkResult demo_create_display_surface(struct demo *demo) { + VkResult U_ASSERT_ONLY err; + uint32_t display_count; + uint32_t mode_count; + uint32_t plane_count; + VkDisplayPropertiesKHR display_props; + VkDisplayKHR display; + VkDisplayModePropertiesKHR mode_props; + VkDisplayPlanePropertiesKHR *plane_props; + VkBool32 found_plane = VK_FALSE; + uint32_t plane_index; + VkExtent2D image_extent; + VkDisplaySurfaceCreateInfoKHR create_info; + + // Get the first display + err = vkGetPhysicalDeviceDisplayPropertiesKHR(demo->gpu, &display_count, NULL); + assert(!err); + + if (display_count == 0) { + printf("Cannot find any display!\n"); + fflush(stdout); + exit(1); + } + + display_count = 1; + err = vkGetPhysicalDeviceDisplayPropertiesKHR(demo->gpu, &display_count, &display_props); + assert(!err || (err == VK_INCOMPLETE)); + + display = display_props.display; + + // Get the first mode of the display + err = vkGetDisplayModePropertiesKHR(demo->gpu, display, &mode_count, NULL); + assert(!err); + + if (mode_count == 0) { + printf("Cannot find any mode for the display!\n"); + fflush(stdout); + exit(1); + } + + mode_count = 1; + err = vkGetDisplayModePropertiesKHR(demo->gpu, display, &mode_count, &mode_props); + assert(!err || (err == VK_INCOMPLETE)); + + // Get the list of planes + err = vkGetPhysicalDeviceDisplayPlanePropertiesKHR(demo->gpu, &plane_count, NULL); + assert(!err); + + if (plane_count == 0) { + printf("Cannot find any plane!\n"); + fflush(stdout); + exit(1); + } + + plane_props = malloc(sizeof(VkDisplayPlanePropertiesKHR) * plane_count); + assert(plane_props); + + err = vkGetPhysicalDeviceDisplayPlanePropertiesKHR(demo->gpu, &plane_count, plane_props); + assert(!err); + + // Find a plane compatible with the display + for (plane_index = 0; plane_index < plane_count; plane_index++) { + uint32_t supported_count; + VkDisplayKHR *supported_displays; + + // Disqualify planes that are bound to a different display + if ((plane_props[plane_index].currentDisplay != VK_NULL_HANDLE) && + (plane_props[plane_index].currentDisplay != display)) { + continue; + } + + err = vkGetDisplayPlaneSupportedDisplaysKHR(demo->gpu, plane_index, &supported_count, NULL); + assert(!err); + + if (supported_count == 0) { + continue; + } + + supported_displays = malloc(sizeof(VkDisplayKHR) * supported_count); + assert(supported_displays); + + err = vkGetDisplayPlaneSupportedDisplaysKHR(demo->gpu, plane_index, &supported_count, supported_displays); + assert(!err); + + for (uint32_t i = 0; i < supported_count; i++) { + if (supported_displays[i] == display) { + found_plane = VK_TRUE; + break; + } + } + + free(supported_displays); + + if (found_plane) { + break; + } + } + + if (!found_plane) { + printf("Cannot find a plane compatible with the display!\n"); + fflush(stdout); + exit(1); + } + + free(plane_props); + + image_extent.width = mode_props.parameters.visibleRegion.width; + image_extent.height = mode_props.parameters.visibleRegion.height; + + create_info.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR; + create_info.pNext = NULL; + create_info.flags = 0; + create_info.displayMode = mode_props.displayMode; + create_info.planeIndex = plane_index; + create_info.planeStackIndex = plane_props[plane_index].currentStackIndex; + create_info.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + create_info.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; + create_info.globalAlpha = 1.0f; + create_info.imageExtent = image_extent; + + return vkCreateDisplayPlaneSurfaceKHR(demo->inst, &create_info, NULL, &demo->surface); +} + +static void demo_run_display(struct demo *demo) +{ + while (!demo->quit) { + demo_draw(demo); + demo->curFrame++; + + if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount) { + demo->quit = true; + } + } +} #endif /* @@ -2641,6 +2776,13 @@ static void demo_init_vk(struct demo *demo) { VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME; } #elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + if (!strcmp(VK_KHR_DISPLAY_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + demo->extension_names[demo->enabled_extension_count++] = + VK_KHR_DISPLAY_EXTENSION_NAME; + } #elif defined(VK_USE_PLATFORM_ANDROID_KHR) if (!strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { @@ -2697,6 +2839,14 @@ static void demo_init_vk(struct demo *demo) { "information.\n", "vkCreateInstance Failure"); #elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_DISPLAY_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); #elif defined(VK_USE_PLATFORM_ANDROID_KHR) ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " "the " VK_KHR_ANDROID_SURFACE_EXTENSION_NAME @@ -2990,6 +3140,8 @@ static void demo_init_vk_swapchain(struct demo *demo) { createInfo.window = demo->xcb_window; err = vkCreateXcbSurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface); +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + err = demo_create_display_surface(demo); #endif assert(!err); @@ -3470,6 +3622,8 @@ int main(int argc, char **argv) { #elif defined(VK_USE_PLATFORM_WAYLAND_KHR) demo_run(&demo); #elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + demo_run_display(&demo); #endif demo_cleanup(&demo); diff --git a/demos/cube.cpp b/demos/cube.cpp index 20425431..a7bb7a09 100644 --- a/demos/cube.cpp +++ b/demos/cube.cpp @@ -816,6 +816,14 @@ struct Demo { extension_names[enabled_extension_count++] = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME; } #elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + if (!strcmp(VK_KHR_DISPLAY_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + extension_names[enabled_extension_count++] = + VK_KHR_DISPLAY_EXTENSION_NAME; + } + #endif assert(enabled_extension_count < 64); } @@ -875,6 +883,14 @@ struct Demo { "Please look at the Getting Started guide for additional " "information.\n", "vkCreateInstance Failure"); +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_DISPLAY_EXTENSION_NAME " extension.\n\n" + "Do you have a compatible Vulkan installable client " + "driver (ICD) installed?\n" + "Please look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); #endif } auto const app = vk::ApplicationInfo() @@ -1018,6 +1034,11 @@ struct Demo { auto result = inst.createXcbSurfaceKHR(&createInfo, nullptr, &surface); VERIFY(result == vk::Result::eSuccess); } +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + { + auto result = create_display_surface(); + VERIFY(result == vk::Result::eSuccess); + } #endif // Iterate over each queue to learn whether it supports presenting: std::unique_ptr supportsPresent(new vk::Bool32[queue_family_count]); @@ -2352,6 +2373,144 @@ struct Demo { wl_shell_surface_set_title(shell_surface, APP_SHORT_NAME); } #elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + + vk::Result create_display_surface() { + vk::Result result; + uint32_t display_count; + uint32_t mode_count; + uint32_t plane_count; + vk::DisplayPropertiesKHR display_props; + vk::DisplayKHR display; + vk::DisplayModePropertiesKHR mode_props; + vk::DisplayPlanePropertiesKHR *plane_props; + vk::Bool32 found_plane = VK_FALSE; + uint32_t plane_index; + vk::Extent2D image_extent; + + // Get the first display + result = gpu.getDisplayPropertiesKHR(&display_count, nullptr); + VERIFY(result == vk::Result::eSuccess); + + if (display_count == 0) { + printf("Cannot find any display!\n"); + fflush(stdout); + exit(1); + } + + display_count = 1; + result = gpu.getDisplayPropertiesKHR(&display_count, &display_props); + VERIFY((result == vk::Result::eSuccess) || + (result == vk::Result::eIncomplete)); + + display = display_props.display; + + // Get the first mode of the display + result = gpu.getDisplayModePropertiesKHR(display, &mode_count, nullptr); + VERIFY(result == vk::Result::eSuccess); + + if (mode_count == 0) { + printf("Cannot find any mode for the display!\n"); + fflush(stdout); + exit(1); + } + + mode_count = 1; + result = gpu.getDisplayModePropertiesKHR(display, &mode_count, &mode_props); + VERIFY((result == vk::Result::eSuccess) || + (result == vk::Result::eIncomplete)); + + // Get the list of planes + result = gpu.getDisplayPlanePropertiesKHR(&plane_count, nullptr); + VERIFY(result == vk::Result::eSuccess); + + if (plane_count == 0) { + printf("Cannot find any plane!\n"); + fflush(stdout); + exit(1); + } + + plane_props = (vk::DisplayPlanePropertiesKHR *) + malloc(sizeof(vk::DisplayPlanePropertiesKHR) * plane_count); + VERIFY(plane_props != nullptr); + + result = gpu.getDisplayPlanePropertiesKHR(&plane_count, plane_props); + VERIFY(result == vk::Result::eSuccess); + + // Find a plane compatible with the display + for (plane_index = 0; plane_index < plane_count; plane_index++) { + uint32_t supported_count; + vk::DisplayKHR *supported_displays; + + // Disqualify planes that are bound to a different display + if (plane_props[plane_index].currentDisplay && + (plane_props[plane_index].currentDisplay != display)) { + continue; + } + + result = gpu.getDisplayPlaneSupportedDisplaysKHR(plane_index, + &supported_count, + nullptr); + VERIFY(result == vk::Result::eSuccess); + + if (supported_count == 0) { + continue; + } + + supported_displays = (vk::DisplayKHR *) + malloc(sizeof(vk::DisplayKHR) * supported_count); + VERIFY(supported_displays != nullptr); + + result = gpu.getDisplayPlaneSupportedDisplaysKHR(plane_index, + &supported_count, + supported_displays); + VERIFY(result == vk::Result::eSuccess); + + for (uint32_t i = 0; i < supported_count; i++) { + if (supported_displays[i] == display) { + found_plane = VK_TRUE; + break; + } + } + + free(supported_displays); + + if (found_plane) { + break; + } + } + + if (!found_plane) { + printf("Cannot find a plane compatible with the display!\n"); + fflush(stdout); + exit(1); + } + + free(plane_props); + + image_extent.setWidth(mode_props.parameters.visibleRegion.width); + image_extent.setHeight(mode_props.parameters.visibleRegion.height); + + auto const createInfo = vk::DisplaySurfaceCreateInfoKHR() + .setDisplayMode(mode_props.displayMode) + .setPlaneIndex(plane_index) + .setPlaneStackIndex(plane_props[plane_index].currentStackIndex) + .setImageExtent(image_extent); + + return inst.createDisplayPlaneSurfaceKHR(&createInfo, nullptr, &surface); + } + + void run_display() { + while (!quit) { + update_data_buffer(); + draw(); + curFrame++; + + if (frameCount != INT32_MAX && curFrame == frameCount) { + quit = true; + } + } + } #endif #if defined(VK_USE_PLATFORM_WIN32_KHR) @@ -2611,6 +2770,8 @@ int main(int argc, char **argv) { #elif defined(VK_USE_PLATFORM_WAYLAND_KHR) demo.run(); #elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + demo.run_display(); #endif demo.cleanup(); -- cgit v1.2.3