M CMakeLists.txt => CMakeLists.txt +38 -25
@@ 145,33 145,46 @@ endforeach()
set(WAYLAND_PROTOCOLS_DIR "${CMAKE_CURRENT_BINARY_DIR}/wayland-protocols/")
file(MAKE_DIRECTORY "${WAYLAND_PROTOCOLS_DIR}")
-set(PROTOCOL xdg-shell-unstable-v6)
-set(PROTOCOL_XML
- "${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/${PROTOCOL}.xml")
+set(PROTOCOLS)
+set(PROTOCOLS_XML)
+list(APPEND PROTOCOLS xdg-shell-unstable-v6)
+list(APPEND PROTOCOLS_XML
+ "${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/xdg-shell-unstable-v6.xml")
+
+list(APPEND PROTOCOLS drm-lease-unstable-v1)
+list(APPEND PROTOCOLS_XML
+ "${CMAKE_CURRENT_SOURCE_DIR}/vitamin-k/window/drm-lease-unstable-v1.xml")
set(WAYLAND_PROTOCOLS_SRC)
-set(OUTFILE "${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c")
-list(APPEND WAYLAND_PROTOCOLS_SRC "${OUTFILE}")
-add_custom_command(OUTPUT "${OUTFILE}"
- COMMAND
- ${WAYLAND_SCANNER}
- code
- "${PROTOCOL_XML}"
- "${OUTFILE}"
- VERBATIM
- COMMENT "Generating code file with wayland-scanner")
-
-
-set(OUTFILE "${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h")
-list(APPEND WAYLAND_PROTOCOLS_SRC "${OUTFILE}")
-add_custom_command(OUTPUT "${OUTFILE}"
- COMMAND
- ${WAYLAND_SCANNER}
- client-header
- "${PROTOCOL_XML}"
- "${OUTFILE}"
- VERBATIM
- COMMENT "Generating client header file with wayland-scanner")
+list(LENGTH PROTOCOLS NPROTOCOLS)
+math(EXPR NPROTOCOLS "${NPROTOCOLS}-1")
+foreach(INDEX RANGE ${NPROTOCOLS})
+ list(GET PROTOCOLS ${INDEX} PROTOCOL)
+ list(GET PROTOCOLS_XML ${INDEX} PROTOCOL_XML)
+
+ set(OUTFILE "${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.c")
+ list(APPEND WAYLAND_PROTOCOLS_SRC "${OUTFILE}")
+
+ add_custom_command(OUTPUT "${OUTFILE}"
+ COMMAND
+ ${WAYLAND_SCANNER}
+ private-code
+ "${PROTOCOL_XML}"
+ "${OUTFILE}"
+ VERBATIM
+ COMMENT "Generating code file with wayland-scanner for ${PROTOCOL}")
+
+ set(OUTFILE "${WAYLAND_PROTOCOLS_DIR}/${PROTOCOL}.h")
+ list(APPEND WAYLAND_PROTOCOLS_SRC "${OUTFILE}")
+ add_custom_command(OUTPUT "${OUTFILE}"
+ COMMAND
+ ${WAYLAND_SCANNER}
+ client-header
+ "${PROTOCOL_XML}"
+ "${OUTFILE}"
+ VERBATIM
+ COMMENT "Generating client header file with wayland-scanner for ${PROTOCOL}")
+endforeach()
add_library(wayland-protocols ${WAYLAND_PROTOCOLS_SRC})
target_include_directories(wayland-protocols PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
M vitamin-k/render/vikRenderer.hpp => vitamin-k/render/vikRenderer.hpp +2 -1
@@ 467,8 467,9 @@ class Renderer {
if (count > 0) {
std::vector<VkExtensionProperties> extensions(count);
if (vkEnumerateInstanceExtensionProperties(nullptr, &count, &extensions.front()) == VK_SUCCESS)
- for (auto ext : extensions)
+ for (auto ext : extensions) {
supported_extensions.push_back(ext.extensionName);
+ }
}
}
M vitamin-k/system/vikApplication.hpp => vitamin-k/system/vikApplication.hpp +4 -0
@@ 31,6 31,7 @@
#endif
#include "../window/vikWindowDirectMode.hpp"
+#include "../window/vikWindowDirectWayland.hpp"
#include "../render/vikTools.hpp"
#include "../scene/vikCamera.hpp"
@@ 177,6 178,9 @@ class Application {
case Settings::DIRECT_MODE:
window = new WindowDirectMode(&settings);
return set_and_init_window();
+ case Settings::DIRECT_WAYLAND:
+ window = new WindowDirectWayland(&settings);
+ return set_and_init_window();
default:
vik_log_f("Usupported Window Type %d", settings.window_type);
return -1;
M vitamin-k/system/vikSettings.hpp => vitamin-k/system/vikSettings.hpp +3 -0
@@ 31,6 31,7 @@ class Settings {
WAYLAND_XDG,
WAYLAND_SHELL,
DIRECT_MODE,
+ DIRECT_WAYLAND,
INVALID
};
@@ 268,6 269,8 @@ class Settings {
return WAYLAND_SHELL;
else if (streq(s, "direct"))
return DIRECT_MODE;
+ else if (streq(s, "direct-wayland"))
+ return DIRECT_WAYLAND;
else
return INVALID;
}
A vitamin-k/window/drm-lease-unstable-v1.xml => vitamin-k/window/drm-lease-unstable-v1.xml +246 -0
@@ 0,0 1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm_lease_unstable_v1">
+ <copyright>
+ Copyright © 2018 NXP
+ Copyright © 2019 Status Research & Development GmbH.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="zwp_drm_lease_manager_v1" version="1">
+ <description summary="lease manager">
+ This protocol is used by Wayland compositors which act as Direct
+ Renderering Manager (DRM) masters to lease DRM resources to Wayland
+ clients. Once leased, the compositor will not use the leased resources
+ until the lease is revoked or the client closes the file descriptor. The
+ compositor will advertise one zwp_drm_lease_manager_v1 for each DRM node
+ which has resources available for leasing.
+
+ The lease manager is used to advertise connectors which are available for
+ leasing, and by the client to negotiate a lease request.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible changes
+ may be added together with the corresponding interface version bump.
+ Backward incompatible changes are done by bumping the version number in
+ the protocol and interface names and resetting the interface version.
+ Once the protocol is to be declared stable, the 'z' prefix and the
+ version number in the protocol and interface names are removed and the
+ interface version number is reset.
+ </description>
+
+ <enum name="error">
+ <entry name="stopped_manager" value="0"
+ summary="request sent to a manager which has been stopped"/>
+ </enum>
+
+ <request name="create_lease_request">
+ <description summary="create a lease request object">
+ Creates a lease request object.
+
+ See the documentation for zwp_drm_lease_request_v1 for details.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_drm_lease_request_v1" />
+ </request>
+
+ <request name="stop">
+ <description summary="stop sending events">
+ Indicates the client no longer wishes to receive connector events. The
+ compositor may still send connector events until it sends the finish
+ event, however.
+
+ The client must not send any requests after this one.
+ </description>
+ </request>
+
+ <event name="drm_fd">
+ <description summary="open a non-master fd for this DRM node">
+ The compositor will send this event when the zwp_drm_lease_manager_v1
+ global is bound. The included fd is a non-master DRM file descriptor
+ opened for this device. The purpose of this event is to give the client
+ the ability to query DRM and discover information which may help them
+ pick the appropriate DRM device or select the appropriate connectors
+ therein.
+ </description>
+ <arg name="fd" type="fd" summary="DRM file descriptor" />
+ </event>
+
+ <event name="connector">
+ <description summary="advertise connectors available for leases">
+ The compositor may choose to advertise 0 or more connectors which may be
+ leased to clients, and will use this event to do so. This object may be
+ passed into a lease request to lease that connector. See
+ zwp_drm_lease_request_v1.add_connector for details.
+
+ When this global is bound, the compositor will send all connectors
+ available for lease, but may send additional connectors at any time.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_drm_lease_connector_v1" />
+ </event>
+
+ <event name="finished">
+ <description summary="the compositor has finished using the manager">
+ This event indicates that the compositor is done sending connector
+ events. The compositor will destroy this object immediately after
+ sending this event, and it will become invalid. The client should
+ release any resources associated with this manager after receiving this
+ event.
+ </description>
+ </event>
+ </interface>
+
+ <interface name="zwp_drm_lease_connector_v1" version="1">
+ <description summary="a leasable DRM connector">
+ Represents a DRM connector which is available for lease. These objects are
+ created via zwp_drm_lease_manager_v1.connector, and should be passed into
+ lease requests via zwp_drm_lease_request_v1.add_connector.
+ </description>
+
+ <event name="name">
+ <description summary="name">
+ The compositor sends this event once the connector is created to
+ indicate the name of this connector. This will not change for the
+ duration of the Wayland session, but is not guaranteed to be consistent
+ between sessions.
+
+ If the compositor also supports zxdg_output_manager_v1 and this
+ connector corresponds to a zxdg_output_v1, this name will match the
+ name of this zxdg_output_v1 object.
+ </description>
+ <arg name="name" type="string" summary="connector name" />
+ </event>
+
+ <event name="description">
+ <description summary="description">
+ The compositor sends this event once the connector is created to provide
+ a human-readable description for this connector, which may be presented
+ to the user.
+ </description>
+ <arg name="description" type="string" summary="connector description" />
+ </event>
+
+ <event name="connector_id">
+ <description summary="connector_id">
+ The compositor will send this event to indicate the DRM ID which
+ represents the underlying connector which is being offered. Note that
+ the final lease may include additional object IDs, such as CRTCs and
+ planes.
+ </description>
+ <arg name="connector_id" type="int" summary="DRM Connector ID" />
+ </event>
+
+ <event name="withdrawn">
+ <description summary="lease offer withdrawn">
+ Sent to indicate that the compositor will no longer honor requests for
+ DRM leases which include this connector. The client may still issue a
+ lease request including this connector, but the compositor will send
+ zwp_drm_lease_v1.finished without issuing a lease fd.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy connector">
+ The client may send this request to indicate that it will not issue a
+ lease request for this connector. Clients are encouraged to send this
+ after receiving the "withdrawn" request so that the server can release
+ the resources associated with this connector offer.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwp_drm_lease_request_v1" version="1">
+ <description summary="DRM lease request">
+ A client that wishes to lease DRM resources will attach the list of
+ connectors advertised with zwp_drm_lease_manager_v1.connector that they
+ wish to lease, then use zwp_drm_lease_request_v1.submit to submit the
+ request.
+ </description>
+
+ <enum name="error">
+ <entry name="submitted_lease" value="0"
+ summary="attempted to reuse a submitted lease"/>
+ </enum>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroys the lease request object">
+ Indicates that the client will no longer use this lease request.
+ </description>
+ </request>
+
+ <request name="request_connector">
+ <description summary="request a connector for this lease">
+ Indicates that the client would like to lease the given connector.
+ This is only used as a suggestion, the compositor may choose to
+ include any resources in the lease it issues, or change the set of
+ leased resources at any time.
+ </description>
+ <arg name="connector" type="object"
+ interface="zwp_drm_lease_connector_v1" />
+ </request>
+
+ <request name="submit">
+ <description summary="submit the lease request">
+ Submits the lease request and creates a new zwp_drm_lease_v1 object.
+ After calling submit, issuing any other request than destroy is a
+ protocol error.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_drm_lease_v1" />
+ </request>
+ </interface>
+
+ <interface name="zwp_drm_lease_v1" version="1">
+ <description summary="a DRM lease">
+ A DRM lease object is used to transfer the DRM file descriptor to the
+ client and manage the lifetime of the lease.
+ </description>
+
+ <event name="lease_fd">
+ <description summary="shares the DRM file descriptor">
+ This event returns a file descriptor suitable for use with DRM-related
+ ioctls. The client should use drmModeGetLease to enumerate the DRM
+ objects which have been leased to them. If the compositor cannot or
+ will not grant a lease for the requested connectors, it will not send
+ this event, instead sending the finished event immediately.
+
+ It is a protocol error for the compositor to send this event more than
+ once for a given lease.
+ </description>
+ <arg name="leased_fd" type="fd" summary="leased DRM file descriptor" />
+ </event>
+
+ <event name="finished">
+ <description summary="sent when the lease has been revoked">
+ When the compositor revokes the lease, it will issue this event to
+ notify clients of the change. If the client requires a new lease, they
+ should destroy this object and submit a new lease request. The
+ compositor will send no further events for this object after sending
+ the finish event.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroys the lease object">
+ The client should send this to indicate that it no longer wishes to use
+ this lease. The compositor should use drmModeRevokeLease on the
+ appropriate file descriptor, if necessary, then release this object.
+ </description>
+ </request>
+ </interface>
+</protocol>
A vitamin-k/window/vikWindowDirectWayland.hpp => vitamin-k/window/vikWindowDirectWayland.hpp +345 -0
@@ 0,0 1,345 @@
+/*
+ * vitamin-k
+ *
+ * Copyright 2017-2018 Collabora Ltd.
+ * Copyright 2019 Status Holdings Ltd.
+ *
+ * Authors: Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
+ * Authors: Drew DeVault <sir@cmpwn.com>
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+
+#include <wayland-client.h>
+#include "wayland-protocols/drm-lease-unstable-v1.h"
+
+#include <vulkan/vulkan.h>
+#include <vulkan/vulkan_wayland.h>
+
+#include <string>
+#include <vector>
+#include <utility>
+
+#include "vikWindow.hpp"
+
+#include "../render/vikSwapChainVK.hpp"
+
+namespace vik {
+class WindowDirectWayland : public Window {
+ struct wl_display *wl_display = nullptr;
+ struct zwp_drm_lease_manager_v1 *manager = nullptr;
+
+ SwapChainVK swap_chain;
+
+ struct VikDisplay {
+ std::string name, description;
+ struct zwp_drm_lease_connector_v1 *connector;
+ struct zwp_drm_lease_v1 *lease;
+ };
+
+ std::vector<VikDisplay> displays;
+
+ static void lease_connector_handle_connector_id(void *data,
+ struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
+ int32_t conn_id) {
+ /* This space deliberately left blank */
+ }
+
+ static void lease_connector_handle_name(void *data,
+ struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
+ const char *name) {
+ VikDisplay *d = (VikDisplay *)data;
+ d->name = std::string(name);
+ }
+
+ static void lease_connector_handle_description(void *data,
+ struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1,
+ const char *desc) {
+ VikDisplay *d = (VikDisplay *)data;
+ d->description = std::string(desc);
+ }
+
+ static void lease_connector_handle_withdrawn(void *data,
+ struct zwp_drm_lease_connector_v1 *zwp_drm_lease_connector_v1) {
+ /* This space deliberately left blank */
+ }
+
+ const struct zwp_drm_lease_connector_v1_listener lease_connector_listener = {
+ .name = lease_connector_handle_name,
+ .description = lease_connector_handle_description,
+ .connector_id = lease_connector_handle_connector_id,
+ .withdrawn = lease_connector_handle_withdrawn,
+ };
+
+ static void lease_manager_handle_drm_fd(void *data,
+ struct zwp_drm_lease_manager_v1 *lease_manager, int fd) {
+ close(fd);
+ }
+
+ static void lease_manager_handle_connector(void *data,
+ struct zwp_drm_lease_manager_v1 *lease_manager,
+ struct zwp_drm_lease_connector_v1 *id) {
+ WindowDirectWayland *win = (WindowDirectWayland *)data;
+ VikDisplay d = {
+ .connector = id,
+ };
+ win->displays.push_back(d);
+ zwp_drm_lease_connector_v1_add_listener(id, &win->lease_connector_listener,
+ &win->displays[win->displays.size() - 1]);
+ }
+
+ static void lease_manager_handle_finished(void *data,
+ struct zwp_drm_lease_manager_v1 *lease_manager) {
+ /* This space deliberately left blank */
+ }
+
+ const struct zwp_drm_lease_manager_v1_listener lease_manager_listener = {
+ .drm_fd = lease_manager_handle_drm_fd,
+ .connector = lease_manager_handle_connector,
+ .finished = lease_manager_handle_finished,
+ };
+
+ static void registry_handle_global(
+ void *data, struct wl_registry *wl_registry, uint32_t name,
+ const char *interface, uint32_t version) {
+ WindowDirectWayland *win = (WindowDirectWayland *)data;
+ if (strcmp(interface, zwp_drm_lease_manager_v1_interface.name) == 0) {
+ win->manager = (struct zwp_drm_lease_manager_v1 *)wl_registry_bind(
+ wl_registry, name, &zwp_drm_lease_manager_v1_interface, 1);
+ }
+ }
+
+ static void registry_handle_global_remove(
+ void *data, struct wl_registry *wl_registry, uint32_t name) {
+ // Who cares
+ }
+
+ const struct wl_registry_listener registry_listener = {
+ .global = registry_handle_global,
+ .global_remove = registry_handle_global_remove,
+ };
+
+ public:
+ explicit WindowDirectWayland(Settings *s) : Window(s) {
+ name = "direct-wayland";
+ }
+
+ ~WindowDirectWayland() {
+ if (manager)
+ zwp_drm_lease_manager_v1_destroy(manager);
+ if (wl_display)
+ wl_display_disconnect(wl_display);
+ }
+
+ int init() {
+ wl_display = wl_display_connect(NULL);
+ if (wl_display == NULL)
+ return -1;
+
+ struct wl_registry *wl_registry = wl_display_get_registry(wl_display);
+ wl_registry_add_listener(wl_registry, ®istry_listener, this);
+ wl_display_roundtrip(wl_display);
+ if (manager == nullptr) {
+ vik_log_f("Wayland compositor does not support drm-lease-unstable-v1");
+ return -1;
+ }
+ zwp_drm_lease_manager_v1_add_listener(
+ manager, &lease_manager_listener, this);
+ wl_display_roundtrip(wl_display);
+ /* Again to get connector details */
+ wl_display_roundtrip(wl_display);
+
+ if (settings->list_screens_and_exit) {
+ int display_i = 0;
+ for (VikDisplay d : displays) {
+ vik_log_i("%d: %s %s",
+ display_i,
+ d.name.c_str(),
+ d.description.c_str());
+ display_i++;
+ }
+ exit(0);
+ }
+
+ if (settings->display > (int) displays.size() - 1) {
+ vik_log_w("Requested display %d, but only %d displays are available.",
+ settings->display, displays.size());
+
+ settings->display = 0;
+ VikDisplay *d = current_display();
+ vik_log_w("Selecting '%s' instead.", d->name.c_str());
+ }
+
+ if (settings->display < 0) {
+ settings->display = 0;
+ VikDisplay *d = current_display();
+ vik_log_w("Selecting '%s' first display.", d->name.c_str());
+ }
+
+ settings->size.first = 2160;
+ settings->size.second = 1200;
+ size_only_cb(settings->size.first, settings->size.second);
+
+ return 0;
+ }
+
+ VikDisplay* current_display() {
+ return &displays[settings->display];
+ }
+
+ void iterate() {
+ render_frame_cb();
+ }
+
+ VkDisplayModeKHR get_primary_display_mode (VkDisplayKHR display) {
+ uint32_t mode_count;
+ VkResult res =
+ vkGetDisplayModePropertiesKHR(swap_chain.physical_device, display,
+ &mode_count, nullptr);
+ vik_log_f_if(res != VK_SUCCESS,
+ "Could not vkGetDisplayModePropertiesKHR: %s",
+ Log::result_string(res).c_str());
+
+ vik_log_d("Found %d modes", mode_count);
+
+ VkDisplayModePropertiesKHR* mode_properties;
+ mode_properties = new VkDisplayModePropertiesKHR[mode_count];
+ res = vkGetDisplayModePropertiesKHR(swap_chain.physical_device, display,
+ &mode_count, mode_properties);
+ vik_log_f_if(res != VK_SUCCESS,
+ "Could not vkGetDisplayModePropertiesKHR: %s",
+ Log::result_string(res).c_str());
+
+ VkDisplayModePropertiesKHR props = mode_properties[0];
+
+ vik_log_d("found dispkay mode %d %d",
+ props.parameters.visibleRegion.width,
+ props.parameters.visibleRegion.height);
+
+ delete[] mode_properties;
+
+ return props.displayMode;
+ }
+
+ VkDisplayPlaneAlphaFlagBitsKHR
+ choose_alpha_mode (VkDisplayPlaneAlphaFlagsKHR flags) {
+ if (flags & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR)
+ return VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR;
+ else if (flags & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR)
+ return VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR;
+ else
+ return VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR;
+ }
+
+ void init_swap_chain(uint32_t width, uint32_t height) {
+ VikDisplay *d = current_display();
+
+ vik_log_i("Will use display: %s", d->name.c_str());
+
+ VkDisplayKHR display = acquire_wl_display(current_display());
+
+ // Get plane properties
+ uint32_t plane_property_count;
+ VkResult res =
+ vkGetPhysicalDeviceDisplayPlanePropertiesKHR(swap_chain.physical_device,
+ &plane_property_count,
+ nullptr);
+ vik_log_f_if(res != VK_SUCCESS,
+ "Could not vkGetPhysicalDeviceDisplayPlanePropertiesKHR: %s",
+ Log::result_string(res).c_str());
+
+ vik_log_i("Found %d plane properites.", plane_property_count);
+
+ VkDisplayPlanePropertiesKHR* plane_properties =
+ new VkDisplayPlanePropertiesKHR[plane_property_count];
+
+ res =
+ vkGetPhysicalDeviceDisplayPlanePropertiesKHR(swap_chain.physical_device,
+ &plane_property_count,
+ plane_properties);
+ vik_log_f_if(res != VK_SUCCESS,
+ "Could not vkGetPhysicalDeviceDisplayPlanePropertiesKHR: %s",
+ Log::result_string(res).c_str());
+
+ uint32_t plane_index = 0;
+
+ VkDisplayModeKHR display_mode = get_primary_display_mode (display);
+
+ VkDisplayPlaneCapabilitiesKHR plane_caps;
+ vkGetDisplayPlaneCapabilitiesKHR(swap_chain.physical_device, display_mode,
+ plane_index, &plane_caps);
+
+ VkDisplaySurfaceCreateInfoKHR surface_info = {
+ .sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR,
+ .flags = 0,
+ .displayMode = display_mode,
+ .planeIndex = plane_index,
+ .planeStackIndex = plane_properties[plane_index].currentStackIndex,
+ .transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
+ .globalAlpha = 1.0,
+ .alphaMode = choose_alpha_mode(plane_caps.supportedAlpha),
+ .imageExtent = {
+ .width = width,
+ .height = height
+ }
+ };
+
+ VkResult result = vkCreateDisplayPlaneSurfaceKHR(swap_chain.instance,
+ &surface_info, nullptr,
+ &swap_chain.surface);
+ vik_log_f_if(result !=VK_SUCCESS, "Failed to create surface!");
+
+ delete[] plane_properties;
+
+ swap_chain.set_settings(settings);
+ swap_chain.select_surface_format();
+ swap_chain.create(width, height);
+ }
+
+ SwapChain* get_swap_chain() {
+ return (SwapChain*) &swap_chain;
+ }
+
+ VkDisplayKHR acquire_wl_display(VikDisplay *dpy) {
+ VkWaylandLeaseConnectorEXT connectors[] = {
+ {
+ .pConnector = dpy->connector,
+ }
+ };
+
+ PFN_vkAcquireWaylandDisplayEXT fun =
+ (PFN_vkAcquireWaylandDisplayEXT)
+ vkGetInstanceProcAddr(swap_chain.instance, "vkAcquireWaylandDisplayEXT");
+ vik_log_f_if(fun == nullptr,
+ "Could not Get Device Proc Addr vkAcquireWaylandDisplayEXT.");
+
+ VkResult res = fun(swap_chain.physical_device,
+ wl_display, manager, 1, connectors);
+ vik_log_f_if(res != VK_SUCCESS,
+ "Could not acquire Wayland display: %s",
+ Log::result_string(res).c_str());
+ return connectors[0].pDisplay;
+ }
+
+ public:
+ const std::vector<const char*> required_extensions() {
+ return {
+ VK_KHR_DISPLAY_EXTENSION_NAME,
+ VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME,
+ VK_EXT_ACQUIRE_WL_DISPLAY_EXTENSION_NAME,
+ };
+ }
+
+ const std::vector<const char*> required_device_extensions() {
+ return {};
+ }
+
+ VkBool32 check_support(VkPhysicalDevice physical_device) {
+ return true;
+ }
+
+ void update_window_title(const std::string& title) {}
+
+};
+} // namespace vik