summaryrefslogtreecommitdiff
path: root/src/render/Renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/Renderer.cpp')
-rw-r--r--src/render/Renderer.cpp597
1 files changed, 305 insertions, 292 deletions
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index a7f3c941..82dfc887 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -2,6 +2,8 @@
#include "../Compositor.hpp"
#include "../helpers/math/Math.hpp"
#include <algorithm>
+#include <aquamarine/output/Output.hpp>
+#include <cstring>
#include "../config/ConfigValue.hpp"
#include "../managers/CursorManager.hpp"
#include "../managers/PointerManager.hpp"
@@ -13,6 +15,10 @@
#include "../protocols/PresentationTime.hpp"
#include "../protocols/core/DataDevice.hpp"
#include "../protocols/core/Compositor.hpp"
+#include "../protocols/DRMSyncobj.hpp"
+#include "../protocols/LinuxDMABUF.hpp"
+#include "../helpers/sync/SyncTimeline.hpp"
+#include "debug/Log.hpp"
extern "C" {
#include <xf86drm.h>
@@ -25,11 +31,11 @@ static int cursorTicker(void* data) {
}
CHyprRenderer::CHyprRenderer() {
- if (g_pCompositor->m_sWLRSession) {
- wlr_device* dev;
- wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) {
- const auto DRMV = drmGetVersion(dev->fd);
-
+ if (g_pCompositor->m_pAqBackend->hasSession()) {
+ for (auto& dev : g_pCompositor->m_pAqBackend->session->sessionDevices) {
+ const auto DRMV = drmGetVersion(dev->fd);
+ if (!DRMV)
+ continue;
std::string name = std::string{DRMV->name, DRMV->name_len};
std::transform(name.begin(), name.end(), name.begin(), tolower);
@@ -42,7 +48,7 @@ CHyprRenderer::CHyprRenderer() {
drmFreeVersion(DRMV);
}
} else {
- Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks");
+ Debug::log(LOG, "Aq backend has no session, omitting full DRM node checks");
const auto DRMV = drmGetVersion(g_pCompositor->m_iDRMFD);
@@ -108,6 +114,14 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
if (!TEXTURE->m_iTexID)
return;
+ // explicit sync: wait for the timeline, if any
+ if (surface->syncobj && surface->syncobj->acquireTimeline) {
+ if (!g_pHyprOpenGL->waitForTimelinePoint(surface->syncobj->acquireTimeline->timeline, surface->syncobj->acquirePoint)) {
+ Debug::log(ERR, "Renderer: failed to wait for explicit timeline");
+ return;
+ }
+ }
+
TRACY_GPU_ZONE("RenderSurface");
double outputX = -RDATA->pMonitor->vecPosition.x, outputY = -RDATA->pMonitor->vecPosition.y;
@@ -167,12 +181,10 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
if (windowBox.width <= 1 || windowBox.height <= 1) {
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
- surface->frame(RDATA->when);
- auto FEEDBACK = makeShared<CQueuedPresentationData>(surface);
- FEEDBACK->attachMonitor(RDATA->pMonitor);
- FEEDBACK->discarded();
- PROTO::presentation->queueData(FEEDBACK);
+ Debug::log(TRACE, "presentFeedback for invisible surface");
+ surface->presentFeedback(RDATA->when, RDATA->pMonitor);
}
+
return; // invisible
}
@@ -225,11 +237,8 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
}
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
- surface->frame(RDATA->when);
- auto FEEDBACK = makeShared<CQueuedPresentationData>(surface);
- FEEDBACK->attachMonitor(RDATA->pMonitor);
- FEEDBACK->presented();
- PROTO::presentation->queueData(FEEDBACK);
+ Debug::log(TRACE, "presentFeedback for visible surface");
+ surface->presentFeedback(RDATA->when, RDATA->pMonitor);
}
g_pHyprOpenGL->blend(true);
@@ -1079,53 +1088,6 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP<CWLSurfaceResour
}
}
-bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
- return false; // FIXME: fix when we move to new lib for backend.
-
- // if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked)
- // return false; // do not DS if this monitor is being mirrored. Will break the functionality.
-
- // if (!wlr_output_is_direct_scanout_allowed(pMonitor->output))
- // return false;
-
- // const auto PCANDIDATE = pMonitor->solitaryClient.lock();
-
- // if (!PCANDIDATE)
- // return false;
-
- // const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE);
-
- // if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform)
- // return false;
-
- // // finally, we should be GTG.
- // wlr_output_state_set_buffer(pMonitor->state.wlr(), &PSURFACE->buffer->base);
-
- // if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr()))
- // return false;
-
- // timespec now;
- // clock_gettime(CLOCK_MONOTONIC, &now);
- // PSURFACE->frame(&now);
- // auto FEEDBACK = makeShared<CQueuedPresentationData>(PSURFACE);
- // FEEDBACK->attachMonitor(pMonitor);
- // FEEDBACK->presented();
- // FEEDBACK->setPresentationType(true);
- // PROTO::presentation->queueData(FEEDBACK);
-
- // if (pMonitor->state.commit()) {
- // if (m_pLastScanout.expired()) {
- // m_pLastScanout = PCANDIDATE;
- // Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle);
- // }
- // } else {
- // m_pLastScanout.reset();
- // return false;
- // }
-
- // return true;
-}
-
void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
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();
@@ -1177,7 +1139,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
pMonitor->framesToSkip -= 1;
if (!pMonitor->noFrameSchedule)
- g_pCompositor->scheduleFrameForMonitor(pMonitor);
+ g_pCompositor->scheduleFrameForMonitor(pMonitor, Aquamarine::IOutput::AQ_SCHEDULE_RENDER_MONITOR);
else
Debug::log(LOG, "NoFrameSchedule hit for {}.", pMonitor->szName);
@@ -1205,6 +1167,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
}
+ if (!pMonitor->output->needsFrame && pMonitor->forceFullFrames == 0)
+ return;
+
// tearing and DS first
bool shouldTear = false;
if (pMonitor->tearingState.nextRenderTorn) {
@@ -1230,11 +1195,11 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
}
if (!*PNODIRECTSCANOUT && !shouldTear) {
- if (attemptDirectScanout(pMonitor)) {
+ if (pMonitor->attemptDirectScanout()) {
return;
- } else if (!m_pLastScanout.expired()) {
+ } else if (!pMonitor->lastScanout.expired()) {
Debug::log(LOG, "Left a direct scanout.");
- m_pLastScanout.reset();
+ pMonitor->lastScanout.reset();
}
}
@@ -1249,7 +1214,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
clock_gettime(CLOCK_MONOTONIC, &now);
// check the damage
- bool hasChanged = pMonitor->output->needs_frame || pMonitor->damage.hasChanged();
+ bool hasChanged = pMonitor->output->needsFrame || pMonitor->damage.hasChanged();
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0)
return;
@@ -1295,7 +1260,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
CRegion damage, finalDamage;
if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) {
Debug::log(ERR, "renderer: couldn't beginRender()!");
- pMonitor->state.clear();
return;
}
@@ -1316,11 +1280,11 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
// now, prep the damage, get the extended damage region
- wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring
+ damage.expand(BLURRADIUS); // expand for proper blurring
finalDamage = damage;
- wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring 2
+ damage.expand(BLURRADIUS); // expand for proper blurring
} else
finalDamage = damage;
}
@@ -1396,10 +1360,10 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
TRACY_GPU_COLLECT;
if (!pMonitor->mirrors.empty()) {
- CRegion frameDamage{};
+ CRegion frameDamage{finalDamage};
- const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform);
- wlr_region_transform(frameDamage.pixman(), finalDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
+ const auto TRANSFORM = invertTransform(pMonitor->transform);
+ frameDamage.transform(wlTransformToHyprutils(TRANSFORM), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
frameDamage.add(0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
@@ -1414,18 +1378,16 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
EMIT_HOOK_EVENT("render", RENDER_POST);
- pMonitor->state.wlr()->tearing_page_flip = shouldTear;
+ pMonitor->output->state->setPresentationMode(shouldTear ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE :
+ Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC);
- if (!pMonitor->state.commit()) {
- pMonitor->damage.damageEntire();
- return;
- }
+ commitPendingAndDoExplicitSync(pMonitor);
if (shouldTear)
pMonitor->tearingState.busy = true;
if (*PDAMAGEBLINK || *PVFR == 0 || pMonitor->pendingFrame)
- g_pCompositor->scheduleFrameForMonitor(pMonitor);
+ g_pCompositor->scheduleFrameForMonitor(pMonitor, Aquamarine::IOutput::AQ_SCHEDULE_RENDER_MONITOR);
pMonitor->pendingFrame = false;
@@ -1442,6 +1404,63 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
}
}
+bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) {
+ static auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("experimental:explicit_sync");
+
+ // apply timelines for explicit sync
+ pMonitor->output->state->resetExplicitFences();
+
+ bool anyExplicit = !explicitPresented.empty();
+ if (anyExplicit) {
+ Debug::log(TRACE, "Explicit sync presented begin");
+ auto inFence = pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint);
+ if (inFence < 0)
+ Debug::log(ERR, "Export lastWaitPoint {} as sync explicitInFence failed", pMonitor->lastWaitPoint);
+
+ pMonitor->output->state->setExplicitInFence(inFence);
+
+ for (auto& e : explicitPresented) {
+ Debug::log(TRACE, "Explicit sync presented releasePoint {}", e->syncobj && e->syncobj->releaseTimeline ? e->syncobj->releasePoint : -1);
+ if (!e->syncobj || !e->syncobj->releaseTimeline)
+ continue;
+ e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint);
+ }
+
+ explicitPresented.clear();
+ auto outFence = pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq);
+ if (outFence < 0)
+ Debug::log(ERR, "Export commitSeq {} as sync explicitOutFence failed", pMonitor->commitSeq);
+
+ pMonitor->output->state->setExplicitOutFence(outFence);
+ Debug::log(TRACE, "Explicit sync presented end");
+ }
+
+ pMonitor->lastWaitPoint = 0;
+
+ bool ok = pMonitor->state.commit();
+ if (!ok) {
+ Debug::log(TRACE, "Monitor state commit failed");
+ // rollback the buffer to avoid writing to the front buffer that is being
+ // displayed
+ pMonitor->output->swapchain->rollback();
+ pMonitor->damage.damageEntire();
+ }
+
+ if (!*PENABLEEXPLICIT)
+ return ok;
+
+ if (pMonitor->output->state->state().explicitInFence >= 0)
+ close(pMonitor->output->state->state().explicitInFence);
+
+ if (pMonitor->output->state->state().explicitOutFence >= 0) {
+ if (ok)
+ pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, pMonitor->output->state->state().explicitOutFence);
+ close(pMonitor->output->state->state().explicitOutFence);
+ }
+
+ return ok;
+}
+
void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) {
Vector2D translate = {geometry.x, geometry.y};
float scale = (float)geometry.width / pMonitor->vecPixelSize.x;
@@ -1480,33 +1499,11 @@ void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE
}
}
-void CHyprRenderer::setWindowScanoutMode(PHLWINDOW pWindow) {
- // FIXME: fix when moved to new impl
- // if (!g_pCompositor->m_sWLRLinuxDMABuf || g_pSessionLockManager->isSessionLocked())
- // return;
-
- // if (!pWindow->m_bIsFullscreen) {
- // wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), nullptr);
- // Debug::log(LOG, "Scanout mode OFF set for {}", pWindow);
- // return;
- // }
-
- // const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
-
- // const wlr_linux_dmabuf_feedback_v1_init_options INIT_OPTIONS = {
- // .main_renderer = g_pCompositor->m_sWLRRenderer,
- // .scanout_primary_output = PMONITOR->output,
- // };
-
- // wlr_linux_dmabuf_feedback_v1 feedback = {0};
-
- // if (!wlr_linux_dmabuf_feedback_v1_init_with_options(&feedback, &INIT_OPTIONS))
- // return;
-
- // wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), &feedback);
- // wlr_linux_dmabuf_feedback_v1_finish(&feedback);
+void CHyprRenderer::setSurfaceScanoutMode(SP<CWLSurfaceResource> surface, SP<CMonitor> monitor) {
+ if (!PROTO::linuxDma)
+ return;
- // Debug::log(LOG, "Scanout mode ON set for {}", pWindow);
+ PROTO::linuxDma->updateScanoutTranche(surface, monitor);
}
// taken from Sway.
@@ -1572,7 +1569,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector<PHLL
CBox full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
for (auto& ls : layerSurfaces) {
- if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess)
+ if (!ls || ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess)
continue;
const auto PLAYER = ls->layerSurface;
@@ -1708,7 +1705,7 @@ void CHyprRenderer::damageSurface(SP<CWLSurfaceResource> pSurface, double x, dou
damageBox.scale(scale);
// schedule frame events
- g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)));
+ g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE);
if (damageBox.empty())
return;
@@ -1820,13 +1817,13 @@ void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion
monbox.x = (monitor->vecTransformedSize.x - monbox.w) / 2;
monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2;
- wlr_region_scale(transformed.pixman(), transformed.pixman(), scale);
+ transformed.scale(scale);
transformed.transform(wlTransformToHyprutils(mirrored->transform), mirrored->vecPixelSize.x * scale, mirrored->vecPixelSize.y * scale);
transformed.translate(Vector2D(monbox.x, monbox.y));
mirror->addDamage(&transformed);
- g_pCompositor->scheduleFrameForMonitor(mirror);
+ g_pCompositor->scheduleFrameForMonitor(mirror, Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE);
}
}
@@ -1869,7 +1866,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
// don't touch VR headsets
- if (pMonitor->output->non_desktop)
+ if (pMonitor->output->nonDesktop)
return true;
if (!pMonitor->m_bEnabled) {
@@ -1900,7 +1897,10 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
// Needed in case we are switching from a custom modeline to a standard mode
pMonitor->customDrmMode = {};
pMonitor->currentMode = nullptr;
- bool autoScale = false;
+
+ pMonitor->output->state->setFormat(DRM_FORMAT_XRGB8888);
+
+ bool autoScale = false;
if (RULE->scale > 0.1) {
pMonitor->scale = RULE->scale;
@@ -1910,38 +1910,35 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->scale = DEFAULTSCALE;
}
- wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale);
- pMonitor->setScale = pMonitor->scale;
-
- wlr_output_state_set_transform(pMonitor->state.wlr(), RULE->transform);
+ pMonitor->setScale = pMonitor->scale;
pMonitor->transform = RULE->transform;
- const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : RULE->refreshRate * 1000;
+ const auto WLRREFRESHRATE = pMonitor->output->getBackend()->type() == Aquamarine::eBackendType::AQ_BACKEND_DRM ? RULE->refreshRate * 1000 : 0;
// loop over modes and choose an appropriate one.
if (RULE->resolution != Vector2D() && RULE->resolution != Vector2D(-1, -1) && RULE->resolution != Vector2D(-1, -2)) {
- if (!wl_list_empty(&pMonitor->output->modes) && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) {
- wlr_output_mode* mode;
- bool found = false;
+ if (!pMonitor->output->modes.empty() && RULE->drmMode.type != DRM_MODE_TYPE_USERDEF) {
+ bool found = false;
- wl_list_for_each(mode, &pMonitor->output->modes, link) {
+ for (auto& mode : pMonitor->output->modes) {
// if delta of refresh rate, w and h chosen and mode is < 1 we accept it
- if (DELTALESSTHAN(mode->width, RULE->resolution.x, 1) && DELTALESSTHAN(mode->height, RULE->resolution.y, 1) &&
- DELTALESSTHAN(mode->refresh / 1000.f, RULE->refreshRate, 1)) {
- wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
+ if (DELTALESSTHAN(mode->pixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(mode->pixelSize.y, RULE->resolution.y, 1) &&
+ DELTALESSTHAN(mode->refreshRate / 1000.f, RULE->refreshRate, 1)) {
+ pMonitor->output->state->setMode(mode);
- if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
- Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f);
+ if (!pMonitor->state.test()) {
+ Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->pixelSize.x, mode->pixelSize.y,
+ mode->refreshRate / 1000.f);
continue;
}
Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
- (float)RULE->refreshRate, mode->width, mode->height, mode->refresh);
+ (float)RULE->refreshRate, mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate);
found = true;
- pMonitor->refreshRate = mode->refresh / 1000.f;
- pMonitor->vecSize = Vector2D(mode->width, mode->height);
+ pMonitor->refreshRate = mode->refreshRate / 1000.f;
+ pMonitor->vecSize = mode->pixelSize;
pMonitor->currentMode = mode;
break;
@@ -1949,14 +1946,14 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!found) {
- wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE);
+ pMonitor->output->state->setCustomMode(makeShared<Aquamarine::SOutputMode>(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE}));
pMonitor->vecSize = RULE->resolution;
pMonitor->refreshRate = RULE->refreshRate;
- if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
+ if (!pMonitor->state.test()) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
- const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
+ const auto PREFERREDMODE = pMonitor->output->preferredMode();
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution,
@@ -1965,13 +1962,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
// Preferred is valid
- wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
+ pMonitor->output->state->setMode(PREFERREDMODE);
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
- (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f);
- pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
- pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
+ pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f;
+ pMonitor->vecSize = PREFERREDMODE->pixelSize;
pMonitor->currentMode = PREFERREDMODE;
} else {
Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
@@ -1982,30 +1979,30 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
bool fail = false;
if (RULE->drmMode.type == DRM_MODE_TYPE_USERDEF) {
- if (!wlr_output_is_drm(pMonitor->output)) {
+ if (pMonitor->output->getBackend()->type() != Aquamarine::eBackendType::AQ_BACKEND_DRM) {
Debug::log(ERR, "Tried to set custom modeline on non-DRM output");
fail = true;
} else {
- auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode);
- if (mode) {
- wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
- pMonitor->customDrmMode = RULE->drmMode;
- } else {
- Debug::log(ERR, "wlr_drm_connector_add_mode failed");
- fail = true;
- }
+ // FIXME:
+ // auto* mode = wlr_drm_connector_add_mode(pMonitor->output, &RULE->drmMode);
+ // if (mode) {
+ // wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
+ // pMonitor->customDrmMode = RULE->drmMode;
+ // } else {
+ // Debug::log(ERR, "wlr_drm_connector_add_mode failed");
+ // fail = true;
+ // }
}
- } else {
- wlr_output_state_set_custom_mode(pMonitor->state.wlr(), (int)RULE->resolution.x, (int)RULE->resolution.y, WLRREFRESHRATE);
- }
+ } else
+ pMonitor->output->state->setCustomMode(makeShared<Aquamarine::SOutputMode>(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = WLRREFRESHRATE}));
pMonitor->vecSize = RULE->resolution;
pMonitor->refreshRate = RULE->refreshRate;
- if (fail || !wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
+ if (fail || !pMonitor->state.test()) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
- const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
+ const auto PREFERREDMODE = pMonitor->output->preferredMode();
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->output->name, RULE->resolution,
@@ -2014,48 +2011,47 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
// Preferred is valid
- wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
+ pMonitor->output->state->setMode(PREFERREDMODE);
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
- (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f);
- pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
- pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
+ pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f;
+ pMonitor->vecSize = PREFERREDMODE->pixelSize;
pMonitor->customDrmMode = {};
- } else {
+ } else
Debug::log(LOG, "Set a custom mode {:X0}@{:2f} (mode not found in monitor modes)", RULE->resolution, (float)RULE->refreshRate);
- }
}
} else if (RULE->resolution != Vector2D()) {
- if (!wl_list_empty(&pMonitor->output->modes)) {
- wlr_output_mode* mode;
- float currentWidth = 0;
- float currentHeight = 0;
- float currentRefresh = 0;
- bool success = false;
+ if (!pMonitor->output->modes.empty()) {
+ float currentWidth = 0;
+ float currentHeight = 0;
+ float currentRefresh = 0;
+ bool success = false;
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
if (RULE->resolution == Vector2D(-1, -1)) {
- wl_list_for_each(mode, &pMonitor->output->modes, link) {
- if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) || mode->refresh > (currentRefresh + 3000.f)) {
- wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
- if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
- currentWidth = mode->width;
- currentHeight = mode->height;
- currentRefresh = mode->refresh;
+ for (auto& mode : pMonitor->output->modes) {
+ if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) ||
+ mode->refreshRate > (currentRefresh + 3000.f)) {
+ pMonitor->output->state->setMode(mode);
+ if (pMonitor->state.test()) {
+ currentWidth = mode->pixelSize.x;
+ currentHeight = mode->pixelSize.y;
+ currentRefresh = mode->refreshRate;
success = true;
}
}
}
} else {
- wl_list_for_each(mode, &pMonitor->output->modes, link) {
- if ((mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= (currentRefresh - 1000.f)) ||
- (mode->width > currentWidth && mode->height > currentHeight)) {
- wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
- if (wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
- currentWidth = mode->width;
- currentHeight = mode->height;
- currentRefresh = mode->refresh;
+ for (auto& mode : pMonitor->output->modes) {
+ if ((mode->pixelSize.x >= currentWidth && mode->pixelSize.y >= currentHeight && mode->refreshRate >= (currentRefresh - 1000.f)) ||
+ (mode->pixelSize.x > currentWidth && mode->pixelSize.y > currentHeight)) {
+ pMonitor->output->state->setMode(mode);
+ if (pMonitor->state.test()) {
+ currentWidth = mode->pixelSize.x;
+ currentHeight = mode->pixelSize.y;
+ currentRefresh = mode->refreshRate;
success = true;
}
}
@@ -2063,10 +2059,12 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!success) {
- Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
- (float)RULE->refreshRate, mode->width, mode->height, mode->refresh / 1000.f);
+ if (pMonitor->output->state->state().mode)
+ Debug::log(LOG, "Monitor {}: REJECTED mode: {:X0}@{:2f}! Falling back to preferred: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
+ (float)RULE->refreshRate, pMonitor->output->state->state().mode->pixelSize.x, pMonitor->output->state->state().mode->pixelSize.y,
+ pMonitor->output->state->state().mode->refreshRate / 1000.f);
- const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
+ const auto PREFERREDMODE = pMonitor->output->preferredMode();
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE, and an INVALID one was requested: {:X0}@{:2f}", pMonitor->ID, RULE->resolution, (float)RULE->refreshRate);
@@ -2074,13 +2072,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
// Preferred is valid
- wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
+ pMonitor->output->state->setMode(PREFERREDMODE);
Debug::log(ERR, "Monitor {} got an invalid requested mode: {:X0}@{:2f}, using the preferred one instead: {}x{}@{:2f}", pMonitor->output->name, RULE->resolution,
- (float)RULE->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
+ (float)RULE->refreshRate, PREFERREDMODE->pixelSize.x, PREFERREDMODE->pixelSize.y, PREFERREDMODE->refreshRate / 1000.f);
- pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
- pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
+ pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f;
+ pMonitor->vecSize = PREFERREDMODE->pixelSize;
pMonitor->currentMode = PREFERREDMODE;
} else {
@@ -2091,27 +2089,26 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
}
} else {
- const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
+ const auto PREFERREDMODE = pMonitor->output->preferredMode();
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE", pMonitor->output->name);
- if (!wl_list_empty(&pMonitor->output->modes)) {
- wlr_output_mode* mode;
-
- wl_list_for_each(mode, &pMonitor->output->modes, link) {
- wlr_output_state_set_mode(pMonitor->state.wlr(), mode);
+ if (!pMonitor->output->modes.empty()) {
+ for (auto& mode : pMonitor->output->modes) {
+ pMonitor->output->state->setMode(mode);
- if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
- Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->width, mode->height, mode->refresh / 1000.f);
+ if (!pMonitor->state.test()) {
+ Debug::log(LOG, "Monitor {}: REJECTED available mode: {}x{}@{:2f}!", pMonitor->output->name, mode->pixelSize.x, mode->pixelSize.y,
+ mode->refreshRate / 1000.f);
continue;
}
Debug::log(LOG, "Monitor {}: requested {:X0}@{:2f}, found available mode: {}x{}@{}mHz, applying.", pMonitor->output->name, RULE->resolution,
- (float)RULE->refreshRate, mode->width, mode->height, mode->refresh);
+ (float)RULE->refreshRate, mode->pixelSize.x, mode->pixelSize.y, mode->refreshRate);
- pMonitor->refreshRate = mode->refresh / 1000.f;
- pMonitor->vecSize = Vector2D(mode->width, mode->height);
+ pMonitor->refreshRate = mode->refreshRate / 1000.f;
+ pMonitor->vecSize = mode->pixelSize;
pMonitor->currentMode = mode;
break;
@@ -2119,21 +2116,49 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
} else {
// Preferred is valid
- wlr_output_state_set_mode(pMonitor->state.wlr(), PREFERREDMODE);
+ pMonitor->output->state->setMode(PREFERREDMODE);
- pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
- pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
+ pMonitor->vecSize = PREFERREDMODE->pixelSize;
+ pMonitor->refreshRate = PREFERREDMODE->refreshRate / 1000.f;
pMonitor->currentMode = PREFERREDMODE;
Debug::log(LOG, "Setting preferred mode for {}", pMonitor->output->name);
}
}
- pMonitor->vrrActive = pMonitor->state.wlr()->adaptive_sync_enabled // disabled here, will be tested in CConfigManager::ensureVRR()
- || pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync
+ pMonitor->vrrActive = pMonitor->output->state->state().adaptiveSync // disabled here, will be tested in CConfigManager::ensureVRR()
+ || pMonitor->createdByUser; // wayland backend doesn't allow for disabling adaptive_sync
pMonitor->vecPixelSize = pMonitor->vecSize;
+ // clang-format off
+ static const std::array<std::vector<std::pair<std::string, uint32_t>>, 2> formats{
+ std::vector<std::pair<std::string, uint32_t>>{ /* 10-bit */
+ {"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID}
+ },
+ std::vector<std::pair<std::string, uint32_t>>{ /* 8-bit */
+ {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID}
+ }
+ };
+ // clang-format on
+
+ bool set10bit = false;
+
+ for (auto& fmt : formats[(int)!RULE->enable10bit]) {
+ pMonitor->output->state->setFormat(fmt.second);
+
+ if (!pMonitor->state.test()) {
+ Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first);
+ } else {
+ Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
+ if (RULE->enable10bit && fmt.first.contains("101010"))
+ set10bit = true;
+ break;
+ }
+ }
+
+ pMonitor->enabled10bit = set10bit;
+
Vector2D logicalSize = pMonitor->vecPixelSize / pMonitor->scale;
if (!*PDISABLESCALECHECKS && (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y))) {
// invalid scale, will produce fractional pixels.
@@ -2145,10 +2170,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
double scaleZero = searchScale / 120.0;
Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero;
- if (logicalZero == logicalZero.round()) {
+ if (logicalZero == logicalZero.round())
pMonitor->scale = scaleZero;
- wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->scale);
- } else {
+ else {
for (size_t i = 1; i < 90; ++i) {
double scaleUp = (searchScale + i) / 120.0;
double scaleDown = (searchScale - i) / 120.0;
@@ -2185,57 +2209,21 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
} else
pMonitor->scale = searchScale;
}
-
- // for wlroots, that likes flooring, we have to do this.
- double logicalX = std::round(pMonitor->vecPixelSize.x / pMonitor->scale);
- logicalX += 0.1;
-
- wlr_output_state_set_scale(pMonitor->state.wlr(), pMonitor->vecPixelSize.x / logicalX);
- }
- }
-
- // clang-format off
- static const std::array<std::vector<std::pair<std::string, uint32_t>>, 2> formats{
- std::vector<std::pair<std::string, uint32_t>>{ /* 10-bit */
- {"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID}
- },
- std::vector<std::pair<std::string, uint32_t>>{ /* 8-bit */
- {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}, {"DRM_FORMAT_INVALID", DRM_FORMAT_INVALID}
- }
- };
- // clang-format on
-
- bool set10bit = false;
- pMonitor->drmFormat = DRM_FORMAT_INVALID;
-
- for (auto& fmt : formats[(int)!RULE->enable10bit]) {
- wlr_output_state_set_render_format(pMonitor->state.wlr(), fmt.second);
-
- if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr())) {
- Debug::log(ERR, "output {} failed basic test on format {}", pMonitor->szName, fmt.first);
- } else {
- Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
- if (RULE->enable10bit && fmt.first.contains("101010"))
- set10bit = true;
-
- pMonitor->drmFormat = fmt.second;
- break;
}
}
- pMonitor->enabled10bit = set10bit;
+ pMonitor->output->scheduleFrame();
if (!pMonitor->state.commit())
Debug::log(ERR, "Couldn't commit output named {}", pMonitor->output->name);
- int x, y;
- wlr_output_transformed_resolution(pMonitor->output, &x, &y);
- pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).round();
- pMonitor->vecTransformedSize = Vector2D(x, y);
+ Vector2D xfmd = pMonitor->transform % 2 == 1 ? Vector2D{pMonitor->vecPixelSize.y, pMonitor->vecPixelSize.x} : pMonitor->vecPixelSize;
+ pMonitor->vecSize = (xfmd / pMonitor->scale).round();
+ pMonitor->vecTransformedSize = xfmd;
if (pMonitor->createdByUser) {
CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
- transformedBox.transform(wlTransformToHyprutils(wlr_output_transform_invert(pMonitor->output->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);
+ transformedBox.transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);
pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height);
}
@@ -2245,7 +2233,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
if (WAS10B != pMonitor->enabled10bit || OLDRES != pMonitor->vecPixelSize)
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
- // updato wlroots
g_pCompositor->arrangeMonitors();
pMonitor->damage.setSize(pMonitor->vecTransformedSize);
@@ -2260,9 +2247,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
// updato us
arrangeLayersForMonitor(pMonitor->ID);
- // frame skip
- pMonitor->framesToSkip = 1;
-
// reload to fix mirrors
g_pConfigManager->m_bWantsMonitorReload = true;
@@ -2329,7 +2313,7 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Hiding the cursor (hl-mandated)");
for (auto& m : g_pCompositor->m_vMonitors) {
- if (m->output->software_cursor_locks == 0)
+ if (!g_pPointerManager->softwareLockedFor(m))
continue;
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
@@ -2341,7 +2325,7 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Showing the cursor (hl-mandated)");
for (auto& m : g_pCompositor->m_vMonitors) {
- if (m->output->software_cursor_locks == 0)
+ if (!g_pPointerManager->softwareLockedFor(m))
continue;
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
@@ -2570,37 +2554,37 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) {
pMonitor->solitaryClient = PCANDIDATE;
}
-CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt) {
- auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pWlrBuffer == buffer; });
+SP<CRenderbuffer> CHyprRenderer::getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
+ auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; });
if (it != m_vRenderbuffers.end())
- return it->get();
+ return *it;
- return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get();
-}
+ auto buf = makeShared<CRenderbuffer>(buffer, fmt);
-CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP<IWLBuffer> buffer, uint32_t fmt) {
- auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; });
-
- if (it != m_vRenderbuffers.end())
- return it->get();
+ if (!buf->good())
+ return nullptr;
- return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get();
+ m_vRenderbuffers.emplace_back(buf);
+ return buf;
}
void CHyprRenderer::makeEGLCurrent() {
- if (!g_pCompositor)
+ if (!g_pCompositor || !g_pHyprOpenGL)
return;
- if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL))
- eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL));
+ if (eglGetCurrentContext() != g_pHyprOpenGL->m_pEglContext)
+ eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, g_pHyprOpenGL->m_pEglContext);
}
void CHyprRenderer::unsetEGL() {
- eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (!g_pHyprOpenGL)
+ return;
+
+ eglMakeCurrent(g_pHyprOpenGL->m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
-bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP<IWLBuffer> buffer, CFramebuffer* fb, bool simple) {
+bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP<IHLBuffer> buffer, CFramebuffer* fb, bool simple) {
makeEGLCurrent();
@@ -2618,35 +2602,33 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode
return true;
}
- int bufferAge = 0;
+ /* This is a constant expression, as we always use double-buffering in our swapchain
+ TODO: Rewrite the CDamageRing to take advantage of that maybe? It's made to support longer swapchains atm because we used to do wlroots */
+ static constexpr const int HL_BUFFER_AGE = 2;
if (!buffer) {
- if (!wlr_output_configure_primary_swapchain(pMonitor->output, pMonitor->state.wlr(), &pMonitor->output->swapchain)) {
- Debug::log(ERR, "Failed to configure primary swapchain for {}", pMonitor->szName);
- return false;
- }
-
- m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &bufferAge);
- if (!m_pCurrentWlrBuffer) {
+ m_pCurrentBuffer = pMonitor->output->swapchain->next(nullptr);
+ if (!m_pCurrentBuffer) {
Debug::log(ERR, "Failed to acquire swapchain buffer for {}", pMonitor->szName);
return false;
}
} else
- m_pCurrentHLBuffer = buffer;
+ m_pCurrentBuffer = buffer;
try {
- if (m_pCurrentWlrBuffer)
- m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat);
- else
- m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentHLBuffer.lock(), pMonitor->drmFormat);
+ m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentBuffer, pMonitor->output->state->state().drmFormat);
} catch (std::exception& e) {
Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName);
- wlr_buffer_unlock(m_pCurrentWlrBuffer);
+ return false;
+ }
+
+ if (!m_pCurrentRenderbuffer) {
+ Debug::log(ERR, "failed to start a render pass for output {}, no RBO could be obtained", pMonitor->szName);
return false;
}
if (mode == RENDER_MODE_NORMAL) {
- damage = pMonitor->damage.getBufferDamage(bufferAge);
+ damage = pMonitor->damage.getBufferDamage(HL_BUFFER_AGE);
pMonitor->damage.rotate();
}
@@ -2662,6 +2644,9 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode
void CHyprRenderer::endRender() {
const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor;
static auto PNVIDIAANTIFLICKER = CConfigValue<Hyprlang::INT>("opengl:nvidia_anti_flicker");
+ static auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("experimental:explicit_sync");
+
+ PMONITOR->commitSeq++;
if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY)
g_pHyprOpenGL->end();
@@ -2674,29 +2659,57 @@ void CHyprRenderer::endRender() {
if (m_eRenderMode == RENDER_MODE_FULL_FAKE)
return;
- if (isNvidia() && *PNVIDIAANTIFLICKER)
- glFinish();
- else
- glFlush();
-
if (m_eRenderMode == RENDER_MODE_NORMAL) {
- wlr_output_state_set_buffer(PMONITOR->state.wlr(), m_pCurrentWlrBuffer);
- unsetEGL(); // flush the context
- }
+ PMONITOR->output->state->setBuffer(m_pCurrentBuffer);
+
+ if (PMONITOR->inTimeline && *PENABLEEXPLICIT) {
+ auto sync = g_pHyprOpenGL->createEGLSync(-1);
+ if (!sync) {
+ m_pCurrentRenderbuffer->unbind();
+ m_pCurrentRenderbuffer = nullptr;
+ m_pCurrentBuffer = nullptr;
+ Debug::log(ERR, "renderer: couldn't create an EGLSync for out in endRender");
+ return;
+ }
+
+ auto dupedfd = sync->dupFenceFD();
+ sync.reset();
+ if (dupedfd < 0) {
+ m_pCurrentRenderbuffer->unbind();
+ m_pCurrentRenderbuffer = nullptr;
+ m_pCurrentBuffer = nullptr;
+ Debug::log(ERR, "renderer: couldn't dup an EGLSync fence for out in endRender");
+ return;
+ }
- wlr_buffer_unlock(m_pCurrentWlrBuffer);
+ bool ok = PMONITOR->inTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd);
+ close(dupedfd);
+ if (!ok) {
+ m_pCurrentRenderbuffer->unbind();
+ m_pCurrentRenderbuffer = nullptr;
+ m_pCurrentBuffer = nullptr;
+ Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender");
+ return;
+ }
+ } else {
+ if (isNvidia() && *PNVIDIAANTIFLICKER)
+ glFinish();
+ else
+ glFlush();
+ }
+ }
m_pCurrentRenderbuffer->unbind();
m_pCurrentRenderbuffer = nullptr;
- m_pCurrentWlrBuffer = nullptr;
+ m_pCurrentBuffer = nullptr;
}
void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) {
std::erase_if(m_vRenderbuffers, [&](const auto& rbo) { return rbo.get() == rb; });
}
-CRenderbuffer* CHyprRenderer::getCurrentRBO() {
+SP<CRenderbuffer> CHyprRenderer::getCurrentRBO() {
return m_pCurrentRenderbuffer;
}