internal: reduce some profiled churn (#15705)

* fullscreen: resolve fs handlers once per query

getFullscreenHandlerName() resolved the handlers twice by calling
getFsHandler() for both the layout and default case, and getFsHandler()
itself re-walked the workspace algorithm chain on every call.

Resolve SFsHandlersForWorkspace once and pass it to an overload of
getFullscreenHandlerName(), derive layoutHandled from the resolved
handler name instead of a second layoutManagedFS() pass, and hoist the
repeated algorithm()/tiledAlgo()/floatingAlgo() lookups in
getFsHandlersForWorkspace() into locals.

* damage: compute the surface box once in damageSurface

getSurfaceBoxGlobal() was computed twice per damage event: once for the
frame scheduling hack and again inside computeDamage(). Compute it once
in damageSurface() and pass it into computeDamage(), which now takes the
box as an argument.

* sync: check the timeline before making an eventfd

since most points are signaled when we reach this, we reduce the
churn of making eventfd, ioctl, and poll + close.
This commit is contained in:
Tom Englund
2026-08-02 12:02:49 +02:00
committed by GitHub
parent 88c6386994
commit 41b0fffdec
6 changed files with 63 additions and 27 deletions
+3 -4
View File
@@ -81,7 +81,7 @@ Vector2D CWLSurface::getViewporterCorrectedSize() const {
return m_resource->m_current.viewport.hasDestination ? m_resource->m_current.viewport.destination : m_resource->m_current.bufferSize;
}
CRegion CWLSurface::computeDamage() const {
CRegion CWLSurface::computeDamage(const std::optional<CBox>& box) const {
if (!m_resource->m_current.texture)
return {};
@@ -107,7 +107,6 @@ CRegion CWLSurface::computeDamage() const {
// go from buffer coords in the damage to hl logical
const auto BOX = getSurfaceBoxGlobal();
const auto SURFSIZE = m_resource->m_current.size;
if (SURFSIZE.x <= 0 || SURFSIZE.y <= 0)
return {};
@@ -115,8 +114,8 @@ CRegion CWLSurface::computeDamage() const {
const Vector2D SCALE = SURFSIZE / m_resource->m_current.bufferSize;
damage.scale(SCALE);
if (BOX.has_value()) {
auto boxSize = BOX->size();
if (box.has_value()) {
auto boxSize = box->size();
if (m_view->type() == VIEW_TYPE_WINDOW) {
const auto WINDOW = dynamicPointerCast<CWindow>(m_view.lock());
+1 -1
View File
@@ -37,7 +37,7 @@ namespace Desktop::View {
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
Vector2D correctSmallVecBuf() const; // returns a corrective vector for small() surfaces, in BL coords
Vector2D getViewporterCorrectedSize() const;
CRegion computeDamage() const; // logical coordinates. May be wrong if the surface is unassigned
CRegion computeDamage(const std::optional<CBox>& box) const; // logical coordinates. May be wrong if the surface is unassigned
bool keyboardFocusable() const;
void sendScale(float scale) const;
void sendTransform(wl_output_transform xform) const;
+12
View File
@@ -65,6 +65,18 @@ std::optional<bool> CSyncTimeline::check(uint64_t point, uint32_t flags) {
}
WP<SReadableWaiter> CSyncTimeline::addWaiter(std::function<void()>&& waiter, uint64_t point, uint32_t flags) {
// any failure (incl. -EINVAL on an unmaterialized point) means "not signaled"
auto tryCheck = [this, &point, &flags]() {
uint32_t signaled = 0;
return drmSyncobjTimelineWait(m_drmFD, &m_handle, &point, 1, 0, flags, &signaled) == 0;
};
// skip the eventfd + ioctl + poll + close dance if the point is already there
if (tryCheck()) {
waiter();
return {};
}
auto eventFd = CFileDescriptor(eventfd(0, EFD_CLOEXEC));
if (!eventFd.isValid()) {
@@ -243,10 +243,16 @@ eFullscreenHandler CFullscreenController::getFullscreenHandlerName(const PHLWIND
if (!window)
return FULLSCREEN_HANDLER_NONE;
// IMPORTANT: no layoutHandled value passed -> infinite recursion.
const auto LAYOUT_FS_HANDLER = getFsHandler(window, true);
// IMPORTANT: no layoutHandled value passed -> infinite recursion.
const auto DEFAULT_FS_HANDLER = getFsHandler(window, false);
return getFullscreenHandlerName(window, getFsHandlersForWorkspace(window->m_workspace));
}
eFullscreenHandler CFullscreenController::getFullscreenHandlerName(const PHLWINDOW window, const SFsHandlersForWorkspace& handlers) {
if (!window)
return FULLSCREEN_HANDLER_NONE;
// IMPORTANT: don't route through getFsHandler() without a layoutHandled value -> infinite recursion.
const auto LAYOUT_FS_HANDLER = window->m_isFloating ? handlers.FLOATING_FS_HANDLER : handlers.TILED_FS_HANDLER;
const auto DEFAULT_FS_HANDLER = window->m_isFloating ? handlers.FLOATING_FS_HANDLER : handlers.TILED_DEFAULT_FS_HANDLER;
if (!LAYOUT_FS_HANDLER || !DEFAULT_FS_HANDLER) {
Log::logger->log(Log::ERR, "window {} doesn't have FS handler assinged. This should never happen", window->m_title);
@@ -523,25 +529,42 @@ WP<IFullscreenHandler> CFullscreenController::getFsHandler(const PHLWINDOW windo
if (!window)
return nullptr;
if (!layoutHandled.has_value())
layoutHandled = layoutManagedFS(window);
const auto HANDLERS = getFsHandlersForWorkspace(window->m_workspace);
if (!HANDLERS.TILED_FS_HANDLER || !HANDLERS.TILED_DEFAULT_FS_HANDLER || !HANDLERS.FLOATING_FS_HANDLER)
return nullptr;
if (!layoutHandled.has_value()) {
const auto FS_HANDLER_NAME = getFullscreenHandlerName(window, HANDLERS);
if (FS_HANDLER_NAME == FULLSCREEN_HANDLER_NONE)
Log::logger->log(Log::ERR, "window {} doesn't have FS handler assinged. This should never happen", window->m_title);
// If a window is not FS at all, we consider its handler to be layout if it is in a workspace with a layout that implements their custom FS behaviour.
layoutHandled = FS_HANDLER_NAME & FULLSCREEN_HANDLER_LAYOUT;
}
return (layoutHandled.value() ? (window->m_isFloating ? HANDLERS.FLOATING_FS_HANDLER : HANDLERS.TILED_FS_HANDLER) :
(window->m_isFloating ? HANDLERS.FLOATING_FS_HANDLER : HANDLERS.TILED_DEFAULT_FS_HANDLER));
}
CFullscreenController::SFsHandlersForWorkspace CFullscreenController::getFsHandlersForWorkspace(const PHLWORKSPACE workspace) const {
if (!workspace || !workspace->m_space || !workspace->m_space->algorithm() || !workspace->m_space->algorithm()->floatingAlgo() || !workspace->m_space->algorithm()->tiledAlgo())
if (!workspace || !workspace->m_space)
return {};
const auto TILED_FS_HANDLER = workspace->m_space->algorithm()->tiledAlgo()->getFSHandler();
const auto TILED_DEFAULT_FS_HANDLER = workspace->m_space->algorithm()->tiledAlgo()->IModeAlgorithm::getFSHandler();
const auto ALGO = workspace->m_space->algorithm();
if (!ALGO)
return {};
const auto FLOATING_FS_HANDLER = workspace->m_space->algorithm()->floatingAlgo()->getFSHandler();
const auto& TILED_ALGO = ALGO->tiledAlgo();
const auto& FLOATING_ALGO = ALGO->floatingAlgo();
if (!TILED_ALGO || !FLOATING_ALGO)
return {};
const auto TILED_FS_HANDLER = TILED_ALGO->getFSHandler();
const auto TILED_DEFAULT_FS_HANDLER = TILED_ALGO->IModeAlgorithm::getFSHandler();
const auto FLOATING_FS_HANDLER = FLOATING_ALGO->getFSHandler();
if (!TILED_FS_HANDLER || !TILED_DEFAULT_FS_HANDLER || !FLOATING_FS_HANDLER) {
Log::logger->log(Log::ERR, "workspace ID:{} doesn't have FS handlers assinged. This should never happen", workspace->m_id);
@@ -106,6 +106,9 @@ namespace Fullscreen {
SFsHandlersForWorkspace getFsHandlersForWorkspace(const PHLWORKSPACE workspace) const;
// avoids re-resolving the handlers when the caller already has them
eFullscreenHandler getFullscreenHandlerName(const PHLWINDOW window, const SFsHandlersForWorkspace& handlers);
// List of FSMODE_MAX windows
std::unordered_set<WP<Desktop::View::CWindow>> m_fsModeMaxWindows;
};
+10 -11
View File
@@ -2711,21 +2711,20 @@ void IHyprRenderer::damageSurface(SP<CWLSurfaceResource> pSurface, double x, dou
return;
}
// hack: schedule frame events
if (!WLSURF->resource()->m_current.callbacks.empty() && pSurface->m_hlSurface) {
const auto BOX = pSurface->m_hlSurface->getSurfaceBoxGlobal();
if (BOX && !BOX->empty()) {
for (auto const& m : State::monitorState()->monitors()) {
if (!m->m_output)
continue;
const auto SURFACE_BOX = WLSURF->getSurfaceBoxGlobal();
if (BOX->overlaps(m->logicalBox()))
m->scheduleFrame(Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME);
}
// hack: schedule frame events
if (!pSurface->m_current.callbacks.empty() && SURFACE_BOX && !SURFACE_BOX->empty()) {
for (auto const& m : State::monitorState()->monitors()) {
if (!m->m_output)
continue;
if (SURFACE_BOX->overlaps(m->logicalBox()))
m->scheduleFrame(Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME);
}
}
CRegion damageBox = WLSURF->computeDamage();
CRegion damageBox = WLSURF->computeDamage(SURFACE_BOX);
if (damageBox.empty())
return;