layer, wlserver: Implement swapchain feedback

This commit is contained in:
Joshua Ashton 2022-12-15 08:02:41 +00:00 committed by Joshie
parent 1064ddcce7
commit 2aa4791ba0
5 changed files with 96 additions and 5 deletions

View file

@ -25,6 +25,7 @@ namespace GamescopeWSILayer {
VKROOTS_DEFINE_SYNCHRONIZED_MAP_TYPE(GamescopeInstance, VkInstance);
struct GamescopeSurfaceData {
VkInstance instance;
wl_surface* surface;
};
VKROOTS_DEFINE_SYNCHRONIZED_MAP_TYPE(GamescopeSurface, VkSurfaceKHR);
@ -258,6 +259,7 @@ namespace GamescopeWSILayer {
printf("Made gamescope surface for xid: 0x%x\n", window_xid);
GamescopeSurface::create(*pSurface, GamescopeSurfaceData {
.instance = instance,
.surface = waylandSurface,
});
@ -311,7 +313,7 @@ namespace GamescopeWSILayer {
wl_registry_bind(registry, name, &wl_compositor_interface, version));
} else if (!std::strcmp(interface, gamescope_xwayland_interface.name)) {
instance->gamescope = reinterpret_cast<gamescope_xwayland *>(
wl_registry_bind(registry, name, &gamescope_xwayland_interface, 1));
wl_registry_bind(registry, name, &gamescope_xwayland_interface, version));
}
},
.global_remove = [](void* data, wl_registry* registry, uint32_t name) {
@ -351,6 +353,23 @@ namespace GamescopeWSILayer {
GamescopeSwapchain::create(*pSwapchain, GamescopeSwapchainData{
.surface = pCreateInfo->surface,
});
auto gamescopeInstance = GamescopeInstance::get((*gamescopeSurface)->instance);
if (gamescopeInstance) {
uint32_t imageCount = 0;
pDispatch->GetSwapchainImagesKHR(device, *pSwapchain, &imageCount, nullptr);
gamescope_xwayland_swapchain_feedback(
(*gamescopeInstance)->gamescope,
(*gamescopeSurface)->surface,
imageCount,
uint32_t(pCreateInfo->imageFormat),
uint32_t(pCreateInfo->imageColorSpace),
uint32_t(pCreateInfo->compositeAlpha),
uint32_t(pCreateInfo->preTransform),
uint32_t(pCreateInfo->presentMode),
uint32_t(pCreateInfo->clipped));
}
}
return res;
}
@ -369,7 +388,8 @@ namespace GamescopeWSILayer {
VKROOTS_DEFINE_LAYER_INTERFACES(GamescopeWSILayer::VkInstanceOverrides,
vkroots::NoOverrides,
vkroots::NoOverrides);
GamescopeWSILayer::VkDeviceOverrides);
VKROOTS_IMPLEMENT_SYNCHRONIZED_MAP_TYPE(GamescopeWSILayer::GamescopeInstance);
VKROOTS_IMPLEMENT_SYNCHRONIZED_MAP_TYPE(GamescopeWSILayer::GamescopeSurface);
VKROOTS_IMPLEMENT_SYNCHRONIZED_MAP_TYPE(GamescopeWSILayer::GamescopeSwapchain);

View file

@ -4,7 +4,7 @@ project(
'cpp',
meson_version: '>=0.58.0',
default_options: [
'cpp_std=c++14',
'cpp_std=c++17',
'warning_level=2',
'force_fallback_for=wlroots,libliftoff',
],

View file

@ -29,7 +29,7 @@
it.
</description>
<interface name="gamescope_xwayland" version="1">
<interface name="gamescope_xwayland" version="2">
<request name="destroy" type="destructor"></request>
<request name="override_window_content">
@ -46,5 +46,34 @@
<arg name="surface" type="object" interface="wl_surface" summary="Wayland surface"/>
<arg name="x11_window" type="uint" summary="X11 window ID"/>
</request>
<request name="swapchain_feedback" since="2">
<description summary="provide swapchain feedback">
Provide swapchain feedback to the compositor.
This is what the useless tearing protocol should have been.
Absolutely not enough information in the final protocol to do what we want for SteamOS --
which is have the Allow Tearing toggle apply to *both* Mailbox + Immediate and NOT fifo,
essentially acting as an override for tearing on/off for games.
The upstream protocol is very useless for our usecase here.
Provides image count ahead of time instead of needing to try and calculate it from
an initial stall if we are doing low latency.
Provides colorspace info for us to do HDR for both HDR10 PQ and scRGB.
The upstream HDR efforts seem to have no interest in supporting scRGB but we *need* that so /shrug
We can do it here now! Yipee!
Swapchain feedback solves so many problems! :D
</description>
<arg name="surface" type="object" interface="wl_surface" summary="Wayland surface"/>
<arg name="image_count" type="uint" summary="image count of swapchain"/>
<arg name="vk_format" type="uint" summary="VkFormat of swapchain"/>
<arg name="vk_colorspace" type="uint" summary="VkColorSpaceKHR of swapchain"/>
<arg name="vk_composite_alpha" type="uint" summary="VkCompositeAlphaFlagBitsKHR of swapchain"/>
<arg name="vk_pre_transform" type="uint" summary="VkSurfaceTransformFlagBitsKHR of swapchain"/>
<arg name="vk_present_mode" type="uint" summary="VkPresentModeKHR of swapchain"/>
<arg name="vk_clipped" type="uint" summary="clipped (VkBool32) of swapchain"/>
</request>
</interface>
</protocol>

View file

@ -515,6 +515,32 @@ static void gamescope_xwayland_handle_override_window_content( struct wl_client
server->handle_override_window_content(client, resource, surface_resource, x11_window);
}
static void gamescope_xwayland_handle_swapchain_feedback( struct wl_client *client, struct wl_resource *resource,
struct wl_resource *surface_resource,
uint32_t image_count,
uint32_t vk_format,
uint32_t vk_colorspace,
uint32_t vk_composite_alpha,
uint32_t vk_pre_transform,
uint32_t vk_present_mode,
uint32_t vk_clipped)
{
struct wlr_surface *surface = wlr_surface_from_resource( surface_resource );
wlserver_wl_surface_info *wl_info = get_wl_surface_info( surface );
if ( wl_info )
{
wl_info->swapchain_feedback = wlserver_vk_swapchain_feedback {
.image_count = image_count,
.vk_format = VkFormat(vk_format),
.vk_colorspace = VkColorSpaceKHR(vk_colorspace),
.vk_composite_alpha = VkCompositeAlphaFlagBitsKHR(vk_composite_alpha),
.vk_pre_transform = VkSurfaceTransformFlagBitsKHR(vk_pre_transform),
.vk_present_mode = VkPresentModeKHR(vk_present_mode),
.vk_clipped = VkBool32(vk_clipped),
};
}
}
static void gamescope_xwayland_handle_destroy( struct wl_client *client, struct wl_resource *resource )
{
wl_resource_destroy( resource );
@ -523,6 +549,7 @@ static void gamescope_xwayland_handle_destroy( struct wl_client *client, struct
static const struct gamescope_xwayland_interface gamescope_xwayland_impl = {
.destroy = gamescope_xwayland_handle_destroy,
.override_window_content = gamescope_xwayland_handle_override_window_content,
.swapchain_feedback = gamescope_xwayland_handle_swapchain_feedback,
};
static void gamescope_xwayland_bind( struct wl_client *client, void *data, uint32_t version, uint32_t id )
@ -533,7 +560,7 @@ static void gamescope_xwayland_bind( struct wl_client *client, void *data, uint3
static void create_gamescope_xwayland( void )
{
uint32_t version = 1;
uint32_t version = 2;
wl_global_create( wlserver.display, &gamescope_xwayland_interface, version, NULL, gamescope_xwayland_bind );
}

View file

@ -9,6 +9,8 @@
#include <mutex>
#include <map>
#include <set>
#include <optional>
#include <vulkan/vulkan_core.h>
#define WLSERVER_BUTTON_COUNT 4
@ -199,6 +201,17 @@ struct wlserver_x11_surface_info
gamescope_xwayland_server_t *xwayland_server;
};
struct wlserver_vk_swapchain_feedback
{
uint32_t image_count;
VkFormat vk_format;
VkColorSpaceKHR vk_colorspace;
VkCompositeAlphaFlagBitsKHR vk_composite_alpha;
VkSurfaceTransformFlagBitsKHR vk_pre_transform;
VkPresentModeKHR vk_present_mode;
VkBool32 vk_clipped;
};
struct wlserver_wl_surface_info
{
wlserver_x11_surface_info *x11_surface = nullptr;
@ -207,6 +220,8 @@ struct wlserver_wl_surface_info
struct wl_listener destroy;
uint32_t presentation_hint = 0;
std::optional<wlserver_vk_swapchain_feedback> swapchain_feedback = std::nullopt;
};
void wlserver_x11_surface_info_init( struct wlserver_x11_surface_info *surf, gamescope_xwayland_server_t *server, uint32_t x11_id );