chore(gamescope): Apply patches sooner, use newer wlroots

This commit is contained in:
Kyle Gospodnetich 2024-07-05 08:37:02 -07:00
parent 8736c5afc4
commit 00ae363482
3 changed files with 460 additions and 3 deletions

View File

@ -0,0 +1,239 @@
From ab115896be1a448bde0eb7673c26300ea4ca5040 Mon Sep 17 00:00:00 2001
From: sharkautarch <128002472+sharkautarch@users.noreply.github.com>
Date: Sun, 19 May 2024 20:15:36 -0400
Subject: [PATCH 1/2] QueuePresent: canBypassXWayland(): fetch multiple xcb
cookies initially before waiting on any of them
---
layer/VkLayer_FROG_gamescope_wsi.cpp | 1 +
layer/xcb_helpers.hpp | 105 +++++++++++++++++++++++----
2 files changed, 93 insertions(+), 13 deletions(-)
diff --git a/layer/VkLayer_FROG_gamescope_wsi.cpp b/layer/VkLayer_FROG_gamescope_wsi.cpp
index 5844c2a63..ca44849f2 100644
--- a/layer/VkLayer_FROG_gamescope_wsi.cpp
+++ b/layer/VkLayer_FROG_gamescope_wsi.cpp
@@ -975,6 +975,7 @@ namespace GamescopeWSILayer {
continue;
}
+ xcb::Prefetcher prefetcher(gamescopeSurface->connection, gamescopeSurface->window);
const bool canBypass = gamescopeSurface->canBypassXWayland();
if (canBypass != gamescopeSwapchain->isBypassingXWayland)
UpdateSwapchainResult(canBypass ? VK_SUBOPTIMAL_KHR : VK_ERROR_OUT_OF_DATE_KHR);
diff --git a/layer/xcb_helpers.hpp b/layer/xcb_helpers.hpp
index 8fac5635b..72d0ec092 100644
--- a/layer/xcb_helpers.hpp
+++ b/layer/xcb_helpers.hpp
@@ -4,22 +4,106 @@
#include <xcb/composite.h>
#include <cstdio>
#include <optional>
+#include <pthread.h>
namespace xcb {
+ inline static constinit pthread_t g_cache_tid; //incase g_cache could otherwise be accessed by one thread, while it is being deleted by another thread
+ inline static constinit struct cookie_cache_t {
+ xcb_window_t window;
+ std::tuple<xcb_get_geometry_cookie_t, xcb_query_tree_cookie_t> cached_cookies;
+ std::tuple<xcb_get_geometry_reply_t*, xcb_query_tree_reply_t*> cached_replies;
+ } g_cache = {};
+
+ //Note: this class is currently only meant to be used within GamescopeWSILayer::VkDeviceOverrides::QueuePresentKHR:
+ struct Prefetcher {
+ explicit Prefetcher(xcb_connection_t* connection, const xcb_window_t window) {
+ g_cache = {
+ .window = window,
+ .cached_cookies = {
+ xcb_get_geometry(connection, window),
+ xcb_query_tree(connection, window)
+ }
+ };
+ g_cache_tid = pthread_self();
+ }
+ ~Prefetcher() {
+ g_cache_tid = {};
+ free(std::get<0>(g_cache.cached_replies));
+ free(std::get<1>(g_cache.cached_replies));
+ g_cache.cached_replies = {nullptr,nullptr};
+ }
+ };
+
struct ReplyDeleter {
+ const bool m_bOwning = true;
+ consteval ReplyDeleter(bool bOwning = true) : m_bOwning{bOwning} {}
template <typename T>
void operator()(T* ptr) const {
- free(const_cast<std::remove_const_t<T>*>(ptr));
+ if (m_bOwning)
+ free(const_cast<std::remove_const_t<T>*>(ptr));
}
};
template <typename T>
using Reply = std::unique_ptr<T, ReplyDeleter>;
+
+ template <typename Cookie_RetType, typename Reply_RetType, typename XcbConn=xcb_connection_t*, typename... Args>
+ class XcbFetch {
+ using cookie_f_ptr_t = Cookie_RetType (*)(XcbConn, Args...);
+ using reply_f_ptr_t = Reply_RetType* (*)(XcbConn, Cookie_RetType, xcb_generic_error_t**);
+
+ const cookie_f_ptr_t m_cookieFunc;
+ const reply_f_ptr_t m_replyFunc;
+
+ public:
+ consteval XcbFetch(cookie_f_ptr_t cookieFunc, reply_f_ptr_t replyFunc) : m_cookieFunc{cookieFunc}, m_replyFunc{replyFunc} {}
+
+ inline Reply<Reply_RetType> operator()(XcbConn conn, auto... args) { //have to use auto for argsTwo, since otherwise there'd be a type deduction conflict
+ return Reply<Reply_RetType> { m_replyFunc(conn, m_cookieFunc(conn, args...), nullptr) };
+ }
+ };
+
+ template <typename CookieType>
+ concept CacheableCookie = std::is_same<CookieType, xcb_get_geometry_cookie_t>::value
+ || std::is_same<CookieType, xcb_query_tree_cookie_t>::value;
+
+ template <CacheableCookie Cookie_RetType, typename Reply_RetType>
+ class XcbFetch<Cookie_RetType, Reply_RetType, xcb_connection_t*, xcb_window_t> {
+ using cookie_f_ptr_t = Cookie_RetType (*)(xcb_connection_t*, xcb_window_t);
+ using reply_f_ptr_t = Reply_RetType* (*)(xcb_connection_t*, Cookie_RetType, xcb_generic_error_t**);
+
+ const cookie_f_ptr_t m_cookieFunc;
+ const reply_f_ptr_t m_replyFunc;
+
+ inline Reply<Reply_RetType> getCachedReply(xcb_connection_t* connection) {
+ if (std::get<Reply_RetType*>(g_cache.cached_replies) == nullptr) {
+ std::get<Reply_RetType*>(g_cache.cached_replies) = m_replyFunc(connection, std::get<Cookie_RetType>(g_cache.cached_cookies), nullptr);
+ }
+ return Reply<Reply_RetType>{std::get<Reply_RetType*>(g_cache.cached_replies), ReplyDeleter{false}}; // return 'non-owning' unique_ptr
+ }
+
+ public:
+ consteval XcbFetch(cookie_f_ptr_t cookieFunc, reply_f_ptr_t replyFunc) : m_cookieFunc{cookieFunc}, m_replyFunc{replyFunc} {}
+
+ inline Reply<Reply_RetType> operator()(xcb_connection_t* conn, xcb_window_t window) {
+ const bool tryCached = pthread_equal(g_cache_tid, pthread_self())
+ && g_cache.window == window;
+ if (!tryCached) [[unlikely]]
+ return Reply<Reply_RetType> { m_replyFunc(conn, m_cookieFunc(conn, window), nullptr) };
+
+ auto ret = getCachedReply(conn);
+ #if !defined(NDEBUG) || NDEBUG == 0
+ if (!ret)
+ fprintf(stderr, "[Gamescope WSI] getCachedReply() failed.\n");
+ #endif
+ return ret;
+ }
+ };
+
static std::optional<xcb_atom_t> getAtom(xcb_connection_t* connection, std::string_view name) {
- xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, false, name.length(), name.data());
- auto reply = Reply<xcb_intern_atom_reply_t>{ xcb_intern_atom_reply(connection, cookie, nullptr) };
+ auto reply = XcbFetch{xcb_intern_atom, xcb_intern_atom_reply}(connection, false, name.length(), name.data());
if (!reply) {
fprintf(stderr, "[Gamescope WSI] Failed to get xcb atom.\n");
return std::nullopt;
@@ -34,8 +118,7 @@ namespace xcb {
xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;
- xcb_get_property_cookie_t cookie = xcb_get_property(connection, false, screen->root, atom, XCB_ATOM_CARDINAL, 0, sizeof(T) / sizeof(uint32_t));
- auto reply = Reply<xcb_get_property_reply_t>{ xcb_get_property_reply(connection, cookie, nullptr) };
+ auto reply = XcbFetch{xcb_get_property, xcb_get_property_reply}(connection, false, screen->root, atom, XCB_ATOM_CARDINAL, 0, sizeof(T) / sizeof(uint32_t));
if (!reply) {
fprintf(stderr, "[Gamescope WSI] Failed to read T root window property.\n");
return std::nullopt;
@@ -61,8 +144,7 @@ namespace xcb {
static std::optional<xcb_window_t> getToplevelWindow(xcb_connection_t* connection, xcb_window_t window) {
for (;;) {
- xcb_query_tree_cookie_t cookie = xcb_query_tree(connection, window);
- auto reply = Reply<xcb_query_tree_reply_t>{ xcb_query_tree_reply(connection, cookie, nullptr) };
+ auto reply = XcbFetch{xcb_query_tree, xcb_query_tree_reply}(connection, window);
if (!reply) {
fprintf(stderr, "[Gamescope WSI] getToplevelWindow: xcb_query_tree failed for window 0x%x.\n", window);
@@ -77,8 +159,7 @@ namespace xcb {
}
static std::optional<VkRect2D> getWindowRect(xcb_connection_t* connection, xcb_window_t window) {
- xcb_get_geometry_cookie_t cookie = xcb_get_geometry(connection, window);
- auto reply = Reply<xcb_get_geometry_reply_t>{ xcb_get_geometry_reply(connection, cookie, nullptr) };
+ auto reply = XcbFetch{xcb_get_geometry, xcb_get_geometry_reply}(connection, window);
if (!reply) {
fprintf(stderr, "[Gamescope WSI] getWindowRect: xcb_get_geometry failed for window 0x%x.\n", window);
return std::nullopt;
@@ -112,8 +193,7 @@ namespace xcb {
static std::optional<VkExtent2D> getLargestObscuringChildWindowSize(xcb_connection_t* connection, xcb_window_t window) {
VkExtent2D largestExtent = {};
- xcb_query_tree_cookie_t cookie = xcb_query_tree(connection, window);
- auto reply = Reply<xcb_query_tree_reply_t>{ xcb_query_tree_reply(connection, cookie, nullptr) };
+ auto reply = XcbFetch{xcb_query_tree, xcb_query_tree_reply}(connection, window);
if (!reply) {
fprintf(stderr, "[Gamescope WSI] getLargestObscuringWindowSize: xcb_query_tree failed for window 0x%x.\n", window);
@@ -130,8 +210,7 @@ namespace xcb {
for (uint32_t i = 0; i < reply->children_len; i++) {
xcb_window_t child = children[i];
- xcb_get_window_attributes_cookie_t attributeCookie = xcb_get_window_attributes(connection, child);
- auto attributeReply = Reply<xcb_get_window_attributes_reply_t>{ xcb_get_window_attributes_reply(connection, attributeCookie, nullptr) };
+ auto attributeReply = XcbFetch{xcb_get_window_attributes, xcb_get_window_attributes_reply}(connection, child);
const bool obscuring =
attributeReply &&
From 1b59621f4de5c05096d1f279cba2e04264124154 Mon Sep 17 00:00:00 2001
From: sharkautarch <128002472+sharkautarch@users.noreply.github.com>
Date: Tue, 18 Jun 2024 22:21:23 -0400
Subject: [PATCH 2/2] WSI: prefetcher: fix issue w/ attempting to prefetch xcb
stuff for pure wayland surfaces
---
layer/VkLayer_FROG_gamescope_wsi.cpp | 2 +-
layer/xcb_helpers.hpp | 9 ++++++++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/layer/VkLayer_FROG_gamescope_wsi.cpp b/layer/VkLayer_FROG_gamescope_wsi.cpp
index f26819a60..ce011dcd7 100644
--- a/layer/VkLayer_FROG_gamescope_wsi.cpp
+++ b/layer/VkLayer_FROG_gamescope_wsi.cpp
@@ -1234,7 +1234,7 @@ namespace GamescopeWSILayer {
continue;
}
- xcb::Prefetcher prefetcher(gamescopeSurface->connection, gamescopeSurface->window);
+ auto prefetcher = xcb::Prefetcher::GetPrefetcherIf(!gamescopeSurface->isWayland(), gamescopeSurface->connection, gamescopeSurface->window);
const bool canBypass = gamescopeSurface->canBypassXWayland();
if (canBypass != gamescopeSwapchain->isBypassingXWayland)
UpdateSwapchainResult(canBypass ? VK_SUBOPTIMAL_KHR : VK_ERROR_OUT_OF_DATE_KHR);
diff --git a/layer/xcb_helpers.hpp b/layer/xcb_helpers.hpp
index 72d0ec092..f26aef38b 100644
--- a/layer/xcb_helpers.hpp
+++ b/layer/xcb_helpers.hpp
@@ -16,6 +16,13 @@ namespace xcb {
//Note: this class is currently only meant to be used within GamescopeWSILayer::VkDeviceOverrides::QueuePresentKHR:
struct Prefetcher {
+ static std::optional<Prefetcher> GetPrefetcherIf(bool bCond, xcb_connection_t* connection, const xcb_window_t window) {
+ if (bCond)
+ return std::optional<Prefetcher>(std::in_place_t{}, connection, window);
+
+ return std::nullopt;
+ }
+
explicit Prefetcher(xcb_connection_t* connection, const xcb_window_t window) {
g_cache = {
.window = window,
@@ -90,7 +97,7 @@ namespace xcb {
inline Reply<Reply_RetType> operator()(xcb_connection_t* conn, xcb_window_t window) {
const bool tryCached = pthread_equal(g_cache_tid, pthread_self())
&& g_cache.window == window;
- if (!tryCached) [[unlikely]]
+ if (!tryCached)
return Reply<Reply_RetType> { m_replyFunc(conn, m_cookieFunc(conn, window), nullptr) };
auto ret = getCachedReply(conn);

View File

@ -0,0 +1,215 @@
From d81aad780c67e8737ceee60ca58742dc8df72648 Mon Sep 17 00:00:00 2001
From: sharkautarch <128002472+sharkautarch@users.noreply.github.com>
Date: Sun, 23 Jun 2024 10:53:50 -0400
Subject: [PATCH] use latest upstream wlroots
---
.gitmodules | 7 ++++---
src/rendervulkan.cpp | 37 +++++++++++++++++--------------------
src/wlserver.cpp | 18 +++++++++++-------
src/wlserver.hpp | 14 ++++++++++++--
subprojects/wlroots | 2 +-
5 files changed, 45 insertions(+), 33 deletions(-)
diff --git a/.gitmodules b/.gitmodules
index ec7d4e4..34e81f5 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "subprojects/wlroots"]
- path = subprojects/wlroots
- url = https://github.com/Joshua-Ashton/wlroots.git
[submodule "subprojects/libliftoff"]
path = subprojects/libliftoff
url = https://gitlab.freedesktop.org/emersion/libliftoff.git
@@ -19,3 +16,7 @@
[submodule "thirdparty/SPIRV-Headers"]
path = thirdparty/SPIRV-Headers
url = https://github.com/KhronosGroup/SPIRV-Headers/
+[submodule "subprojects/wlroots"]
+ path = subprojects/wlroots
+ url = https://gitlab.freedesktop.org/wlroots/wlroots.git
+ branch = master
\ No newline at end of file
diff --git a/src/rendervulkan.cpp b/src/rendervulkan.cpp
index 711beb5..0f00b68 100644
--- a/src/rendervulkan.cpp
+++ b/src/rendervulkan.cpp
@@ -128,7 +128,7 @@ static bool Contains( const std::span<const T> x, T value )
}
static std::map< VkFormat, std::map< uint64_t, VkDrmFormatModifierPropertiesEXT > > DRMModifierProps = {};
-static std::vector< uint32_t > sampledShmFormats{};
+static struct wlr_drm_format_set sampledShmFormats = {};
static struct wlr_drm_format_set sampledDRMFormats = {};
static LogScope vk_log("vulkan");
@@ -2588,8 +2588,12 @@ bool vulkan_init_format(VkFormat format, uint32_t drmFormat)
return false;
}
- if ( std::find( sampledShmFormats.begin(), sampledShmFormats.end(), drmFormat ) == sampledShmFormats.end() )
+ if (sampledShmFormats.formats == nullptr
sampledShmFormats.push_back( drmFormat );
+ || std::none_of( sampledShmFormats.formats, sampledShmFormats.formats+sampledShmFormats.len, [=](wlr_drm_format format) { return format.format == drmFormat;} ) )
+ {
+ wlr_drm_format_set_add( &sampledShmFormats, drmFormat, DRM_FORMAT_MOD_INVALID );
+ }
if ( !g_device.supportsModifiers() )
{
@@ -3990,21 +3994,16 @@ static const struct wlr_texture_impl texture_impl = {
.destroy = texture_destroy,
};
-static uint32_t renderer_get_render_buffer_caps( struct wlr_renderer *renderer )
+static const struct wlr_drm_format_set *renderer_get_texture_formats(struct wlr_renderer *wlr_renderer, uint32_t buffer_caps) {
{
+ if (buffer_caps & WLR_BUFFER_CAP_DMABUF) {
return 0;
-}
-
-static const uint32_t *renderer_get_shm_texture_formats( struct wlr_renderer *wlr_renderer, size_t *len
- )
-{
- *len = sampledShmFormats.size();
- return sampledShmFormats.data();
-}
-
-static const struct wlr_drm_format_set *renderer_get_dmabuf_texture_formats( struct wlr_renderer *wlr_renderer )
-{
- return &sampledDRMFormats;
+ return &sampledDRMFormats;
+ } else if (buffer_caps & WLR_BUFFER_CAP_DATA_PTR) {
+ return &sampledShmFormats;
+ } else {
+ return nullptr;
+ }
}
static int renderer_get_drm_fd( struct wlr_renderer *wlr_renderer )
@@ -4028,18 +4027,17 @@ static struct wlr_render_pass *renderer_begin_buffer_pass( struct wlr_renderer *
}
static const struct wlr_renderer_impl renderer_impl = {
- .get_shm_texture_formats = renderer_get_shm_texture_formats,
- .get_dmabuf_texture_formats = renderer_get_dmabuf_texture_formats,
+ .get_texture_formats = renderer_get_texture_formats,
.get_drm_fd = renderer_get_drm_fd,
- .get_render_buffer_caps = renderer_get_render_buffer_caps,
.texture_from_buffer = renderer_texture_from_buffer,
.begin_buffer_pass = renderer_begin_buffer_pass,
};
struct wlr_renderer *vulkan_renderer_create( void )
{
+ static constexpr uint32_t render_buffer_caps = WLR_BUFFER_CAP_DMABUF | WLR_BUFFER_CAP_DATA_PTR | WLR_BUFFER_CAP_SHM;
VulkanRenderer_t *renderer = new VulkanRenderer_t();
- wlr_renderer_init(&renderer->base, &renderer_impl);
+ wlr_renderer_init(&renderer->base, &renderer_impl, render_buffer_caps);
return &renderer->base;
}
diff --git a/src/wlserver.cpp b/src/wlserver.cpp
index 776e014..2964ade 100644
--- a/src/wlserver.cpp
+++ b/src/wlserver.cpp
@@ -25,7 +25,6 @@
#include <wlr/backend/multi.h>
#include <wlr/interfaces/wlr_keyboard.h>
#include <wlr/render/wlr_renderer.h>
-#include <wlr/render/timeline.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_pointer.h>
@@ -37,7 +36,7 @@
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/types/wlr_pointer_constraints_v1.h>
-#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
+#include <wlr/render/drm_syncobj.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/util/region.h>
#include "wlr_end.hpp"
@@ -70,6 +69,11 @@
#include <list>
#include <set>
+extern "C" {
+ __attribute__((visibility("hidden"))) struct wlr_linux_drm_syncobj_surface_v1_state * wlr_linux_drm_syncobj_v1_get_surface_state(struct wlr_surface *wlr_surface);
+ __attribute__((visibility("hidden"))) struct wlr_linux_drm_syncobj_manager_v1 *wlr_linux_drm_syncobj_manager_v1_create(struct wl_display *display, uint32_t version, int drm_fd);
+}
+
static LogScope wl_log("wlserver");
bool pending_gesture_x = false;
bool pending_gesture_y = false;
@@ -124,7 +128,7 @@ void GamescopeTimelinePoint::Release()
//fprintf( stderr, "Release: %lu\n", ulPoint );
drmSyncobjTimelineSignal( pTimeline->drm_fd, &pTimeline->handle, &ulPoint, 1 );
- wlr_render_timeline_unref( pTimeline );
+ wlr_drm_syncobj_timeline_unref( pTimeline );
}
//
@@ -136,7 +140,7 @@ void GamescopeTimelinePoint::Release()
static std::optional<GamescopeAcquireTimelineState> TimelinePointToEventFd( const std::optional<GamescopeTimelinePoint>& oPoint )
{
- if (!oPoint)
+ if (!oPoint || !(oPoint->pTimeline) )
return std::nullopt;
uint64_t uSignalledPoint = 0;
@@ -187,8 +191,8 @@ std::optional<ResListEntry_t> PrepareCommit( struct wlr_surface *surf, struct wl
const auto& pFeedback = wlserver_surface_swapchain_feedback(surf);
- wlr_linux_drm_syncobj_surface_v1_state *pSyncState =
- wlr_linux_drm_syncobj_v1_get_surface_state( wlserver.wlr.drm_syncobj_manager_v1, surf );
+ struct wlr_linux_drm_syncobj_surface_v1_state *pSyncState =
+ wlr_linux_drm_syncobj_v1_get_surface_state( surf );
auto oAcquirePoint = !pSyncState ? std::nullopt : std::optional<GamescopeTimelinePoint> {
std::in_place_t{},
@@ -205,7 +209,7 @@ std::optional<ResListEntry_t> PrepareCommit( struct wlr_surface *surf, struct wl
}
oReleasePoint.emplace(
- wlr_render_timeline_ref( pSyncState->release_timeline ),
+ wlr_drm_syncobj_timeline_ref( pSyncState->release_timeline ),
pSyncState->release_point
);
}
diff --git a/src/wlserver.hpp b/src/wlserver.hpp
index 07675fe..16e6665 100644
--- a/src/wlserver.hpp
+++ b/src/wlserver.hpp
@@ -2,6 +2,16 @@
#pragma once
+//two function prototypes from wlr/types/wlr_linux_drm_syncobj_v1.h would cause linker errors
+//due to c++ vs c linkage weirdness
+//need to ignore the prototypes from the header, and instead use versions w/ 'extern "C"' :
+#define wlr_linux_drm_syncobj_v1_get_surface_state wlr_linux_drm_syncobj_v1_get_surface_state_C_LINKAGE
+#define wlr_linux_drm_syncobj_manager_v1_create wlr_linux_drm_syncobj_manager_v1_create_C_LINKAGE
+#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
+
+#undef wlr_linux_drm_syncobj_v1_get_surface_state
+#undef wlr_linux_drm_syncobj_manager_v1_create
+
#include <wayland-server-core.h>
#include <atomic>
#include <vector>
@@ -42,8 +52,8 @@ struct wlserver_vk_swapchain_feedback
struct GamescopeTimelinePoint
{
- struct wlr_render_timeline *pTimeline = nullptr;
- uint64_t ulPoint = 0;
+ decltype(wlr_linux_drm_syncobj_surface_v1_state::acquire_timeline) pTimeline = nullptr;
+ decltype(wlr_linux_drm_syncobj_surface_v1_state::acquire_point) ulPoint = 0;
void Release();
};

View File

@ -6,7 +6,7 @@
Name: gamescope
Version: 100.%{gamescope_tag}
Release: 10.bazzite
Release: 11.bazzite
Summary: Micro-compositor for video games on Wayland
License: BSD
@ -27,6 +27,10 @@ Patch3: drm-Separate-BOE-and-SDC-OLED-Deck-panel-rates.patch
Patch4: revert-299bc34.patch
# https://github.com/ValveSoftware/gamescope/pull/1335
Patch5: 1335.patch
# https://github.com/ValveSoftware/gamescope/pull/1231
Patch6: 1231.patch
# https://github.com/ValveSoftware/gamescope/pull/1394
Patch7: 1394.patch
BuildRequires: meson >= 0.54.0
BuildRequires: ninja-build
@ -100,6 +104,7 @@ Summary: libs for %{name}
%prep
git clone --depth 1 --branch %{gamescope_tag} %{url}.git
cd gamescope
%autopatch -p1
git submodule update --init --recursive
mkdir -p pkgconfig
cp %{SOURCE0} pkgconfig/stb.pc
@ -107,8 +112,6 @@ cp %{SOURCE0} pkgconfig/stb.pc
# Replace spirv-headers include with the system directory
sed -i 's^../thirdparty/SPIRV-Headers/include/spirv/^/usr/include/spirv/^' src/meson.build
%autopatch -p1
%build
cd gamescope
export PKG_CONFIG_PATH=pkgconfig