bazzite/spec_files/gamescope/upstream.patch
2024-08-03 22:25:18 -07:00

1202 lines
42 KiB
Diff

From 7f5c30200408ea7207d077ea30d8f1068cf48053 Mon Sep 17 00:00:00 2001
From: Joshua Ashton <joshua@froggi.es>
Date: Wed, 31 Jul 2024 03:32:41 +0100
Subject: [PATCH 1/8] wlserver: Filter wp_linux_drm_syncobj_manager_v1 if
explicit sync is disabled by convar
---
src/wlserver.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/wlserver.cpp b/src/wlserver.cpp
index 79b9c5c..c4bfb25 100644
--- a/src/wlserver.cpp
+++ b/src/wlserver.cpp
@@ -72,6 +72,10 @@
static LogScope wl_log("wlserver");
+using namespace std::literals;
+
+extern gamescope::ConVar<bool> cv_drm_debug_disable_explicit_sync;
+
//#define GAMESCOPE_SWAPCHAIN_DEBUG
struct wlserver_t wlserver = {
@@ -1426,6 +1430,10 @@ void wlserver_set_output_info( const wlserver_output_info *info )
static bool filter_global(const struct wl_client *client, const struct wl_global *global, void *data)
{
const struct wl_interface *iface = wl_global_get_interface(global);
+
+ if ( cv_drm_debug_disable_explicit_sync && iface->name == "wp_linux_drm_syncobj_manager_v1"sv )
+ return false;
+
if (strcmp(iface->name, wl_output_interface.name) != 0)
return true;
--
2.45.2
From cbf274b05b446a81d94c89d1137a808bcb89791d Mon Sep 17 00:00:00 2001
From: Joshua Ashton <joshua@froggi.es>
Date: Wed, 31 Jul 2024 03:40:56 +0100
Subject: [PATCH 2/8] wlserver: Add cv_drm_debug_syncobj_force_wait_on_commit
---
src/wlserver.cpp | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/wlserver.cpp b/src/wlserver.cpp
index c4bfb25..c69f068 100644
--- a/src/wlserver.cpp
+++ b/src/wlserver.cpp
@@ -180,6 +180,8 @@ static std::optional<GamescopeAcquireTimelineState> TimelinePointToEventFd( cons
}
}
+gamescope::ConVar<bool> cv_drm_debug_syncobj_force_wait_on_commit( "drm_debug_syncobj_force_wait_on_commit", false );
+
std::optional<ResListEntry_t> PrepareCommit( struct wlr_surface *surf, struct wlr_buffer *buf )
{
auto wl_surf = get_wl_surface_info( surf );
@@ -194,6 +196,17 @@ std::optional<ResListEntry_t> PrepareCommit( struct wlr_surface *surf, struct wl
pSyncState->acquire_timeline,
pSyncState->acquire_point
};
+
+ if ( pSyncState && cv_drm_debug_syncobj_force_wait_on_commit )
+ {
+ int ret = drmSyncobjTimelineWait( pSyncState->acquire_timeline->drm_fd, &pSyncState->acquire_timeline->handle, &pSyncState->acquire_point, 1, INT64_MAX, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL, nullptr );
+ if ( ret )
+ {
+ wl_log.errorf( "drmSyncobjWait failed!" );
+ return std::nullopt;
+ }
+ }
+
std::optional<GamescopeAcquireTimelineState> oAcquireState = TimelinePointToEventFd( oAcquirePoint );
std::optional<GamescopeTimelinePoint> oReleasePoint;
if ( pSyncState )
--
2.45.2
From f35e1b38665fa236ed21731d9de208ee55e82c2c Mon Sep 17 00:00:00 2001
From: Joshua Ashton <joshua@froggi.es>
Date: Wed, 31 Jul 2024 04:52:49 +0100
Subject: [PATCH 3/8] wlserver, backend: Fix explicit sync release not
accounting for backend fb referencing
---
src/Backends/HeadlessBackend.cpp | 2 +-
src/Backends/OpenVRBackend.cpp | 93 +++++++++++++++++---------------
src/Backends/SDLBackend.cpp | 2 +-
src/backend.cpp | 29 ++++++++--
src/backend.h | 6 ++-
src/gamescope_shared.h | 10 ++++
src/steamcompmgr.cpp | 15 ++++--
src/wlserver.hpp | 9 ----
8 files changed, 103 insertions(+), 63 deletions(-)
diff --git a/src/Backends/HeadlessBackend.cpp b/src/Backends/HeadlessBackend.cpp
index 787abda..d65a9b3 100644
--- a/src/Backends/HeadlessBackend.cpp
+++ b/src/Backends/HeadlessBackend.cpp
@@ -178,7 +178,7 @@ namespace gamescope
virtual OwningRc<IBackendFb> ImportDmabufToBackend( wlr_buffer *pBuffer, wlr_dmabuf_attributes *pDmaBuf ) override
{
- return nullptr;
+ return new CBaseBackendFb( pBuffer );
}
virtual bool UsesModifiers() const override
diff --git a/src/Backends/OpenVRBackend.cpp b/src/Backends/OpenVRBackend.cpp
index 79b05d1..6e0fbca 100644
--- a/src/Backends/OpenVRBackend.cpp
+++ b/src/Backends/OpenVRBackend.cpp
@@ -654,55 +654,59 @@ namespace gamescope
virtual OwningRc<IBackendFb> ImportDmabufToBackend( wlr_buffer *pBuffer, wlr_dmabuf_attributes *pDmaBuf ) override
{
- if ( !UsesModifiers() )
- return nullptr;
-
- vr::DmabufAttributes_t dmabufAttributes =
+ if ( UsesModifiers() )
{
- .unWidth = uint32_t( pDmaBuf->width ),
- .unHeight = uint32_t( pDmaBuf->height ),
- .unDepth = 1,
- .unMipLevels = 1,
- .unArrayLayers = 1,
- .unSampleCount = 1,
- .unFormat = pDmaBuf->format,
- .ulModifier = pDmaBuf->modifier,
- .unPlaneCount = uint32_t( pDmaBuf->n_planes ),
- .plane =
+ vr::DmabufAttributes_t dmabufAttributes =
{
+ .unWidth = uint32_t( pDmaBuf->width ),
+ .unHeight = uint32_t( pDmaBuf->height ),
+ .unDepth = 1,
+ .unMipLevels = 1,
+ .unArrayLayers = 1,
+ .unSampleCount = 1,
+ .unFormat = pDmaBuf->format,
+ .ulModifier = pDmaBuf->modifier,
+ .unPlaneCount = uint32_t( pDmaBuf->n_planes ),
+ .plane =
{
- .unOffset = pDmaBuf->offset[0],
- .unStride = pDmaBuf->stride[0],
- .nFd = pDmaBuf->fd[0],
- },
- {
- .unOffset = pDmaBuf->offset[1],
- .unStride = pDmaBuf->stride[1],
- .nFd = pDmaBuf->fd[1],
- },
- {
- .unOffset = pDmaBuf->offset[2],
- .unStride = pDmaBuf->stride[2],
- .nFd = pDmaBuf->fd[2],
- },
- {
- .unOffset = pDmaBuf->offset[3],
- .unStride = pDmaBuf->stride[3],
- .nFd = pDmaBuf->fd[3],
- },
- }
- };
+ {
+ .unOffset = pDmaBuf->offset[0],
+ .unStride = pDmaBuf->stride[0],
+ .nFd = pDmaBuf->fd[0],
+ },
+ {
+ .unOffset = pDmaBuf->offset[1],
+ .unStride = pDmaBuf->stride[1],
+ .nFd = pDmaBuf->fd[1],
+ },
+ {
+ .unOffset = pDmaBuf->offset[2],
+ .unStride = pDmaBuf->stride[2],
+ .nFd = pDmaBuf->fd[2],
+ },
+ {
+ .unOffset = pDmaBuf->offset[3],
+ .unStride = pDmaBuf->stride[3],
+ .nFd = pDmaBuf->fd[3],
+ },
+ }
+ };
- vr::SharedTextureHandle_t ulSharedHandle = 0;
- if ( !m_pIPCResourceManager->ImportDmabuf( vr::VRApplication_Overlay, &dmabufAttributes, &ulSharedHandle ) )
- return nullptr;
- assert( ulSharedHandle != 0 );
+ vr::SharedTextureHandle_t ulSharedHandle = 0;
+ if ( !m_pIPCResourceManager->ImportDmabuf( vr::VRApplication_Overlay, &dmabufAttributes, &ulSharedHandle ) )
+ return nullptr;
+ assert( ulSharedHandle != 0 );
- // Take the first reference!
- if ( !m_pIPCResourceManager->RefResource( ulSharedHandle, nullptr ) )
- return nullptr;
+ // Take the first reference!
+ if ( !m_pIPCResourceManager->RefResource( ulSharedHandle, nullptr ) )
+ return nullptr;
- return new COpenVRFb{ this, ulSharedHandle, pBuffer };
+ return new COpenVRFb{ this, ulSharedHandle, pBuffer };
+ }
+ else
+ {
+ return new COpenVRFb{ this, 0, pBuffer };
+ }
}
virtual bool UsesModifiers() const override
@@ -1169,7 +1173,8 @@ namespace gamescope
COpenVRFb::~COpenVRFb()
{
- m_pBackend->GetIPCResourceManager()->UnrefResource( m_ulHandle );
+ if ( m_ulHandle != 0 )
+ m_pBackend->GetIPCResourceManager()->UnrefResource( m_ulHandle );
m_ulHandle = 0;
}
diff --git a/src/Backends/SDLBackend.cpp b/src/Backends/SDLBackend.cpp
index e508789..df0b356 100644
--- a/src/Backends/SDLBackend.cpp
+++ b/src/Backends/SDLBackend.cpp
@@ -397,7 +397,7 @@ namespace gamescope
OwningRc<IBackendFb> CSDLBackend::ImportDmabufToBackend( wlr_buffer *pBuffer, wlr_dmabuf_attributes *pDmaBuf )
{
- return nullptr;
+ return new CBaseBackendFb( pBuffer );
}
bool CSDLBackend::UsesModifiers() const
diff --git a/src/backend.cpp b/src/backend.cpp
index 91ad0ef..e625d8d 100644
--- a/src/backend.cpp
+++ b/src/backend.cpp
@@ -75,16 +75,37 @@ namespace gamescope
uint32_t CBaseBackendFb::DecRef()
{
wlr_buffer *pClientBuffer = m_pClientBuffer;
+
+ std::optional<GamescopeTimelinePoint> oPoint = std::move( m_oPoint );
+ m_oPoint = std::nullopt;
+
uint32_t uRefCount = IBackendFb::DecRef();
- if ( pClientBuffer && !uRefCount )
+ if ( uRefCount )
{
- wlserver_lock();
- wlr_buffer_unlock( pClientBuffer );
- wlserver_unlock();
+ // TODO: The pulling out and re-assignment could be made better here
+ // Perhaps if we had a better way of knowing if the object was destroyed.
+ m_oPoint = oPoint;
+ }
+ else
+ {
+ if ( pClientBuffer || oPoint )
+ {
+ wlserver_lock();
+ if ( pClientBuffer )
+ wlr_buffer_unlock( pClientBuffer );
+ if ( oPoint )
+ oPoint->Release();
+ wlserver_unlock();
+ }
}
return uRefCount;
}
+ void CBaseBackendFb::SetReleasePoint( const GamescopeTimelinePoint &point )
+ {
+ m_oPoint = point;
+ }
+
/////////////////
// CBaseBackend
/////////////////
diff --git a/src/backend.h b/src/backend.h
index 85783c9..6c86349 100644
--- a/src/backend.h
+++ b/src/backend.h
@@ -145,7 +145,8 @@ namespace gamescope
class IBackendFb : public IRcObject
{
- // Dummy
+ public:
+ virtual void SetReleasePoint( const GamescopeTimelinePoint &point ) = 0;
};
class CBaseBackendFb : public IBackendFb
@@ -157,8 +158,11 @@ namespace gamescope
uint32_t IncRef() override;
uint32_t DecRef() override;
+ void SetReleasePoint( const GamescopeTimelinePoint &point ) override;
+
private:
wlr_buffer *m_pClientBuffer = nullptr;
+ std::optional<GamescopeTimelinePoint> m_oPoint;
};
class IBackend
diff --git a/src/gamescope_shared.h b/src/gamescope_shared.h
index 60e3829..863b03f 100644
--- a/src/gamescope_shared.h
+++ b/src/gamescope_shared.h
@@ -1,5 +1,7 @@
#pragma once
+#include <cstdint>
+
namespace gamescope
{
class BackendBlob;
@@ -62,6 +64,14 @@ enum GamescopePanelOrientation
GAMESCOPE_PANEL_ORIENTATION_AUTO,
};
+struct GamescopeTimelinePoint
+{
+ struct wlr_drm_syncobj_timeline *pTimeline = nullptr;
+ uint64_t ulPoint = 0;
+
+ void Release();
+};
+
// Disable partial composition for now until we get
// composite priorities working in libliftoff + also
// use the proper libliftoff composite plane system.
diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp
index 4216555..eef2f45 100644
--- a/src/steamcompmgr.cpp
+++ b/src/steamcompmgr.cpp
@@ -1207,7 +1207,7 @@ static steamcompmgr_win_t * find_win( xwayland_ctx_t *ctx, struct wlr_surface *s
static gamescope::CBufferMemoizer s_BufferMemos;
static gamescope::Rc<commit_t>
-import_commit ( steamcompmgr_win_t *w, struct wlr_surface *surf, struct wlr_buffer *buf, bool async, std::shared_ptr<wlserver_vk_swapchain_feedback> swapchain_feedback, std::vector<struct wl_resource*> presentation_feedbacks, std::optional<uint32_t> present_id, uint64_t desired_present_time, bool fifo )
+import_commit ( steamcompmgr_win_t *w, struct wlr_surface *surf, struct wlr_buffer *buf, bool async, std::shared_ptr<wlserver_vk_swapchain_feedback> swapchain_feedback, std::vector<struct wl_resource*> presentation_feedbacks, std::optional<uint32_t> present_id, uint64_t desired_present_time, bool fifo, std::optional<GamescopeTimelinePoint> oReleasePoint )
{
gamescope::Rc<commit_t> commit = new commit_t;
@@ -1225,6 +1225,13 @@ import_commit ( steamcompmgr_win_t *w, struct wlr_surface *surf, struct wlr_buff
if ( gamescope::OwningRc<CVulkanTexture> pTexture = s_BufferMemos.LookupVulkanTexture( buf ) )
{
+ if ( oReleasePoint )
+ {
+ if ( gamescope::IBackendFb *pBackendFb = pTexture->GetBackendFb() )
+ {
+ pBackendFb->SetReleasePoint( *oReleasePoint );
+ }
+ }
// Going from OwningRc -> Rc now.
commit->vulkanTex = pTexture;
return commit;
@@ -1236,6 +1243,9 @@ import_commit ( steamcompmgr_win_t *w, struct wlr_surface *surf, struct wlr_buff
{
pBackendFb = GetBackend()->ImportDmabufToBackend( buf, &dmabuf );
}
+
+ if ( pBackendFb && oReleasePoint )
+ pBackendFb->SetReleasePoint( *oReleasePoint );
gamescope::OwningRc<CVulkanTexture> pOwnedTexture = vulkan_create_texture_from_wlr_buffer( buf, std::move( pBackendFb ) );
commit->vulkanTex = pOwnedTexture;
@@ -6261,7 +6271,7 @@ void update_wayland_res(CommitDoneList_t *doneCommits, steamcompmgr_win_t *w, Re
return;
}
- gamescope::Rc<commit_t> newCommit = import_commit( w, reslistentry.surf, buf, reslistentry.async, std::move(reslistentry.feedback), std::move(reslistentry.presentation_feedbacks), reslistentry.present_id, reslistentry.desired_present_time, reslistentry.fifo );
+ gamescope::Rc<commit_t> newCommit = import_commit( w, reslistentry.surf, buf, reslistentry.async, std::move(reslistentry.feedback), std::move(reslistentry.presentation_feedbacks), reslistentry.present_id, reslistentry.desired_present_time, reslistentry.fifo, std::move( reslistentry.oReleasePoint ) );
int fence = -1;
if ( newCommit != nullptr )
@@ -6299,7 +6309,6 @@ void update_wayland_res(CommitDoneList_t *doneCommits, steamcompmgr_win_t *w, Re
gpuvis_trace_printf( "pushing wait for commit %lu win %lx", newCommit->commitID, w->type == steamcompmgr_win_type_t::XWAYLAND ? w->xwayland().id : 0 );
{
newCommit->SetFence( fence, mango_nudge, doneCommits );
- newCommit->SetReleasePoint( reslistentry.oReleasePoint );
if ( bKnownReady )
newCommit->Signal();
else
diff --git a/src/wlserver.hpp b/src/wlserver.hpp
index ec7809c..7a8c155 100644
--- a/src/wlserver.hpp
+++ b/src/wlserver.hpp
@@ -40,15 +40,6 @@ struct wlserver_vk_swapchain_feedback
std::shared_ptr<gamescope::BackendBlob> hdr_metadata_blob;
};
-
-struct GamescopeTimelinePoint
-{
- struct wlr_drm_syncobj_timeline *pTimeline = nullptr;
- uint64_t ulPoint = 0;
-
- void Release();
-};
-
struct GamescopeAcquireTimelineState
{
int32_t nEventFd = -1;
--
2.45.2
From 8e62848d76fac3cb3316a39bfb182fe03980c141 Mon Sep 17 00:00:00 2001
From: Joshua Ashton <joshua@froggi.es>
Date: Fri, 2 Aug 2024 03:51:18 +0100
Subject: [PATCH 4/8] log: Create convars to control log level
---
src/Apps/gamescopereaper.cpp | 1 +
src/Backends/DRMBackend.cpp | 17 +++--
src/Backends/WaylandBackend.cpp | 2 +
src/InputEmulation.cpp | 6 +-
src/convar.h | 4 +-
src/edid.cpp | 2 +-
src/log.cpp | 112 +++++++++++++++++++++++++-------
src/log.hpp | 44 ++++++++-----
src/meson.build | 17 +++--
src/rendervulkan.cpp | 2 +-
src/steamcompmgr.cpp | 4 +-
src/wlserver.cpp | 2 +-
12 files changed, 149 insertions(+), 64 deletions(-)
diff --git a/src/Apps/gamescopereaper.cpp b/src/Apps/gamescopereaper.cpp
index 9e74937..0fd2c36 100644
--- a/src/Apps/gamescopereaper.cpp
+++ b/src/Apps/gamescopereaper.cpp
@@ -3,6 +3,7 @@
#include <cassert>
#include <cstdlib>
+#include <cstring>
#include <getopt.h>
#include <pthread.h>
diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp
index 24bbbf2..72bd1ec 100644
--- a/src/Backends/DRMBackend.cpp
+++ b/src/Backends/DRMBackend.cpp
@@ -539,8 +539,7 @@ extern GamescopePanelOrientation g_DesiredInternalOrientation;
extern bool g_bForceDisableColorMgmt;
-static LogScope drm_log("drm");
-static LogScope drm_verbose_log("drm", LOG_SILENT);
+static LogScope drm_log( "drm" );
static std::unordered_map< std::string, std::string > pnps = {};
@@ -700,7 +699,7 @@ static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsi
// TODO: get the fbids_queued instance from data if we ever have more than one in flight
- drm_verbose_log.debugf("page_flip_handler %" PRIu64, pCtx->ulPendingFlipCount);
+ drm_log.debugf("page_flip_handler %" PRIu64, pCtx->ulPendingFlipCount);
gpuvis_trace_printf("page_flip_handler %" PRIu64, pCtx->ulPendingFlipCount);
{
@@ -1423,7 +1422,7 @@ gamescope::OwningRc<gamescope::IBackendFb> drm_fbid_from_dmabuf( struct drm_t *d
if ( !wlr_drm_format_set_has( &drm->formats, dma_buf->format, dma_buf->modifier ) )
{
- drm_verbose_log.errorf( "Cannot import FB to DRM: format 0x%" PRIX32 " and modifier 0x%" PRIX64 " not supported for scan-out", dma_buf->format, dma_buf->modifier );
+ drm_log.errorf( "Cannot import FB to DRM: format 0x%" PRIX32 " and modifier 0x%" PRIX64 " not supported for scan-out", dma_buf->format, dma_buf->modifier );
return nullptr;
}
@@ -1463,7 +1462,7 @@ gamescope::OwningRc<gamescope::IBackendFb> drm_fbid_from_dmabuf( struct drm_t *d
}
}
- drm_verbose_log.debugf("make fbid %u", fb_id);
+ drm_log.debugf("make fbid %u", fb_id);
pBackendFb = new gamescope::CDRMFb( fb_id, buf );
@@ -2369,7 +2368,7 @@ drm_prepare_liftoff( struct drm_t *drm, const struct FrameInfo_t *frameInfo, boo
if ( pDrmFb == nullptr )
{
- drm_verbose_log.errorf("drm_prepare_liftoff: layer %d has no FB", i );
+ drm_log.debugf("drm_prepare_liftoff: layer %d has no FB", i );
return -EINVAL;
}
@@ -2575,9 +2574,9 @@ drm_prepare_liftoff( struct drm_t *drm, const struct FrameInfo_t *frameInfo, boo
}
if ( ret == 0 )
- drm_verbose_log.debugf( "can drm present %i layers", frameInfo->layerCount );
+ drm_log.debugf( "can drm present %i layers", frameInfo->layerCount );
else
- drm_verbose_log.debugf( "can NOT drm present %i layers", frameInfo->layerCount );
+ drm_log.debugf( "can NOT drm present %i layers", frameInfo->layerCount );
return ret;
}
@@ -3654,7 +3653,7 @@ namespace gamescope
m_uNextPresentCtx = ( m_uNextPresentCtx + 1 ) % 3;
m_PresentCtxs[uCurrentPresentCtx].ulPendingFlipCount = m_PresentFeedback.m_uQueuedPresents;
- drm_verbose_log.debugf("flip commit %" PRIu64, (uint64_t)m_PresentFeedback.m_uQueuedPresents);
+ drm_log.debugf("flip commit %" PRIu64, (uint64_t)m_PresentFeedback.m_uQueuedPresents);
gpuvis_trace_printf( "flip commit %" PRIu64, (uint64_t)m_PresentFeedback.m_uQueuedPresents );
ret = drmModeAtomicCommit(drm->fd, drm->req, drm->flags, &m_PresentCtxs[uCurrentPresentCtx] );
diff --git a/src/Backends/WaylandBackend.cpp b/src/Backends/WaylandBackend.cpp
index cc76f62..bac1d7d 100644
--- a/src/Backends/WaylandBackend.cpp
+++ b/src/Backends/WaylandBackend.cpp
@@ -790,6 +790,8 @@ namespace gamescope
assert( m_pHostBuffer );
assert( m_pHostBuffer == pBuffer );
+ xdg_log.debugf( "buffer_release: %p", pBuffer );
+
OnCompositorRelease();
}
diff --git a/src/InputEmulation.cpp b/src/InputEmulation.cpp
index 7a26868..460d0b4 100644
--- a/src/InputEmulation.cpp
+++ b/src/InputEmulation.cpp
@@ -1,12 +1,14 @@
#if HAVE_LIBEIS
#include <libeis.h>
-#include <stdio.h>
+
+#include <cstdio>
+#include <cstring>
#include "InputEmulation.h"
#include "wlserver.hpp"
-static LogScope gamescope_ei("gamescope-ei");
+static LogScope gamescope_ei("gamescope_ei");
namespace gamescope
{
diff --git a/src/convar.h b/src/convar.h
index f2a0485..0bcdcff 100644
--- a/src/convar.h
+++ b/src/convar.h
@@ -129,7 +129,7 @@ namespace gamescope
template <typename T>
class ConVar : public ConCommand
{
- using ConVarCallbackFunc = std::function<void()>;
+ using ConVarCallbackFunc = std::function<void(ConVar<T> &)>;
public:
ConVar( std::string_view pszName, T defaultValue = T{}, std::string_view pszDescription = "", ConVarCallbackFunc func = nullptr, bool bRunCallbackAtStartup = false )
: ConCommand( pszName, pszDescription, [this]( std::span<std::string_view> pArgs ){ this->InvokeFunc( pArgs ); } )
@@ -160,7 +160,7 @@ namespace gamescope
if ( !m_bInCallback && m_Callback )
{
m_bInCallback = true;
- m_Callback();
+ m_Callback( *this );
m_bInCallback = false;
}
}
diff --git a/src/edid.cpp b/src/edid.cpp
index 03e5de1..6c01813 100644
--- a/src/edid.cpp
+++ b/src/edid.cpp
@@ -15,7 +15,7 @@ extern "C"
#include "libdisplay-info/cta.h"
}
-static LogScope edid_log("josh edid");
+static LogScope edid_log("edid");
namespace gamescope
{
diff --git a/src/log.cpp b/src/log.cpp
index f5fd828..50e5bb4 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -1,29 +1,16 @@
-#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
+#include <cstdio>
+#include <cerrno>
+#include <cstring>
+#include <cerrno>
-#include <memory>
+#include <format>
#include "Utils/Process.h"
#include "Utils/Defer.h"
+#include "convar.h"
#include "log.hpp"
-LogScope::LogScope(const char *name) {
- this->name = name;
- this->priority = LOG_DEBUG;
-}
-
-LogScope::LogScope(const char *name, enum LogPriority priority) {
- this->name = name;
- this->priority = priority;
-}
-
-bool LogScope::has(enum LogPriority priority) {
- return priority <= this->priority;
-}
-
-static const char *GetLogName( LogPriority ePriority )
+static constexpr std::string_view GetLogPriorityText( LogPriority ePriority )
{
switch ( ePriority )
{
@@ -36,10 +23,80 @@ static const char *GetLogName( LogPriority ePriority )
}
}
-void LogScope::vlogf(enum LogPriority priority, const char *fmt, va_list args) {
- if (!this->has(priority)) {
- return;
+static constexpr std::string_view GetLogName( LogPriority ePriority )
+{
+ switch ( ePriority )
+ {
+ case LOG_SILENT: return "silent";
+ case LOG_ERROR: return "error";
+ case LOG_WARNING: return "warning";
+ case LOG_DEBUG: return "debug";
+ default:
+ case LOG_INFO: return "info";
}
+}
+
+static constexpr LogPriority GetPriorityFromString( std::string_view psvScope )
+{
+ if ( psvScope == "silent" )
+ return LOG_SILENT;
+ else if ( psvScope == "error" )
+ return LOG_ERROR;
+ else if ( psvScope == "warning" )
+ return LOG_WARNING;
+ else if ( psvScope == "debug" )
+ return LOG_DEBUG;
+ else
+ return LOG_INFO;
+}
+
+struct LogConVar_t
+{
+ LogConVar_t( LogScope *pScope, std::string_view psvName, LogPriority eDefaultPriority )
+ : sName{ std::format( "log_{}", psvName ) }
+ , sDescription{ std::format( "Max logging priority for the {} channel. Valid options are: [ silent, error, warning, debug, info ].", psvName ) }
+ , convar
+ { sName, std::string( GetLogName( eDefaultPriority ) ), sDescription,
+ [ pScope ]( gamescope::ConVar<std::string> &cvar )
+ {
+ pScope->SetPriority( GetPriorityFromString( cvar ) );
+ },
+ }
+ {
+
+ }
+ std::string sName;
+ std::string sDescription;
+
+ gamescope::ConVar<std::string> convar;
+};
+
+LogScope::LogScope( std::string_view psvName, LogPriority eMaxPriority )
+ : LogScope( psvName, psvName, eMaxPriority )
+{
+}
+
+LogScope::LogScope( std::string_view psvName, std::string_view psvPrefix, LogPriority eMaxPriority )
+ : m_psvName{ psvName }
+ , m_psvPrefix{ psvPrefix }
+ , m_eMaxPriority{ eMaxPriority }
+ , m_pEnableConVar{ std::make_unique<LogConVar_t>( this, psvName, eMaxPriority ) }
+{
+}
+
+LogScope::~LogScope()
+{
+}
+
+bool LogScope::Enabled( LogPriority ePriority ) const
+{
+ return ePriority <= m_eMaxPriority;
+}
+
+void LogScope::vlogf(enum LogPriority priority, const char *fmt, va_list args)
+{
+ if ( !Enabled( priority ) )
+ return;
char *buf = nullptr;
vasprintf(&buf, fmt, args);
@@ -48,10 +105,15 @@ void LogScope::vlogf(enum LogPriority priority, const char *fmt, va_list args) {
defer( free(buf); );
for (auto& listener : m_LoggingListeners)
- listener.second( priority, this->name, buf );
+ listener.second( priority, m_psvPrefix, buf );
+ std::string_view psvLogName = GetLogPriorityText( priority );
if ( bPrefixEnabled )
- fprintf(stderr, "[%s] %s \e[0;37m%s:\e[0m %s\n", gamescope::Process::GetProcessName(), GetLogName( priority ), this->name, buf);
+ fprintf(stderr, "[%s] %.*s \e[0;37m%.*s:\e[0m %s\n",
+ gamescope::Process::GetProcessName(),
+ (int)psvLogName.size(), psvLogName.data(),
+ (int)this->m_psvPrefix.size(), this->m_psvPrefix.data(),
+ buf);
else
fprintf(stderr, "%s\n", buf);
}
diff --git a/src/log.hpp b/src/log.hpp
index 9dec0bb..5d28da6 100644
--- a/src/log.hpp
+++ b/src/log.hpp
@@ -1,11 +1,11 @@
#pragma once
-#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdint.h>
+#include <cstdarg>
+#include <cstdint>
+
+#include <memory>
#include <functional>
+#include <string_view>
#ifdef __GNUC__
#define ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end)))
@@ -13,7 +13,8 @@
#define ATTRIB_PRINTF(start, end)
#endif
-enum LogPriority {
+enum LogPriority
+{
LOG_SILENT,
LOG_ERROR,
LOG_WARNING,
@@ -21,17 +22,17 @@ enum LogPriority {
LOG_DEBUG,
};
-class LogScope {
- const char *name;
- enum LogPriority priority;
-
- bool has(enum LogPriority priority);
- void vprintf(enum LogPriority priority, const char *fmt, va_list args) ATTRIB_PRINTF(3, 0);
- void logf(enum LogPriority priority, const char *fmt, ...) ATTRIB_PRINTF(3, 4);
+struct LogConVar_t;
+class LogScope
+{
public:
- LogScope(const char *name);
- LogScope(const char *name, enum LogPriority priority);
+ LogScope( std::string_view psvName, LogPriority eMaxPriority = LOG_INFO );
+ LogScope( std::string_view psvName, std::string_view psvPrefix, LogPriority eMaxPriority = LOG_INFO );
+ ~LogScope();
+
+ bool Enabled( LogPriority ePriority ) const;
+ void SetPriority( LogPriority ePriority ) { m_eMaxPriority = ePriority; }
void vlogf(enum LogPriority priority, const char *fmt, va_list args) ATTRIB_PRINTF(3, 0);
@@ -44,6 +45,17 @@ public:
bool bPrefixEnabled = true;
- using LoggingListenerFunc = std::function<void(LogPriority ePriority, const char *pScope, const char *pText)>;
+ using LoggingListenerFunc = std::function<void( LogPriority ePriority, std::string_view psvScope, const char *psvText )>;
std::unordered_map<uintptr_t, LoggingListenerFunc> m_LoggingListeners;
+
+private:
+ void vprintf(enum LogPriority priority, const char *fmt, va_list args) ATTRIB_PRINTF(3, 0);
+ void logf(enum LogPriority priority, const char *fmt, ...) ATTRIB_PRINTF(3, 4);
+
+ std::string_view m_psvName;
+ std::string_view m_psvPrefix;
+
+ LogPriority m_eMaxPriority = LOG_INFO;
+
+ std::unique_ptr<LogConVar_t> m_pEnableConVar;
};
diff --git a/src/meson.build b/src/meson.build
index 0090629..cbe4113 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -181,15 +181,22 @@ gamescope_version = vcs_tag(
cpp_args: gamescope_cpp_args,
)
+gamescope_core_src = [
+ 'convar.cpp',
+ 'log.cpp',
+ 'Utils/Process.cpp',
+ 'Utils/Version.cpp',
+]
+
if pipewire_dep.found()
- executable( 'gamescopestream', ['Apps/gamescopestream.cpp', 'log.cpp', 'Utils/Process.cpp'], gamescope_version, protocols_client_src, dependencies: [ pipewire_dep, dep_wayland, libdecor_dep ], install: true )
+ executable( 'gamescopestream', ['Apps/gamescopestream.cpp'], gamescope_core_src, gamescope_version, protocols_client_src, dependencies: [ pipewire_dep, dep_wayland, libdecor_dep ], install: true )
endif
-executable('gamescopereaper', ['Utils/Process.cpp', 'Apps/gamescopereaper.cpp', 'log.cpp'], gamescope_version, install:true )
+executable('gamescopereaper', ['Apps/gamescopereaper.cpp', gamescope_core_src], gamescope_version, install:true )
benchmark_dep = dependency('benchmark', required: get_option('benchmark'), disabler: true)
-executable('gamescope_color_microbench', ['color_bench.cpp', 'color_helpers.cpp'], dependencies:[benchmark_dep, glm_dep])
+executable('gamescope_color_microbench', ['color_bench.cpp', 'color_helpers.cpp'], gamescope_core_src, dependencies:[benchmark_dep, glm_dep])
-executable('gamescope_color_tests', ['color_tests.cpp', 'color_helpers.cpp'], dependencies:[glm_dep])
+executable('gamescope_color_tests', ['color_tests.cpp', 'color_helpers.cpp'], gamescope_core_src, dependencies:[glm_dep])
-executable('gamescopectl', ['Apps/gamescopectl.cpp', 'convar.cpp', 'log.cpp', 'Utils/Version.cpp', 'Utils/Process.cpp'], gamescope_version, protocols_client_src, dependencies: [dep_wayland], install:true )
+executable('gamescopectl', ['Apps/gamescopectl.cpp'], gamescope_core_src, gamescope_version, protocols_client_src, dependencies: [dep_wayland], install:true )
diff --git a/src/rendervulkan.cpp b/src/rendervulkan.cpp
index 123d46e..f144611 100644
--- a/src/rendervulkan.cpp
+++ b/src/rendervulkan.cpp
@@ -368,7 +368,7 @@ bool CVulkanDevice::selectPhysDev(VkSurfaceKHR surface)
vk.GetPhysicalDeviceSurfaceSupportKHR( cphysDev, computeOnlyIndex, surface, &canPresent );
if ( !canPresent )
{
- vk_log.debugf( "physical device %04x:%04x compute queue doesn't support presenting on our surface, using graphics queue", deviceProperties.vendorID, deviceProperties.deviceID );
+ vk_log.infof( "physical device %04x:%04x compute queue doesn't support presenting on our surface, using graphics queue", deviceProperties.vendorID, deviceProperties.deviceID );
computeOnlyIndex = ~0u;
}
}
diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp
index eef2f45..2912750 100644
--- a/src/steamcompmgr.cpp
+++ b/src/steamcompmgr.cpp
@@ -7048,9 +7048,9 @@ static std::vector<uint32_t> s_uRelativeMouseFilteredAppids;
static gamescope::ConVar<std::string> cv_mouse_relative_filter_appids( "mouse_relative_filter_appids",
"8400" /* Geometry Wars: Retro Evolved */,
"Comma separated appids to filter out using relative mouse mode for.",
-[]()
+[]( gamescope::ConVar<std::string> &cvar )
{
- std::vector<std::string_view> sFilterAppids = gamescope::Split( cv_mouse_relative_filter_appids, "," );
+ std::vector<std::string_view> sFilterAppids = gamescope::Split( cvar, "," );
std::vector<uint32_t> uFilterAppids;
uFilterAppids.reserve( sFilterAppids.size() );
for ( auto &sFilterAppid : sFilterAppids )
diff --git a/src/wlserver.cpp b/src/wlserver.cpp
index c69f068..a2e1985 100644
--- a/src/wlserver.cpp
+++ b/src/wlserver.cpp
@@ -1230,7 +1230,7 @@ static const struct gamescope_private_interface gamescope_private_impl = {
static void gamescope_private_bind( struct wl_client *client, void *data, uint32_t version, uint32_t id )
{
struct wl_resource *resource = wl_resource_create( client, &gamescope_private_interface, version, id );
- console_log.m_LoggingListeners[(uintptr_t)resource] = [ resource ](LogPriority ePriority, const char *pScope, const char *pText)
+ console_log.m_LoggingListeners[(uintptr_t)resource] = [ resource ]( LogPriority ePriority, std::string_view psvScope, const char *pText )
{
if ( !wlserver_is_lock_held() )
return;
--
2.45.2
From 6fc1aa3075bd175b27ab08fbb39ba4d1b4da7867 Mon Sep 17 00:00:00 2001
From: Joshua Ashton <joshua@froggi.es>
Date: Fri, 2 Aug 2024 05:10:52 +0100
Subject: [PATCH 5/8] steamcompmgr: Add paint_debug_pause_base_plane
---
src/steamcompmgr.cpp | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp
index 2912750..e4738f9 100644
--- a/src/steamcompmgr.cpp
+++ b/src/steamcompmgr.cpp
@@ -1866,6 +1866,8 @@ wlserver_vk_swapchain_feedback* steamcompmgr_get_base_layer_swapchain_feedback()
return &(*g_HeldCommits[ HELD_COMMIT_BASE ]->feedback);
}
+gamescope::ConVar<bool> cv_paint_debug_pause_base_plane( "paint_debug_pause_base_plane", false, "Pause updates to the base plane." );
+
static void
paint_window(steamcompmgr_win_t *w, steamcompmgr_win_t *scaleW, struct FrameInfo_t *frameInfo,
MouseCursor *cursor, PaintWindowFlags flags = 0, float flOpacityScale = 1.0f, steamcompmgr_win_t *fit = nullptr )
@@ -1880,7 +1882,7 @@ paint_window(steamcompmgr_win_t *w, steamcompmgr_win_t *scaleW, struct FrameInfo
if ( flags & PaintWindowFlag::BasePlane )
{
- if ( lastCommit == nullptr )
+ if ( lastCommit == nullptr || cv_paint_debug_pause_base_plane )
{
// If we're the base plane and have no valid contents
// pick up that buffer we've been holding onto if we have one.
@@ -3876,12 +3878,15 @@ determine_and_apply_focus()
}
}
- // Update last focus commit
- if ( global_focus.focusWindow &&
- previous_focus.focusWindow != global_focus.focusWindow &&
- !global_focus.focusWindow->isSteamStreamingClient )
+ if ( !cv_paint_debug_pause_base_plane )
{
- get_window_last_done_commit( global_focus.focusWindow, g_HeldCommits[ HELD_COMMIT_BASE ] );
+ // Update last focus commit
+ if ( global_focus.focusWindow &&
+ previous_focus.focusWindow != global_focus.focusWindow &&
+ !global_focus.focusWindow->isSteamStreamingClient )
+ {
+ get_window_last_done_commit( global_focus.focusWindow, g_HeldCommits[ HELD_COMMIT_BASE ] );
+ }
}
// Set SDL window title
@@ -5998,7 +6003,8 @@ bool handle_done_commit( steamcompmgr_win_t *w, xwayland_ctx_t *ctx, uint64_t co
// If this is the main plane, repaint
if ( w == global_focus.focusWindow && !w->isSteamStreamingClient )
{
- g_HeldCommits[ HELD_COMMIT_BASE ] = w->commit_queue[ j ];
+ if ( !cv_paint_debug_pause_base_plane )
+ g_HeldCommits[ HELD_COMMIT_BASE ] = w->commit_queue[ j ];
hasRepaint = true;
}
@@ -6009,7 +6015,8 @@ bool handle_done_commit( steamcompmgr_win_t *w, xwayland_ctx_t *ctx, uint64_t co
if ( w->isSteamStreamingClientVideo && global_focus.focusWindow && global_focus.focusWindow->isSteamStreamingClient )
{
- g_HeldCommits[ HELD_COMMIT_BASE ] = w->commit_queue[ j ];
+ if ( !cv_paint_debug_pause_base_plane )
+ g_HeldCommits[ HELD_COMMIT_BASE ] = w->commit_queue[ j ];
hasRepaint = true;
}
--
2.45.2
From fa51eceec09c0bc9de0227e95cb6ec09ba5ff6ec Mon Sep 17 00:00:00 2001
From: Joshua Ashton <joshua@froggi.es>
Date: Fri, 2 Aug 2024 05:11:11 +0100
Subject: [PATCH 6/8] DRMBackend: Clean up flip_lock usage
This is better.
---
src/Backends/DRMBackend.cpp | 33 +++++++++++++++++++--------------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp
index 72bd1ec..c9e2400 100644
--- a/src/Backends/DRMBackend.cpp
+++ b/src/Backends/DRMBackend.cpp
@@ -479,13 +479,14 @@ struct drm_t {
std::vector<gamescope::Rc<gamescope::IBackendFb>> m_QueuedFbIds;
// FBs currently on screen.
// Accessed only on page flip handler thread.
+ std::mutex m_mutVisibleFbIds;
std::vector<gamescope::Rc<gamescope::IBackendFb>> m_VisibleFbIds;
- std::mutex flip_lock;
+ std::atomic < bool > bPendingFlip = { false };
- std::atomic < bool > paused;
- std::atomic < int > out_of_date;
- std::atomic < bool > needs_modeset;
+ std::atomic < bool > paused = { false };
+ std::atomic < int > out_of_date = { false };
+ std::atomic < bool > needs_modeset = { false };
std::unordered_map< std::string, int > connector_priorities;
@@ -693,23 +694,28 @@ static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsi
if ( g_DRM.pCRTC->GetObjectId() != crtc_id )
return;
+ static uint64_t ulLastVBlankTime = 0;
+
// This is the last vblank time
uint64_t vblanktime = sec * 1'000'000'000lu + usec * 1'000lu;
GetVBlankTimer().MarkVBlank( vblanktime, true );
// TODO: get the fbids_queued instance from data if we ever have more than one in flight
- drm_log.debugf("page_flip_handler %" PRIu64, pCtx->ulPendingFlipCount);
+ drm_log.debugf("page_flip_handler %" PRIu64 " delta: %" PRIu64, pCtx->ulPendingFlipCount, vblanktime - ulLastVBlankTime );
gpuvis_trace_printf("page_flip_handler %" PRIu64, pCtx->ulPendingFlipCount);
+ ulLastVBlankTime = vblanktime;
+
{
- std::unique_lock lock( g_DRM.m_QueuedFbIdsMutex );
+ std::scoped_lock lock{ g_DRM.m_QueuedFbIdsMutex, g_DRM.m_mutVisibleFbIds };
// Swap and clear from queue -> visible to avoid allocations.
g_DRM.m_VisibleFbIds.swap( g_DRM.m_QueuedFbIds );
g_DRM.m_QueuedFbIds.clear();
}
- g_DRM.flip_lock.unlock();
+ g_DRM.bPendingFlip = false;
+ g_DRM.bPendingFlip.notify_all();
mangoapp_output_update( vblanktime );
@@ -1399,7 +1405,7 @@ void finish_drm(struct drm_t *drm)
drm->m_QueuedFbIds.clear();
}
{
- std::unique_lock lock( drm->flip_lock );
+ std::unique_lock lock( drm->m_mutVisibleFbIds );
drm->m_VisibleFbIds.clear();
}
drm->sdr_static_metadata = nullptr;
@@ -3637,7 +3643,7 @@ namespace gamescope
if ( isPageFlip )
{
- drm->flip_lock.lock();
+ drm->bPendingFlip = true;
// Do it before the commit, as otherwise the pageflip handler could
// potentially beat us to the refcount checks.
@@ -3665,7 +3671,7 @@ namespace gamescope
{
drm_log.errorf( "fatal flip error, aborting" );
if ( isPageFlip )
- drm->flip_lock.unlock();
+ drm->bPendingFlip = false;
abort();
}
@@ -3683,7 +3689,7 @@ namespace gamescope
m_PresentFeedback.m_uQueuedPresents--;
if ( isPageFlip )
- drm->flip_lock.unlock();
+ drm->bPendingFlip = false;
return ret;
} else {
@@ -3731,9 +3737,8 @@ namespace gamescope
if ( isPageFlip )
{
- // Wait for flip handler to unlock
- drm->flip_lock.lock();
- drm->flip_lock.unlock();
+ // Wait for bPendingFlip to change from true -> false.
+ drm->bPendingFlip.wait( true );
}
return ret;
--
2.45.2
From f1963e968ef1224fe7dc326f6af95811f99b01f7 Mon Sep 17 00:00:00 2001
From: Joshua Ashton <joshua@froggi.es>
Date: Fri, 2 Aug 2024 05:16:00 +0100
Subject: [PATCH 7/8] DRMBackend: Track pending flip count robustly
Check we aren't mucking up here.
---
src/Backends/DRMBackend.cpp | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp
index c9e2400..2712994 100644
--- a/src/Backends/DRMBackend.cpp
+++ b/src/Backends/DRMBackend.cpp
@@ -482,7 +482,7 @@ struct drm_t {
std::mutex m_mutVisibleFbIds;
std::vector<gamescope::Rc<gamescope::IBackendFb>> m_VisibleFbIds;
- std::atomic < bool > bPendingFlip = { false };
+ std::atomic < uint32_t > uPendingFlipCount = { 0 };
std::atomic < bool > paused = { false };
std::atomic < int > out_of_date = { false };
@@ -714,8 +714,8 @@ static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsi
g_DRM.m_QueuedFbIds.clear();
}
- g_DRM.bPendingFlip = false;
- g_DRM.bPendingFlip.notify_all();
+ g_DRM.uPendingFlipCount--;
+ g_DRM.uPendingFlipCount.notify_all();
mangoapp_output_update( vblanktime );
@@ -3640,10 +3640,11 @@ namespace gamescope
defer( if ( drm->req != nullptr ) { drmModeAtomicFree( drm->req ); drm->req = nullptr; } );
bool isPageFlip = drm->flags & DRM_MODE_PAGE_FLIP_EVENT;
+ uint32_t uNewPendingFlipCount = 0;
if ( isPageFlip )
{
- drm->bPendingFlip = true;
+ uNewPendingFlipCount = ++drm->uPendingFlipCount;
// Do it before the commit, as otherwise the pageflip handler could
// potentially beat us to the refcount checks.
@@ -3671,7 +3672,7 @@ namespace gamescope
{
drm_log.errorf( "fatal flip error, aborting" );
if ( isPageFlip )
- drm->bPendingFlip = false;
+ drm->uPendingFlipCount--;
abort();
}
@@ -3689,7 +3690,7 @@ namespace gamescope
m_PresentFeedback.m_uQueuedPresents--;
if ( isPageFlip )
- drm->bPendingFlip = false;
+ drm->uPendingFlipCount--;
return ret;
} else {
@@ -3738,7 +3739,8 @@ namespace gamescope
if ( isPageFlip )
{
// Wait for bPendingFlip to change from true -> false.
- drm->bPendingFlip.wait( true );
+ drm->uPendingFlipCount.wait( uNewPendingFlipCount );
+ assert( drm->uPendingFlipCount == 0 );
}
return ret;
--
2.45.2
From e31b8dea137d2cedd4cf71fede560feb2ad3ffc5 Mon Sep 17 00:00:00 2001
From: Joshua Ashton <joshua@froggi.es>
Date: Fri, 2 Aug 2024 21:11:11 +0100
Subject: [PATCH 8/8] DRMBackend: Fix mode fallback on connector changes
---
src/Backends/DRMBackend.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp
index 2712994..ee2cbd3 100644
--- a/src/Backends/DRMBackend.cpp
+++ b/src/Backends/DRMBackend.cpp
@@ -1040,6 +1040,9 @@ static bool setup_best_connector(struct drm_t *drm, bool force, bool initial)
return false;
}
+ // Don't allow rollback of mode_id after connector change
+ drm->current.mode_id = drm->pending.mode_id;
+
const struct wlserver_output_info wlserver_output_info = {
.description = description,
.phys_width = (int) best->GetModeConnector()->mmWidth,
@@ -2876,6 +2879,11 @@ bool drm_set_connector( struct drm_t *drm, gamescope::CDRMConnector *conn )
return false;
}
+ // If we are changing connector, zero out the current and pending mode IDs.
+ // So we don't try to use one mode from the old connector on the new one if we roll back.
+ drm->pending.mode_id = nullptr;
+ drm->current.mode_id = nullptr;
+
drm->pConnector = conn;
drm->needs_modeset = true;
--
2.45.2