mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-24 02:24:14 -05:00
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:
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user