diff --git a/meta/hl.meta.lua b/meta/hl.meta.lua index 6ea875aee..43092b563 100644 --- a/meta/hl.meta.lua +++ b/meta/hl.meta.lua @@ -148,6 +148,8 @@ ---| "ecosystem.enforce_permissions" ---| "ecosystem.no_donation_nag" ---| "ecosystem.no_update_news" +---| "experimental.deadline_client_buffer" +---| "experimental.deadline_main_buffer" ---| "experimental.wp_cm_1_2" ---| "general.allow_tearing" ---| "general.border_size" @@ -984,6 +986,8 @@ hl = {} ---@field ['ecosystem.enforce_permissions'] boolean ---@field ['ecosystem.no_donation_nag'] boolean ---@field ['ecosystem.no_update_news'] boolean +---@field ['experimental.deadline_client_buffer'] boolean +---@field ['experimental.deadline_main_buffer'] boolean ---@field ['experimental.wp_cm_1_2'] boolean ---@field ['general.allow_tearing'] boolean ---@field ['general.border_size'] integer|boolean diff --git a/src/config/values/ConfigValues.cpp b/src/config/values/ConfigValues.cpp index 2c44b1722..bbffecf8a 100644 --- a/src/config/values/ConfigValues.cpp +++ b/src/config/values/ConfigValues.cpp @@ -674,6 +674,8 @@ std::vector> Values::getConfigValues() { */ MS("experimental:wp_cm_1_2", "Allow wp-cm-v1 version 2", false), + MS("experimental:deadline_client_buffer", "set deadline on client buffers", false), + MS("experimental:deadline_main_buffer", "set deadline on main buffers", false), /* * quirks: diff --git a/src/helpers/Drm.cpp b/src/helpers/Drm.cpp index 4f3119f83..7903b24c1 100644 --- a/src/helpers/Drm.cpp +++ b/src/helpers/Drm.cpp @@ -4,8 +4,19 @@ #include #include #include + +#if defined(__linux__) +#include +#include +#endif + +#include +#include + #include "Drm.hpp" +using namespace Hyprutils::OS; + namespace { using SDRMNodePair = std::array; @@ -67,3 +78,61 @@ bool DRM::sameGpu(int fd1, int fd2) { return same; } + +int DRM::doIoctl(int fd, unsigned long request, void* arg) { + int ret; + + do { + ret = ioctl(fd, request, arg); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + return ret; +} + +// https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#c.dma_buf_export_sync_file +// returns a sync file that will be signalled when dmabuf is ready to be read +CFileDescriptor DRM::exportFence(int fd) { +#ifndef __linux__ + return {}; +#endif + +#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE + if (fd < 0) + return {}; + + dma_buf_export_sync_file request{ + .flags = DMA_BUF_SYNC_READ, + .fd = -1, + }; + + if (doIoctl(fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &request) == 0) + return CFileDescriptor{request.fd}; +#endif + return {}; +} + +CFileDescriptor DRM::mergeFence(int fence1, int fence2) { +#ifdef __linux__ + sync_accumulate("merged release fence", &fence1, fence2); + + if (fence2 >= 0) + close(fence2); + + return CFileDescriptor{fence1}; +#else + return {}; +#endif +} + +void DRM::setDeadline(const Time::steady_tp& deadline, const Hyprutils::OS::CFileDescriptor& fence) { +#ifdef SYNC_IOC_SET_DEADLINE + if (!fence.isValid()) + return; + + sync_set_deadline args{ + .deadline_ns = uint64_t(duration_cast(deadline.time_since_epoch()).count()), + .pad = 0, + }; + + doIoctl(fence.get(), SYNC_IOC_SET_DEADLINE, &args); +#endif +} \ No newline at end of file diff --git a/src/helpers/Drm.hpp b/src/helpers/Drm.hpp index 755ee0502..5f5ecc90f 100644 --- a/src/helpers/Drm.hpp +++ b/src/helpers/Drm.hpp @@ -2,8 +2,14 @@ #include #include +#include +#include "time/Time.hpp" namespace DRM { - std::optional devIDFromFD(int fd); - bool sameGpu(int fd1, int fd2); + std::optional devIDFromFD(int fd); + bool sameGpu(int fd1, int fd2); + int doIoctl(int fd, unsigned long request, void* arg); + Hyprutils::OS::CFileDescriptor exportFence(int fd); + Hyprutils::OS::CFileDescriptor mergeFence(int fence1, int fence2); + void setDeadline(const Time::steady_tp& deadline, const Hyprutils::OS::CFileDescriptor& fence); } diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index c7d4168ae..0a679f418 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -155,6 +155,12 @@ void CMonitor::onConnect(bool noRule) { }); } + if (m_pendingFrame) { // if no pending frame, VFR etc we cant estimate this. + auto minVBlankInterval = std::chrono::duration_cast(std::chrono::duration(1.0 / m_refreshRate)); + m_estimatedNextVblank = (ts ? Time::fromTimespec(ts) + minVBlankInterval : Time::steadyNow()) + minVBlankInterval; + } else + m_estimatedNextVblank = std::nullopt; + m_frameScheduler->onPresented(); m_events.presented.emit(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 59a64237e..3ae1877b9 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -106,71 +106,72 @@ class CMonitor { CMonitor(SP output); ~CMonitor(); - Vector2D m_position = Vector2D(-1, -1); // means unset - Vector2D m_xwaylandPosition = Vector2D(-1, -1); // means unset - Config::eAutoDirs m_autoDir = Config::DIR_AUTO_NONE; - Vector2D m_size = Vector2D(0, 0); - Vector2D m_pixelSize = Vector2D(0, 0); - Vector2D m_transformedSize = Vector2D(0, 0); + Vector2D m_position = Vector2D(-1, -1); // means unset + Vector2D m_xwaylandPosition = Vector2D(-1, -1); // means unset + Config::eAutoDirs m_autoDir = Config::DIR_AUTO_NONE; + Vector2D m_size = Vector2D(0, 0); + Vector2D m_pixelSize = Vector2D(0, 0); + Vector2D m_transformedSize = Vector2D(0, 0); - MONITORID m_id = MONITOR_INVALID; - PHLWORKSPACE m_activeWorkspace = nullptr; - PHLWORKSPACE m_activeSpecialWorkspace = nullptr; - float m_setScale = 1; // scale set by cfg - float m_scale = 1; // real scale + MONITORID m_id = MONITOR_INVALID; + PHLWORKSPACE m_activeWorkspace = nullptr; + PHLWORKSPACE m_activeSpecialWorkspace = nullptr; + float m_setScale = 1; // scale set by cfg + float m_scale = 1; // real scale - std::string m_name = ""; - std::string m_description = ""; - std::string m_shortDescription = ""; + std::string m_name = ""; + std::string m_description = ""; + std::string m_shortDescription = ""; - drmModeModeInfo m_customDrmMode = {}; + drmModeModeInfo m_customDrmMode = {}; - Desktop::CReservedArea m_reservedArea; + Desktop::CReservedArea m_reservedArea; - CMonitorState m_state; - CDamageRing m_damage; + CMonitorState m_state; + CDamageRing m_damage; - SP m_output; - float m_refreshRate = 60; // Hz - int m_forceFullFrames = 0; - bool m_scheduledRecalc = false; - wl_output_transform m_transform = WL_OUTPUT_TRANSFORM_NORMAL; - float m_xwaylandScale = 1.f; + SP m_output; + float m_refreshRate = 60; // Hz + int m_forceFullFrames = 0; + bool m_scheduledRecalc = false; + wl_output_transform m_transform = WL_OUTPUT_TRANSFORM_NORMAL; + float m_xwaylandScale = 1.f; - std::optional m_forceSize; - SP m_currentMode; - SP m_cursorSwapchain; - uint32_t m_drmFormat = DRM_FORMAT_INVALID; - uint32_t m_prevDrmFormat = DRM_FORMAT_INVALID; + std::optional m_forceSize; + SP m_currentMode; + SP m_cursorSwapchain; + uint32_t m_drmFormat = DRM_FORMAT_INVALID; + uint32_t m_prevDrmFormat = DRM_FORMAT_INVALID; - CMonitorZoomController m_zoomController; + CMonitorZoomController m_zoomController; - bool m_dpmsStatus = true; - bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. - bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. - NCMType::eCMType m_cmType = NCMType::CM_SRGB; - NTransferFunction::eTF m_sdrEotf = NTransferFunction::TF_DEFAULT; - float m_sdrSaturation = 1.0f; - float m_sdrBrightness = 1.0f; - float m_sdrMinLuminance = 0.2f; - int m_sdrMaxLuminance = 80; - bool m_createdByUser = false; - bool m_isUnsafeFallback = false; + bool m_dpmsStatus = true; + bool m_vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. + bool m_enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. + NCMType::eCMType m_cmType = NCMType::CM_SRGB; + NTransferFunction::eTF m_sdrEotf = NTransferFunction::TF_DEFAULT; + float m_sdrSaturation = 1.0f; + float m_sdrBrightness = 1.0f; + float m_sdrMinLuminance = 0.2f; + int m_sdrMaxLuminance = 80; + bool m_createdByUser = false; + bool m_isUnsafeFallback = false; - SP m_dpmsRetryTimer; + SP m_dpmsRetryTimer; - bool m_pendingFrame = false; // if we schedule a frame during rendering, reschedule it after - bool m_renderingActive = false; + bool m_pendingFrame = false; // if we schedule a frame during rendering, reschedule it after + bool m_renderingActive = false; - bool m_ratsScheduled = false; - CTimer m_lastPresentationTimer; + bool m_ratsScheduled = false; + CTimer m_lastPresentationTimer; + std::optional m_estimatedNextVblank; - bool m_isBeingLeased = false; + bool m_isBeingLeased = false; - Config::CMonitorRule m_activeMonitorRule; + Config::CMonitorRule m_activeMonitorRule; - SP m_splash; - SP m_background; + SP m_splash; + SP m_background; // explicit sync Hyprutils::OS::CFileDescriptor m_inFence; // TODO: remove when aq uses CFileDescriptor diff --git a/src/helpers/sync/SyncReleaser.cpp b/src/helpers/sync/SyncReleaser.cpp index fbc585d0b..a8112741a 100644 --- a/src/helpers/sync/SyncReleaser.cpp +++ b/src/helpers/sync/SyncReleaser.cpp @@ -1,21 +1,7 @@ #include "SyncReleaser.hpp" #include "SyncTimeline.hpp" #include "../../render/OpenGL.hpp" -#include - -#if defined(__linux__) -#include -#else -struct sync_merge_data { - char name[32]; - __s32 fd2; - __s32 fence; - __u32 flags; - __u32 pad; -}; -#define SYNC_IOC_MAGIC '>' -#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) -#endif +#include "../../helpers/Drm.hpp" using namespace Hyprutils::OS; @@ -35,30 +21,11 @@ CSyncReleaser::~CSyncReleaser() { m_timeline->signal(m_point); } -static CFileDescriptor mergeSyncFds(const CFileDescriptor& fd1, const CFileDescriptor& fd2) { - // combines the fences of both sync_fds into a dma_fence_array (https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#c.dma_fence_array_create) - // with the signal_on_any param set to false, so the new sync_fd will "signal when all fences in the array signal." - - struct sync_merge_data data{ - .name = "merged release fence", - .fd2 = fd2.get(), - .fence = -1, - }; - int err = -1; - do { - err = ioctl(fd1.get(), SYNC_IOC_MERGE, &data); - } while (err == -1 && (errno == EINTR || errno == EAGAIN)); - if (err < 0) - return CFileDescriptor{}; - else - return CFileDescriptor(data.fence); -} - void CSyncReleaser::addSyncFileFd(const Hyprutils::OS::CFileDescriptor& syncFd) { - if (m_fd.isValid()) - m_fd = mergeSyncFds(m_fd, syncFd); - else + if (!m_fd.isValid()) m_fd = syncFd.duplicate(); + else + m_fd = DRM::mergeFence(m_fd.take(), syncFd.duplicate().take()); } void CSyncReleaser::drop() { diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 0200ebd4a..322141450 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -8,6 +8,7 @@ #include "Subcompositor.hpp" #include "../Viewporter.hpp" #include "../../helpers/Monitor.hpp" +#include "../../helpers/Drm.hpp" #include "../PresentationTime.hpp" #include "../DRMSyncobj.hpp" #include "../types/DMABuffer.hpp" @@ -148,10 +149,28 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : m_resource(re // fifo and fences first m_events.stateCommit.emit(state); - if (state->buffer && state->buffer->type() == Aquamarine::BUFFER_TYPE_DMABUF && state->buffer->dmabuf().success && !state->updated.bits.acquire) { - state->buffer->m_syncFd = dc(state->buffer.m_buffer.get())->exportSyncFile(); - if (state->buffer->m_syncFd.isValid()) - m_stateQueue.lock(state, LOCK_REASON_FENCE); + if (state->buffer && state->buffer->type() == Aquamarine::BUFFER_TYPE_DMABUF && state->buffer->dmabuf().success) { + static const auto DEADLINE = CConfigValue("experimental:deadline_client_buffer"); + auto const WINDOW = m_hlSurface ? Desktop::View::CWindow::fromView(m_hlSurface->view()) : nullptr; + if (g_pHyprRenderer->explicitSyncSupported()) { + if (state->updated.bits.acquire && *DEADLINE && WINDOW && WINDOW->m_monitor && WINDOW->m_monitor->m_solitaryClient == WINDOW) { + Time::steady_tp deadline = Time::steadyNow() + std::chrono::microseconds(100); + DRM::setDeadline(deadline, state->acquire.exportAsFD()); + } else { + state->buffer->m_syncFds = dc(state->buffer.m_buffer.get())->exportSyncFiles(); + if (!state->buffer->m_syncFds.empty()) { + if (*DEADLINE && WINDOW && WINDOW->m_monitor && WINDOW->m_monitor->m_solitaryClient == WINDOW) { + Time::steady_tp deadline = Time::steadyNow() + std::chrono::microseconds(100); + for (auto& fence : state->buffer->m_syncFds) { + if (fence.isValid()) + DRM::setDeadline(deadline, fence); + } + } + + m_stateQueue.lock(state, LOCK_REASON_FENCE); + } + } + } } // now for timer. @@ -542,9 +561,30 @@ void CWLSurfaceResource::scheduleState(WP state) { } else if (state->buffer && state->buffer->isSynchronous()) { // synchronous (shm) buffers can be read immediately m_stateQueue.unlock(state, LOCK_REASON_FENCE); - } else if (state->buffer && state->buffer->m_syncFd.isValid()) { + } else if (state->buffer && !state->buffer->m_syncFds.empty()) { // async buffer and is dmabuf, then we can wait on implicit fences - g_pEventLoopManager->doOnReadable(std::move(state->buffer->m_syncFd), [state, whenReadable]() { whenReadable(state, LOCK_REASON_FENCE); }); + auto fence = std::ranges::find_if(state->buffer->m_syncFds, [](auto& f) { return !Hyprutils::OS::CFileDescriptor::isReadable(f.get()); }); + if (fence == state->buffer->m_syncFds.end()) + m_stateQueue.unlock(state, LOCK_REASON_FENCE); + else { + //#TODO: if multiple fences are not ready, wait for them.. + auto checkFences = [state, whenReadable](auto&& self) -> void { + if (!state || !state->buffer.m_buffer) + return; + + auto fence = std::ranges::find_if(state->buffer->m_syncFds, [](auto& f) { return !Hyprutils::OS::CFileDescriptor::isReadable(f.get()); }); + + if (fence == state->buffer->m_syncFds.end()) { + // All fences readable + whenReadable(state, LOCK_REASON_FENCE); + return; + } + + g_pEventLoopManager->doOnReadable(fence->duplicate(), [state, whenReadable, self]() mutable { self(self); }); + }; + + checkFences(checkFences); + } } else { // state commit without a buffer. m_stateQueue.tryProcess(); diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index 927cd2591..e93240b1e 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -13,24 +13,24 @@ class CHLBufferReference; class IHLBuffer : public Aquamarine::IBuffer { public: virtual ~IHLBuffer(); - virtual Aquamarine::eBufferCapability caps() = 0; - virtual Aquamarine::eBufferType type() = 0; - virtual void update(const CRegion& damage) = 0; - virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu - virtual bool good() = 0; - virtual void sendRelease(); - virtual void lock(); - virtual void unlock(); - virtual bool locked(); + virtual Aquamarine::eBufferCapability caps() = 0; + virtual Aquamarine::eBufferType type() = 0; + virtual void update(const CRegion& damage) = 0; + virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu + virtual bool good() = 0; + virtual void sendRelease(); + virtual void lock(); + virtual void unlock(); + virtual bool locked(); - void onBackendRelease(const std::function& fn); - void addReleasePoint(CDRMSyncPointState& point); + void onBackendRelease(const std::function& fn); + void addReleasePoint(CDRMSyncPointState& point); - SP m_texture; - bool m_opaque = false; - SP m_resource; - std::vector> m_syncReleasers; - Hyprutils::OS::CFileDescriptor m_syncFd; + SP m_texture; + bool m_opaque = false; + SP m_resource; + std::vector> m_syncReleasers; + std::vector m_syncFds; struct { CHyprSignalListener backendRelease; diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index 37c463387..a3b976104 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -4,12 +4,7 @@ #include "../../render/Renderer.hpp" #include "../../helpers/Format.hpp" #include - -#if defined(__linux__) -#include -#include -#endif -#include +#include "../../helpers/Drm.hpp" using namespace Hyprutils::OS; using namespace Hyprgraphics::Egl; @@ -92,18 +87,9 @@ void CDMABuffer::closeFDs() { m_attrs.planes = 0; } -static int doIoctl(int fd, unsigned long request, void* arg) { - int ret; - - do { - ret = ioctl(fd, request, arg); - } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); - return ret; -} - // https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#c.dma_buf_export_sync_file // returns a sync file that will be signalled when dmabuf is ready to be read -CFileDescriptor CDMABuffer::exportSyncFile() { +std::vector CDMABuffer::exportSyncFiles() { if (!good()) return {}; @@ -113,7 +99,8 @@ CFileDescriptor CDMABuffer::exportSyncFile() { std::vector syncFds; syncFds.reserve(m_attrs.fds.size()); - for (const auto& fd : m_attrs.fds) { + for (auto i = 0ul; i < m_attrs.fds.size(); i++) { + auto fd = m_attrs.fds[i]; if (fd == -1) continue; @@ -124,40 +111,11 @@ CFileDescriptor CDMABuffer::exportSyncFile() { continue; } - dma_buf_export_sync_file request{ - .flags = DMA_BUF_SYNC_READ, - .fd = -1, - }; - - if (doIoctl(fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &request) == 0) - syncFds.emplace_back(request.fd); + auto fence = DRM::exportFence(fd); + if (fence.isValid()) + syncFds.emplace_back(std::move(fence)); } - if (syncFds.empty()) - return {}; - - CFileDescriptor syncFd; - for (auto& fd : syncFds) { - if (!syncFd.isValid()) { - syncFd = std::move(fd); - continue; - } - - const std::string name = "merged release fence"; - struct sync_merge_data data{ - .name = {}, // zero-initialize name[] - .fd2 = fd.get(), - .fence = -1, - }; - - std::ranges::copy_n(name.c_str(), std::min(name.size() + 1, sizeof(data.name)), data.name); - - if (doIoctl(syncFd.get(), SYNC_IOC_MERGE, &data) == 0) - syncFd = CFileDescriptor(data.fence); - else - syncFd = {}; - } - - return syncFd; + return syncFds; #endif } diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp index 5a0064da5..cba157ab1 100644 --- a/src/protocols/types/DMABuffer.hpp +++ b/src/protocols/types/DMABuffer.hpp @@ -17,7 +17,7 @@ class CDMABuffer : public IHLBuffer { virtual void endDataPtr(); bool good(); void closeFDs(); - Hyprutils::OS::CFileDescriptor exportSyncFile(); + std::vector exportSyncFiles(); bool m_success = false; private: diff --git a/src/render/GLRenderer.cpp b/src/render/GLRenderer.cpp index 35aca7db8..1e1640db6 100644 --- a/src/render/GLRenderer.cpp +++ b/src/render/GLRenderer.cpp @@ -11,6 +11,7 @@ #include "../protocols/core/Compositor.hpp" #include "../debug/Overlay.hpp" #include "../helpers/Monitor.hpp" +#include "../helpers/Drm.hpp" #include "pass/TexPassElement.hpp" #include "pass/SurfacePassElement.hpp" #include "../debug/log/Logger.hpp" @@ -71,7 +72,6 @@ bool CHyprGLRenderer::beginFullFakeRenderInternal(PHLMONITOR pMonitor, CRegion& } bool CHyprGLRenderer::beginRenderInternal(PHLMONITOR pMonitor, CRegion& damage, bool simple) { - m_currentRenderbuffer->bind(); if (simple) g_pHyprOpenGL->beginSimple(pMonitor, damage, m_currentRenderbuffer); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 635bef556..1b2ed50e1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -34,6 +34,7 @@ #include "../helpers/CursorShapes.hpp" #include "../helpers/MainLoopExecutor.hpp" #include "../helpers/Monitor.hpp" +#include "../helpers/Drm.hpp" #include "macros.hpp" #include "pass/TexPassElement.hpp" #include "pass/ClearPassElement.hpp" @@ -1970,6 +1971,8 @@ void IHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) { const float ZOOMFACTOR = pMonitor->m_cursorZoom->value(); + auto cleanup = CScopeGuard([pMonitor]() { pMonitor->m_estimatedNextVblank = std::nullopt; }); + if (pMonitor->m_pixelSize.x < 1 || pMonitor->m_pixelSize.y < 1) { Log::logger->log(Log::ERR, "Refusing to render a monitor because of an invalid pixel size: {}", pMonitor->m_pixelSize); return; @@ -2404,6 +2407,16 @@ void IHyprRenderer::handleFullscreenSettings(PHLMONITOR pMonitor) { bool IHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { handleFullscreenSettings(pMonitor); + static const auto DEADLINE = CConfigValue("experimental:deadline_main_buffer"); + if (*DEADLINE && m_currentBuffer) { + auto deadline = pMonitor->isMultiGPU() || pMonitor->m_vrrActive || pMonitor->m_tearingState.activelyTearing || !pMonitor->m_estimatedNextVblank.has_value() ? + Time::steadyNow() + std::chrono::microseconds(100) : + pMonitor->m_estimatedNextVblank.value(); + auto fence = DRM::exportFence(m_currentBuffer->dmabuf().fds[0]); + + DRM::setDeadline(deadline, fence); + } + bool ok = pMonitor->m_state.commit(); if (!ok) { if (pMonitor->m_inFence.isValid()) { diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index f52b9e3a0..fff08a211 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -271,12 +271,12 @@ namespace Render { bool m_cursorHidden = false; bool m_cursorHiddenByCondition = false; bool m_cursorHasSurface = false; - SP m_currentBuffer = nullptr; eRenderMode m_renderMode = RENDER_MODE_NORMAL; bool m_nvidia = false; bool m_intel = false; bool m_software = false; bool m_mgpu = false; + SP m_currentBuffer = nullptr; struct { bool hiddenOnTouch = false;