mirror of
https://github.com/hyprwm/Hyprland
synced 2025-12-20 06:30:06 +01:00
Merge c5fed0f545 into 315806f598
This commit is contained in:
commit
eeb96c3940
16 changed files with 293 additions and 122 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include "helpers/Splashes.hpp"
|
||||
#include "config/ConfigValue.hpp"
|
||||
#include "config/ConfigWatcher.hpp"
|
||||
#include "managers/SurfaceManager.hpp"
|
||||
#include "managers/CursorManager.hpp"
|
||||
#include "managers/TokenManager.hpp"
|
||||
#include "managers/PointerManager.hpp"
|
||||
|
|
@ -661,6 +662,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
|||
|
||||
Log::logger->log(Log::DEBUG, "Creating the SeatManager!");
|
||||
g_pSeatManager = makeUnique<CSeatManager>();
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Creating the CSurfaceManager!");
|
||||
g_pSurfaceManager = makeUnique<CSurfaceManager>();
|
||||
} break;
|
||||
case STAGE_LATE: {
|
||||
Log::logger->log(Log::DEBUG, "Creating CHyprCtl");
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "../managers/animation/AnimationManager.hpp"
|
||||
#include "../managers/animation/DesktopAnimationManager.hpp"
|
||||
#include "../managers/input/InputManager.hpp"
|
||||
#include "../managers/SurfaceManager.hpp"
|
||||
#include "../hyprerror/HyprError.hpp"
|
||||
#include "../i18n/Engine.hpp"
|
||||
#include "sync/SyncTimeline.hpp"
|
||||
|
|
@ -68,6 +69,9 @@ CMonitor::~CMonitor() {
|
|||
m_events.destroy.emit();
|
||||
if (g_pHyprOpenGL)
|
||||
g_pHyprOpenGL->destroyMonitorResources(m_self);
|
||||
|
||||
if (g_pSurfaceManager)
|
||||
g_pSurfaceManager->destroy(m_self);
|
||||
}
|
||||
|
||||
void CMonitor::onConnect(bool noRule) {
|
||||
|
|
@ -114,10 +118,8 @@ void CMonitor::onConnect(bool noRule) {
|
|||
ts = nullptr;
|
||||
}
|
||||
|
||||
if (!ts)
|
||||
PROTO::presentation->onPresented(m_self.lock(), Time::steadyNow(), event.refresh, event.seq, event.flags);
|
||||
else
|
||||
PROTO::presentation->onPresented(m_self.lock(), Time::fromTimespec(event.when), event.refresh, event.seq, event.flags);
|
||||
auto now = ts ? Time::fromTimespec(event.when) : Time::steadyNow();
|
||||
PROTO::presentation->onPresented(m_self.lock(), now, event.refresh, event.seq, event.flags);
|
||||
|
||||
if (m_zoomAnimFrameCounter < 5) {
|
||||
m_zoomAnimFrameCounter++;
|
||||
|
|
@ -140,7 +142,7 @@ void CMonitor::onConnect(bool noRule) {
|
|||
});
|
||||
}
|
||||
|
||||
m_frameScheduler->onPresented();
|
||||
m_frameScheduler->onPresented(now);
|
||||
|
||||
m_events.presented.emit();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "../Compositor.hpp"
|
||||
#include "../render/Renderer.hpp"
|
||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "../managers/SurfaceManager.hpp"
|
||||
|
||||
CMonitorFrameScheduler::CMonitorFrameScheduler(PHLMONITOR m) : m_monitor(m) {
|
||||
;
|
||||
|
|
@ -16,7 +17,7 @@ bool CMonitorFrameScheduler::newSchedulingEnabled() {
|
|||
|
||||
void CMonitorFrameScheduler::onSyncFired() {
|
||||
|
||||
if (!newSchedulingEnabled())
|
||||
if (!newSchedulingEnabled() || m_skipThird)
|
||||
return;
|
||||
|
||||
// Sync fired: reset submitted state, set as rendered. Check the last render time. If we are running
|
||||
|
|
@ -25,21 +26,27 @@ void CMonitorFrameScheduler::onSyncFired() {
|
|||
if (std::chrono::duration_cast<std::chrono::microseconds>(hrc::now() - m_lastRenderBegun).count() / 1000.F < 1000.F / m_monitor->m_refreshRate) {
|
||||
// we are in. Frame is valid. We can just render as normal.
|
||||
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onSyncFired, didn't miss.", m_monitor->m_name);
|
||||
if (!m_renderAtFrame)
|
||||
g_pCompositor->scheduleFrameForMonitor(m_monitor.lock());
|
||||
|
||||
m_renderAtFrame = true;
|
||||
return;
|
||||
} else if (m_renderAtFrame) {
|
||||
m_renderAtFrame = false;
|
||||
g_pCompositor->scheduleFrameForMonitor(m_monitor.lock());
|
||||
return;
|
||||
}
|
||||
|
||||
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onSyncFired, missed.", m_monitor->m_name);
|
||||
|
||||
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onSyncFired, rendering third frame.", m_monitor->m_name);
|
||||
// we are out. The frame is taking too long to render. Begin rendering immediately, but don't commit yet.
|
||||
m_pendingThird = true;
|
||||
m_renderAtFrame = false; // block frame rendering, we already scheduled
|
||||
|
||||
m_lastRenderBegun = hrc::now();
|
||||
|
||||
// get a ref to ourselves. renderMonitor can destroy this scheduler if it decides to perform a monitor reload
|
||||
// FIXME: this is horrible. "renderMonitor" should not be able to do that.
|
||||
auto self = m_self;
|
||||
g_pSurfaceManager->sendScheduledFrames(m_monitor, Time::steadyNow());
|
||||
|
||||
g_pHyprRenderer->renderMonitor(m_monitor.lock(), false);
|
||||
|
||||
|
|
@ -49,31 +56,28 @@ void CMonitorFrameScheduler::onSyncFired() {
|
|||
onFinishRender();
|
||||
}
|
||||
|
||||
void CMonitorFrameScheduler::onPresented() {
|
||||
void CMonitorFrameScheduler::onPresented(const Time::steady_tp& now) {
|
||||
g_pSurfaceManager->sendScheduledFrames(m_monitor, now);
|
||||
|
||||
if (!newSchedulingEnabled())
|
||||
return;
|
||||
|
||||
m_skipThird = false;
|
||||
|
||||
if (!m_pendingThird)
|
||||
return;
|
||||
|
||||
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onPresented, missed, committing pending.", m_monitor->m_name);
|
||||
|
||||
m_pendingThird = false;
|
||||
auto mon = m_monitor.lock();
|
||||
|
||||
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onPresented, missed, committing pending at the earliest convenience.", m_monitor->m_name);
|
||||
|
||||
m_pendingThird = false;
|
||||
|
||||
g_pEventLoopManager->doLater([m = m_monitor.lock()] {
|
||||
if (!m)
|
||||
return;
|
||||
g_pHyprRenderer->commitPendingAndDoExplicitSync(m); // commit the pending frame. If it didn't fire yet (is not rendered) it doesn't matter. Syncs will wait.
|
||||
g_pHyprRenderer->commitPendingAndDoExplicitSync(mon, true); // commit the pending frame. If it didn't fire yet (is not rendered) it doesn't matter. Syncs will wait.
|
||||
m_skipThird = true;
|
||||
|
||||
// schedule a frame: we might have some missed damage, which got cleared due to the above commit.
|
||||
// TODO: this is not always necessary, but doesn't hurt in general. We likely won't hit this if nothing's happening anyways.
|
||||
if (m->m_damage.hasChanged())
|
||||
g_pCompositor->scheduleFrameForMonitor(m);
|
||||
});
|
||||
if (mon->m_damage.hasChanged())
|
||||
g_pCompositor->scheduleFrameForMonitor(mon);
|
||||
}
|
||||
|
||||
void CMonitorFrameScheduler::onFrame() {
|
||||
|
|
@ -100,20 +104,12 @@ void CMonitorFrameScheduler::onFrame() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!m_renderAtFrame) {
|
||||
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> frame event, but m_renderAtFrame = false.", m_monitor->m_name);
|
||||
return;
|
||||
}
|
||||
|
||||
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> frame event, render = true, rendering normally.", m_monitor->m_name);
|
||||
|
||||
m_lastRenderBegun = hrc::now();
|
||||
|
||||
// get a ref to ourselves. renderMonitor can destroy this scheduler if it decides to perform a monitor reload
|
||||
// FIXME: this is horrible. "renderMonitor" should not be able to do that.
|
||||
auto self = m_self;
|
||||
|
||||
g_pHyprRenderer->renderMonitor(m_monitor.lock());
|
||||
g_pHyprRenderer->renderMonitor(m_monitor.lock(), true, (m_renderAtFrame && !m_pendingThird));
|
||||
|
||||
if (!self)
|
||||
return;
|
||||
|
|
@ -122,8 +118,12 @@ void CMonitorFrameScheduler::onFrame() {
|
|||
}
|
||||
|
||||
void CMonitorFrameScheduler::onFinishRender() {
|
||||
m_sync = CEGLSync::create(); // this destroys the old sync
|
||||
g_pEventLoopManager->doOnReadable(m_sync->fd().duplicate(), [this, self = m_self] {
|
||||
if (!m_monitor->m_inFence.isValid()) {
|
||||
Log::logger->log(Log::ERR, "CMonitorFrameScheduler: {} -> onFinishRender, m_inFence is not valid.", m_monitor->m_name);
|
||||
return;
|
||||
}
|
||||
|
||||
g_pEventLoopManager->doOnReadable(m_monitor->m_inFence.duplicate(), [this, self = m_self] {
|
||||
if (!self) // might've gotten destroyed
|
||||
return;
|
||||
onSyncFired();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class CMonitorFrameScheduler {
|
|||
CMonitorFrameScheduler& operator=(CMonitorFrameScheduler&&) = delete;
|
||||
|
||||
void onSyncFired();
|
||||
void onPresented();
|
||||
void onPresented(const Time::steady_tp& when);
|
||||
void onFrame();
|
||||
|
||||
private:
|
||||
|
|
@ -28,12 +28,10 @@ class CMonitorFrameScheduler {
|
|||
|
||||
bool m_renderAtFrame = true;
|
||||
bool m_pendingThird = false;
|
||||
bool m_skipThird = false;
|
||||
hrc::time_point m_lastRenderBegun;
|
||||
|
||||
PHLMONITORREF m_monitor;
|
||||
|
||||
UP<CEGLSync> m_sync;
|
||||
|
||||
WP<CMonitorFrameScheduler> m_self;
|
||||
|
||||
friend class CMonitor;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "../desktop/state/FocusState.hpp"
|
||||
#include "SeatManager.hpp"
|
||||
#include "../helpers/time/Time.hpp"
|
||||
#include "../managers/SurfaceManager.hpp"
|
||||
#include <cstring>
|
||||
#include <gbm.h>
|
||||
#include <cairo/cairo.h>
|
||||
|
|
@ -160,7 +161,7 @@ void CPointerManager::setCursorSurface(SP<Desktop::View::CWLSurface> surf, const
|
|||
|
||||
if (surf->resource()->m_current.texture) {
|
||||
m_currentCursorImage.size = surf->resource()->m_current.bufferSize;
|
||||
surf->resource()->frame(Time::steadyNow());
|
||||
g_pSurfaceManager->scheduleForFrame(Desktop::focusState()->monitor(), surf->resource());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -597,7 +598,8 @@ void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, const Time::
|
|||
|
||||
if (!state->hardwareFailed && state->softwareLocks == 0 && !forceRender) {
|
||||
if (m_currentCursorImage.surface)
|
||||
m_currentCursorImage.surface->resource()->frame(now);
|
||||
g_pSurfaceManager->scheduleForFrame(pMonitor, m_currentCursorImage.surface->resource());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -632,7 +634,7 @@ void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, const Time::
|
|||
g_pHyprRenderer->m_renderPass.add(makeUnique<CTexPassElement>(std::move(data)));
|
||||
|
||||
if (m_currentCursorImage.surface)
|
||||
m_currentCursorImage.surface->resource()->frame(now);
|
||||
g_pSurfaceManager->scheduleForFrame(pMonitor, m_currentCursorImage.surface->resource());
|
||||
}
|
||||
|
||||
Vector2D CPointerManager::getCursorPosForMonitor(PHLMONITOR pMonitor) {
|
||||
|
|
|
|||
127
src/managers/SurfaceManager.cpp
Normal file
127
src/managers/SurfaceManager.cpp
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#include "SurfaceManager.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "render/OpenGL.hpp"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/sync_file.h>
|
||||
#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
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool CSurfaceManager::addBuffer(PHLMONITORREF monitor, const CHLBufferReference& buf) {
|
||||
if (!monitor)
|
||||
return false;
|
||||
|
||||
auto it = std::ranges::find_if(m_buffers[monitor], [&buf](auto& b) { return b == buf; });
|
||||
|
||||
if (it != m_buffers[monitor].end())
|
||||
return false;
|
||||
|
||||
m_buffers[monitor].emplace_back(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSurfaceManager::addFrameCallback(WP<CWLSurfaceResource> surf, SP<CWLCallbackResource> cb) {
|
||||
auto it = std::ranges::find_if(m_frameCallbacks[surf], [&cb](auto& c) { return c == cb; });
|
||||
|
||||
if (it != m_frameCallbacks[surf].end())
|
||||
return false;
|
||||
|
||||
m_frameCallbacks[surf].emplace_back(cb);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSurfaceManager::addFence(PHLMONITORREF monitor) {
|
||||
if (g_pHyprOpenGL->explicitSyncSupported() && monitor->m_inFence.isValid()) {
|
||||
for (auto& b : m_buffers[monitor]) {
|
||||
if (!b->m_syncReleasers.empty()) {
|
||||
for (auto& releaser : b->m_syncReleasers) {
|
||||
releaser->addSyncFileFd(monitor->m_inFence);
|
||||
}
|
||||
} else {
|
||||
if (b->m_syncDropFd.isValid())
|
||||
b->m_syncDropFd = mergeSyncFds(b->m_syncDropFd, monitor->m_inFence.duplicate());
|
||||
else
|
||||
b->m_syncDropFd = monitor->m_inFence.duplicate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSurfaceManager::dropBuffers(PHLMONITORREF monitor) {
|
||||
if (g_pHyprOpenGL->explicitSyncSupported()) {
|
||||
std::erase_if(m_buffers[monitor], [](auto& b) { return !b->m_syncReleasers.empty(); });
|
||||
for (auto& b : m_buffers[monitor]) {
|
||||
g_pEventLoopManager->doOnReadable(b->m_syncDropFd.duplicate(), [buf = b] mutable {});
|
||||
}
|
||||
}
|
||||
|
||||
m_buffers[monitor].clear();
|
||||
std::erase_if(m_buffers, [](auto& b) { return !b.first; }); // if monitor is gone.
|
||||
}
|
||||
|
||||
void CSurfaceManager::sendFrameCallbacks(WP<CWLSurfaceResource> surf, const Time::steady_tp& now) {
|
||||
if (surf) {
|
||||
for (auto& cb : m_frameCallbacks[surf]) {
|
||||
cb->send(now);
|
||||
}
|
||||
|
||||
m_frameCallbacks.erase(surf);
|
||||
}
|
||||
|
||||
std::erase_if(m_frameCallbacks, [](auto& b) { return !b.first; }); // if surface is gone.
|
||||
}
|
||||
|
||||
void CSurfaceManager::scheduleForFrame(PHLMONITORREF monitor, WP<CWLSurfaceResource> surf) {
|
||||
auto it = std::ranges::find_if(m_scheduledForFrame[monitor], [&surf](auto& b) { return b == surf; });
|
||||
|
||||
if (it != m_scheduledForFrame[monitor].end()) // already scheduled
|
||||
return;
|
||||
|
||||
m_scheduledForFrame[monitor].emplace_back(surf);
|
||||
}
|
||||
|
||||
void CSurfaceManager::sendScheduledFrames(PHLMONITORREF monitor, const Time::steady_tp& now) {
|
||||
for (auto& f : m_scheduledForFrame[monitor]) {
|
||||
sendFrameCallbacks(f, now);
|
||||
}
|
||||
|
||||
std::erase_if(m_scheduledForFrame, [](auto& b) { return !b.first; }); // if monitor is gone.
|
||||
}
|
||||
|
||||
void CSurfaceManager::destroy(PHLMONITORREF monitor) {
|
||||
m_buffers.erase(monitor);
|
||||
m_scheduledForFrame.erase(monitor);
|
||||
}
|
||||
25
src/managers/SurfaceManager.hpp
Normal file
25
src/managers/SurfaceManager.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "protocols/core/Compositor.hpp"
|
||||
#include "protocols/types/Buffer.hpp"
|
||||
|
||||
class CSurfaceManager {
|
||||
public:
|
||||
CSurfaceManager() = default;
|
||||
bool addBuffer(PHLMONITORREF monitor, const CHLBufferReference& buf);
|
||||
bool addFrameCallback(WP<CWLSurfaceResource>, SP<CWLCallbackResource>);
|
||||
void addFence(PHLMONITORREF monitor);
|
||||
void dropBuffers(PHLMONITORREF monitor);
|
||||
void sendFrameCallbacks(WP<CWLSurfaceResource> surf, const Time::steady_tp& now);
|
||||
void scheduleForFrame(PHLMONITORREF monitor, WP<CWLSurfaceResource> surf);
|
||||
void sendScheduledFrames(PHLMONITORREF monitor, const Time::steady_tp& now);
|
||||
void destroy(PHLMONITORREF monitor);
|
||||
|
||||
private:
|
||||
std::unordered_map<PHLMONITORREF, std::vector<CHLBufferReference>> m_buffers;
|
||||
std::unordered_map<WP<CWLSurfaceResource>, std::vector<SP<CWLCallbackResource>>> m_frameCallbacks;
|
||||
std::unordered_map<PHLMONITORREF, std::vector<WP<CWLSurfaceResource>>> m_scheduledForFrame;
|
||||
};
|
||||
|
||||
inline UP<CSurfaceManager> g_pSurfaceManager;
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
#include "../../render/Renderer.hpp"
|
||||
#include "config/ConfigValue.hpp"
|
||||
#include "../../managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "../../managers/SurfaceManager.hpp"
|
||||
#include "../../desktop/state/FocusState.hpp"
|
||||
#include "protocols/types/SurfaceRole.hpp"
|
||||
#include "render/Texture.hpp"
|
||||
#include <cstring>
|
||||
|
|
@ -225,10 +227,8 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
|
|||
m_pending.opaque = RG->m_region;
|
||||
});
|
||||
|
||||
m_resource->setFrame([this](CWlSurface* r, uint32_t id) {
|
||||
m_pending.updated.bits.frame = true;
|
||||
m_pending.callbacks.emplace_back(makeShared<CWLCallbackResource>(makeShared<CWlCallback>(m_client, 1, id)));
|
||||
});
|
||||
m_resource->setFrame(
|
||||
[this](CWlSurface* r, uint32_t id) { g_pSurfaceManager->addFrameCallback(m_self, makeShared<CWLCallbackResource>(makeShared<CWlCallback>(m_client, 1, id))); });
|
||||
|
||||
m_resource->setOffset([this](CWlSurface* r, int32_t x, int32_t y) {
|
||||
m_pending.updated.bits.offset = true;
|
||||
|
|
@ -328,17 +328,6 @@ void CWLSurfaceResource::sendPreferredScale(int32_t scale) {
|
|||
m_resource->sendPreferredBufferScale(scale);
|
||||
}
|
||||
|
||||
void CWLSurfaceResource::frame(const Time::steady_tp& now) {
|
||||
if (m_current.callbacks.empty())
|
||||
return;
|
||||
|
||||
for (auto const& c : m_current.callbacks) {
|
||||
c->send(now);
|
||||
}
|
||||
|
||||
m_current.callbacks.clear();
|
||||
}
|
||||
|
||||
void CWLSurfaceResource::resetRole() {
|
||||
m_role = makeShared<CDefaultSurfaceRole>();
|
||||
}
|
||||
|
|
@ -445,7 +434,7 @@ void CWLSurfaceResource::map() {
|
|||
|
||||
m_mapped = true;
|
||||
|
||||
frame(Time::steadyNow());
|
||||
g_pSurfaceManager->scheduleForFrame(Desktop::focusState()->monitor(), m_self);
|
||||
|
||||
m_current.bufferDamage = CBox{{}, m_current.bufferSize};
|
||||
m_pending.bufferDamage = CBox{{}, m_pending.bufferSize};
|
||||
|
|
@ -653,7 +642,6 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) {
|
|||
}
|
||||
|
||||
void CWLSurfaceResource::presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded) {
|
||||
frame(when);
|
||||
auto FEEDBACK = makeUnique<CQueuedPresentationData>(m_self.lock());
|
||||
FEEDBACK->attachMonitor(pMonitor);
|
||||
if (discarded)
|
||||
|
|
@ -661,6 +649,7 @@ void CWLSurfaceResource::presentFeedback(const Time::steady_tp& when, PHLMONITOR
|
|||
else
|
||||
FEEDBACK->presented();
|
||||
PROTO::presentation->queueData(std::move(FEEDBACK));
|
||||
g_pSurfaceManager->scheduleForFrame(pMonitor, m_self);
|
||||
}
|
||||
|
||||
CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> resource_) : m_resource(resource_) {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ class CWLSurfaceResource {
|
|||
void leave(PHLMONITOR monitor);
|
||||
void sendPreferredTransform(wl_output_transform t);
|
||||
void sendPreferredScale(int32_t scale);
|
||||
void frame(const Time::steady_tp& now);
|
||||
uint32_t id();
|
||||
void map();
|
||||
void unmap();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "../../helpers/Monitor.hpp"
|
||||
#include "../../render/Renderer.hpp"
|
||||
#include "../../xwayland/Dnd.hpp"
|
||||
#include "../../managers/SurfaceManager.hpp"
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
CWLDataOfferResource::CWLDataOfferResource(SP<CWlDataOffer> resource_, SP<IDataSource> source_) : m_source(source_), m_resource(resource_) {
|
||||
|
|
@ -836,7 +837,7 @@ void CWLDataDeviceProtocol::renderDND(PHLMONITOR pMonitor, const Time::steady_tp
|
|||
CBox damageBox = CBox{surfacePos, m_dnd.dndSurface->m_current.size}.expand(5);
|
||||
g_pHyprRenderer->damageBox(damageBox);
|
||||
|
||||
m_dnd.dndSurface->frame(when);
|
||||
g_pSurfaceManager->scheduleForFrame(pMonitor, m_dnd.dndSurface);
|
||||
}
|
||||
|
||||
bool CWLDataDeviceProtocol::dndActive() {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class IHLBuffer : public Aquamarine::IBuffer {
|
|||
SP<CWLBufferResource> m_resource;
|
||||
std::vector<UP<CSyncReleaser>> m_syncReleasers;
|
||||
Hyprutils::OS::CFileDescriptor m_syncFd;
|
||||
Hyprutils::OS::CFileDescriptor m_syncDropFd;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener backendRelease;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ void SSurfaceState::reset() {
|
|||
damage.clear();
|
||||
bufferDamage.clear();
|
||||
|
||||
callbacks.clear();
|
||||
lockMask = LOCK_REASON_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -107,9 +106,4 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) {
|
|||
|
||||
if (ref.updated.bits.acked)
|
||||
ackedSize = ref.ackedSize;
|
||||
|
||||
if (ref.updated.bits.frame) {
|
||||
callbacks.insert(callbacks.end(), std::make_move_iterator(ref.callbacks.begin()), std::make_move_iterator(ref.callbacks.end()));
|
||||
ref.callbacks.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ struct SSurfaceState {
|
|||
bool viewport : 1;
|
||||
bool acquire : 1;
|
||||
bool acked : 1;
|
||||
bool frame : 1;
|
||||
} bits;
|
||||
} updated;
|
||||
|
||||
|
|
@ -68,9 +67,6 @@ struct SSurfaceState {
|
|||
// for xdg_shell resizing
|
||||
Vector2D ackedSize;
|
||||
|
||||
// for wl_surface::frame callbacks.
|
||||
std::vector<SP<CWLCallbackResource>> callbacks;
|
||||
|
||||
// viewporter protocol surface state
|
||||
struct {
|
||||
bool hasDestination = false;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "../desktop/view/LayerSurface.hpp"
|
||||
#include "../desktop/view/GlobalViewMethods.hpp"
|
||||
#include "../desktop/state/FocusState.hpp"
|
||||
#include "../managers/SurfaceManager.hpp"
|
||||
#include "../protocols/SessionLock.hpp"
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../protocols/XDGShell.hpp"
|
||||
|
|
@ -170,9 +171,10 @@ CHyprRenderer::CHyprRenderer() {
|
|||
if (!w->wlSurface() || !w->wlSurface()->resource() || shouldRenderWindow(w.lock()))
|
||||
continue;
|
||||
|
||||
w->wlSurface()->resource()->frame(Time::steadyNow());
|
||||
g_pSurfaceManager->scheduleForFrame(Desktop::focusState()->monitor(), w->wlSurface()->resource());
|
||||
auto FEEDBACK = makeUnique<CQueuedPresentationData>(w->wlSurface()->resource());
|
||||
FEEDBACK->attachMonitor(Desktop::focusState()->monitor());
|
||||
|
||||
FEEDBACK->discarded();
|
||||
PROTO::presentation->queueData(std::move(FEEDBACK));
|
||||
}
|
||||
|
|
@ -1260,7 +1262,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP<CWLSurfaceResour
|
|||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
|
||||
void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit, bool dropBuffers) {
|
||||
static std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point renderStartOverlay = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
|
|
@ -1488,7 +1490,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
|
|||
Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC);
|
||||
|
||||
if (commit)
|
||||
commitPendingAndDoExplicitSync(pMonitor);
|
||||
commitPendingAndDoExplicitSync(pMonitor, dropBuffers);
|
||||
|
||||
if (shouldTear)
|
||||
pMonitor->m_tearingState.busy = true;
|
||||
|
|
@ -1555,7 +1557,7 @@ static hdr_output_metadata createHDRMetadata(SImageDescription settings, S
|
|||
};
|
||||
}
|
||||
|
||||
bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
||||
bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor, bool dropBuffers) {
|
||||
static auto PCT = CConfigValue<Hyprlang::INT>("render:send_content_type");
|
||||
static auto PPASS = CConfigValue<Hyprlang::INT>("render:cm_fs_passthrough");
|
||||
static auto PAUTOHDR = CConfigValue<Hyprlang::INT>("render:cm_auto_hdr");
|
||||
|
|
@ -1674,6 +1676,28 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
|
|||
|
||||
pMonitor->m_previousFSWindow = FS_WINDOW;
|
||||
|
||||
if (!g_pHyprOpenGL->explicitSyncSupported()) {
|
||||
static auto PNVIDIAANTIFLICKER = CConfigValue<Hyprlang::INT>("opengl:nvidia_anti_flicker");
|
||||
Log::logger->log(Log::TRACE, "renderer: Explicit sync unsupported, falling back to implicit in endRender");
|
||||
|
||||
// nvidia doesn't have implicit sync, so we have to explicitly wait here, llvmpipe and other software renderer seems to bug out aswell.
|
||||
if ((isNvidia() && *PNVIDIAANTIFLICKER) || isSoftware())
|
||||
glFinish();
|
||||
else
|
||||
glFlush(); // mark an implicit sync point
|
||||
|
||||
pMonitor->m_inFence.reset();
|
||||
} else {
|
||||
if (pMonitor->m_inFence.isValid()) {
|
||||
if (m_renderMode == RENDER_MODE_NORMAL) {
|
||||
pMonitor->m_output->state->setExplicitInFence(pMonitor->m_inFence.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dropBuffers)
|
||||
g_pSurfaceManager->dropBuffers(pMonitor);
|
||||
|
||||
bool ok = pMonitor->m_state.commit();
|
||||
if (!ok) {
|
||||
if (pMonitor->m_inFence.isValid()) {
|
||||
|
|
@ -1714,7 +1738,7 @@ void CHyprRenderer::sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE
|
|||
if (!view->aliveAndVisible())
|
||||
continue;
|
||||
|
||||
view->wlSurface()->resource()->frame(now);
|
||||
g_pSurfaceManager->scheduleForFrame(pMonitor, view->wlSurface()->resource());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2358,43 +2382,30 @@ void CHyprRenderer::endRender(const std::function<void()>& renderingDoneCallback
|
|||
else
|
||||
glFlush(); // mark an implicit sync point
|
||||
|
||||
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
||||
if (renderingDoneCallback)
|
||||
renderingDoneCallback();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
UP<CEGLSync> eglSync = CEGLSync::create();
|
||||
if (eglSync && eglSync->isValid()) {
|
||||
for (auto const& buf : m_usedAsyncBuffers) {
|
||||
for (const auto& releaser : buf->m_syncReleasers) {
|
||||
releaser->addSyncFileFd(eglSync->fd());
|
||||
}
|
||||
}
|
||||
|
||||
// release buffer refs with release points now, since syncReleaser handles actual buffer release based on EGLSync
|
||||
std::erase_if(m_usedAsyncBuffers, [](const auto& buf) { return !buf->m_syncReleasers.empty(); });
|
||||
|
||||
// release buffer refs without release points when EGLSync sync_file/fence is signalled
|
||||
g_pEventLoopManager->doOnReadable(eglSync->fd().duplicate(), [renderingDoneCallback, prevbfs = std::move(m_usedAsyncBuffers)]() mutable {
|
||||
prevbfs.clear();
|
||||
if (renderingDoneCallback) {
|
||||
g_pEventLoopManager->doOnReadable(eglSync->fd().duplicate(), [renderingDoneCallback]() {
|
||||
if (renderingDoneCallback)
|
||||
renderingDoneCallback();
|
||||
});
|
||||
m_usedAsyncBuffers.clear();
|
||||
}
|
||||
|
||||
if (m_renderMode == RENDER_MODE_NORMAL) {
|
||||
PMONITOR->m_inFence = eglSync->takeFd();
|
||||
PMONITOR->m_output->state->setExplicitInFence(PMONITOR->m_inFence.get());
|
||||
g_pSurfaceManager->addFence(PMONITOR);
|
||||
}
|
||||
} else {
|
||||
Log::logger->log(Log::ERR, "renderer: Explicit sync failed, releasing resources");
|
||||
|
||||
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
||||
if (renderingDoneCallback)
|
||||
Log::logger->log(Log::ERR, "renderer: Explicit sync failed, calling renderingDoneCallback without sync");
|
||||
if (renderingDoneCallback) {
|
||||
Log::logger->log(Log::ERR, "renderer: Explicit sync failed, calling renderingDoneCallback without sync");
|
||||
renderingDoneCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class CHyprRenderer {
|
|||
CHyprRenderer();
|
||||
~CHyprRenderer();
|
||||
|
||||
void renderMonitor(PHLMONITOR pMonitor, bool commit = true);
|
||||
void renderMonitor(PHLMONITOR pMonitor, bool commit = true, bool dropBuffers = true);
|
||||
void arrangeLayersForMonitor(const MONITORID&);
|
||||
void damageSurface(SP<CWLSurfaceResource>, double, double, double scale = 1.0);
|
||||
void damageWindow(PHLWINDOW, bool forceFull = false);
|
||||
|
|
@ -105,8 +105,6 @@ class CHyprRenderer {
|
|||
wl_event_source* m_crashingLoop = nullptr;
|
||||
wl_event_source* m_cursorTicker = nullptr;
|
||||
|
||||
std::vector<CHLBufferReference> m_usedAsyncBuffers;
|
||||
|
||||
struct {
|
||||
int hotspotX = 0;
|
||||
int hotspotY = 0;
|
||||
|
|
@ -135,7 +133,7 @@ class CHyprRenderer {
|
|||
void renderSessionLockMissing(PHLMONITOR pMonitor);
|
||||
void renderBackground(PHLMONITOR pMonitor);
|
||||
|
||||
bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor);
|
||||
bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor, bool dropBuffers);
|
||||
|
||||
bool shouldBlur(PHLLS ls);
|
||||
bool shouldBlur(PHLWINDOW w);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
#include "../../protocols/core/Compositor.hpp"
|
||||
#include "../../protocols/DRMSyncobj.hpp"
|
||||
#include "../../managers/input/InputManager.hpp"
|
||||
#include "../../managers/SurfaceManager.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
#include <hyprutils/math/Box.hpp>
|
||||
#include <hyprutils/math/Vector2D.hpp>
|
||||
|
|
@ -154,8 +156,30 @@ void CSurfacePassElement::draw(const CRegion& damage) {
|
|||
|
||||
// add async (dmabuf) buffers to usedBuffers so we can handle release later
|
||||
// sync (shm) buffers will be released in commitState, so no need to track them here
|
||||
if (m_data.surface->m_current.buffer && !m_data.surface->m_current.buffer->isSynchronous())
|
||||
g_pHyprRenderer->m_usedAsyncBuffers.emplace_back(m_data.surface->m_current.buffer);
|
||||
if (m_data.surface->m_current.buffer && !m_data.surface->m_current.buffer->isSynchronous()) {
|
||||
for (auto& m : g_pCompositor->m_monitors) {
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
if (m_data.pMonitor == m || (m_data.pWindow && m_data.pWindow->visibleOnMonitor(m))) {
|
||||
g_pSurfaceManager->addBuffer(m, m_data.surface->m_current.buffer);
|
||||
|
||||
if (m_data.pMonitor != m) {
|
||||
CBox wbox = {m_data.pWindow->m_realPosition->value(), m_data.pWindow->m_realSize->value()};
|
||||
if (m_data.pWindow->m_isFloating)
|
||||
wbox = m_data.pWindow->getFullWindowBoundingBox();
|
||||
|
||||
CBox monbox = {m->m_position, m->m_size};
|
||||
CBox damageBox = wbox.intersection(monbox);
|
||||
|
||||
if (!damageBox.empty()) {
|
||||
m->addDamage(damageBox);
|
||||
g_pCompositor->scheduleFrameForMonitor(m, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->blend(true);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue