mirror of https://github.com/hyprwm/Hyprland
Explicit sync fixes (#6829)
* explicit sync fixes * more logging * reremove wlroots * close explicit fds on rollback * limit presentFeedback explicit sync to direct scanout mode only * explicit sync for texture render * cursor explicit sync initial * common wait for explicit sync point code * code style fixes
This commit is contained in:
parent
4c905b1a8b
commit
805a054389
|
@ -162,13 +162,13 @@ bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) {
|
||||||
if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) {
|
if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) {
|
||||||
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed");
|
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed");
|
||||||
drmSyncobjDestroy(drmFD, syncHandle);
|
drmSyncobjDestroy(drmFD, syncHandle);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drmSyncobjTransfer(drmFD, handle, dst, syncHandle, 0, 0)) {
|
if (drmSyncobjTransfer(drmFD, handle, dst, syncHandle, 0, 0)) {
|
||||||
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjTransfer failed");
|
Debug::log(ERR, "importFromSyncFileFD: drmSyncobjTransfer failed");
|
||||||
drmSyncobjDestroy(drmFD, syncHandle);
|
drmSyncobjDestroy(drmFD, syncHandle);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
drmSyncobjDestroy(drmFD, syncHandle);
|
drmSyncobjDestroy(drmFD, syncHandle);
|
||||||
|
|
|
@ -448,7 +448,7 @@ void CPointerManager::renderSoftwareCursorsFor(SP<CMonitor> pMonitor, timespec*
|
||||||
box.x = std::round(box.x);
|
box.x = std::round(box.x);
|
||||||
box.y = std::round(box.y);
|
box.y = std::round(box.y);
|
||||||
|
|
||||||
g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F);
|
g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F, 0, false, false, currentCursorImage.waitTimeline, currentCursorImage.waitPoint);
|
||||||
|
|
||||||
if (currentCursorImage.surface)
|
if (currentCursorImage.surface)
|
||||||
currentCursorImage.surface->resource()->frame(now);
|
currentCursorImage.surface->resource()->frame(now);
|
||||||
|
|
|
@ -147,6 +147,8 @@ class CPointerManager {
|
||||||
|
|
||||||
CHyprSignalListener destroySurface;
|
CHyprSignalListener destroySurface;
|
||||||
CHyprSignalListener commitSurface;
|
CHyprSignalListener commitSurface;
|
||||||
|
SP<CSyncTimeline> waitTimeline = nullptr;
|
||||||
|
uint64_t waitPoint = 0;
|
||||||
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
|
} currentCursorImage; // TODO: support various sizes per-output so we can have pixel-perfect cursors
|
||||||
|
|
||||||
Vector2D pointerPos = {0, 0};
|
Vector2D pointerPos = {0, 0};
|
||||||
|
|
|
@ -447,22 +447,24 @@ void CWLSurfaceResource::commitPendingState() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor) {
|
void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync) {
|
||||||
frame(when);
|
frame(when);
|
||||||
auto FEEDBACK = makeShared<CQueuedPresentationData>(self.lock());
|
auto FEEDBACK = makeShared<CQueuedPresentationData>(self.lock());
|
||||||
FEEDBACK->attachMonitor(pMonitor);
|
FEEDBACK->attachMonitor(pMonitor);
|
||||||
FEEDBACK->discarded();
|
FEEDBACK->discarded();
|
||||||
PROTO::presentation->queueData(FEEDBACK);
|
PROTO::presentation->queueData(FEEDBACK);
|
||||||
|
|
||||||
if (!pMonitor || !pMonitor->outTimeline || !syncobj)
|
if (!pMonitor || !pMonitor->outTimeline || !syncobj || !needsExplicitSync)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// attach explicit sync
|
// attach explicit sync
|
||||||
g_pHyprRenderer->explicitPresented.emplace_back(self.lock());
|
g_pHyprRenderer->explicitPresented.emplace_back(self.lock());
|
||||||
|
|
||||||
if (syncobj->acquirePoint > pMonitor->lastWaitPoint)
|
if (syncobj->acquirePoint > pMonitor->lastWaitPoint) {
|
||||||
|
Debug::log(TRACE, "presentFeedback lastWaitPoint {} -> {}", pMonitor->lastWaitPoint, syncobj->acquirePoint);
|
||||||
pMonitor->lastWaitPoint = syncobj->acquirePoint;
|
pMonitor->lastWaitPoint = syncobj->acquirePoint;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> resource_) : resource(resource_) {
|
CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> resource_) : resource(resource_) {
|
||||||
if (!good())
|
if (!good())
|
||||||
|
|
|
@ -122,7 +122,7 @@ class CWLSurfaceResource {
|
||||||
|
|
||||||
void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
|
void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
|
||||||
CRegion accumulateCurrentBufferDamage();
|
CRegion accumulateCurrentBufferDamage();
|
||||||
void presentFeedback(timespec* when, CMonitor* pMonitor);
|
void presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync = false);
|
||||||
void lockPendingState();
|
void lockPendingState();
|
||||||
void unlockPendingState();
|
void unlockPendingState();
|
||||||
|
|
||||||
|
|
|
@ -1255,16 +1255,17 @@ void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, i
|
||||||
scissor((CBox*)nullptr);
|
scissor((CBox*)nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV,
|
||||||
|
SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
|
|
||||||
renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true);
|
renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint);
|
||||||
|
|
||||||
scissor((CBox*)nullptr);
|
scissor((CBox*)nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
|
void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
|
||||||
bool allowDim) {
|
bool allowDim, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
|
RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||||
|
|
||||||
|
@ -1289,6 +1290,13 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
|
||||||
float glMatrix[9];
|
float glMatrix[9];
|
||||||
matrixMultiply(glMatrix, m_RenderData.projection, matrix);
|
matrixMultiply(glMatrix, m_RenderData.projection, matrix);
|
||||||
|
|
||||||
|
if (waitTimeline != nullptr) {
|
||||||
|
if (!waitForTimelinePoint(waitTimeline, waitPoint)) {
|
||||||
|
Debug::log(ERR, "renderTextureInternalWithDamage: failed to wait for explicit sync point {}", waitPoint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CShader* shader = nullptr;
|
CShader* shader = nullptr;
|
||||||
|
|
||||||
bool usingFinalShader = false;
|
bool usingFinalShader = false;
|
||||||
|
@ -2744,6 +2752,8 @@ std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
|
||||||
|
|
||||||
SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
|
SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
|
||||||
std::vector<EGLint> attribs;
|
std::vector<EGLint> attribs;
|
||||||
|
int dupFd = -1;
|
||||||
|
if (fenceFD > 0) {
|
||||||
int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0);
|
int dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0);
|
||||||
if (dupFd < 0) {
|
if (dupFd < 0) {
|
||||||
Debug::log(ERR, "createEGLSync: dup failed");
|
Debug::log(ERR, "createEGLSync: dup failed");
|
||||||
|
@ -2753,10 +2763,12 @@ SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
|
||||||
attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID);
|
attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID);
|
||||||
attribs.push_back(dupFd);
|
attribs.push_back(dupFd);
|
||||||
attribs.push_back(EGL_NONE);
|
attribs.push_back(EGL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data());
|
EGLSyncKHR sync = m_sProc.eglCreateSyncKHR(m_pEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data());
|
||||||
if (sync == EGL_NO_SYNC_KHR) {
|
if (sync == EGL_NO_SYNC_KHR) {
|
||||||
Debug::log(ERR, "eglCreateSyncKHR failed");
|
Debug::log(ERR, "eglCreateSyncKHR failed");
|
||||||
|
if (dupFd >= 0)
|
||||||
close(dupFd);
|
close(dupFd);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -2766,6 +2778,28 @@ SP<CEGLSync> CHyprOpenGLImpl::createEGLSync(int fenceFD) {
|
||||||
return eglsync;
|
return eglsync;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CHyprOpenGLImpl::waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point) {
|
||||||
|
int fd = timeline->exportAsSyncFileFD(point);
|
||||||
|
if (fd < 0) {
|
||||||
|
Debug::log(ERR, "waitForTimelinePoint: failed to get a fd from explicit timeline");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sync = g_pHyprOpenGL->createEGLSync(fd);
|
||||||
|
close(fd);
|
||||||
|
if (!sync) {
|
||||||
|
Debug::log(ERR, "waitForTimelinePoint: failed to get an eglsync from explicit timeline");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sync->wait()) {
|
||||||
|
Debug::log(ERR, "waitForTimelinePoint: failed to wait on an eglsync from explicit timeline");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void SRenderModifData::applyToBox(CBox& box) {
|
void SRenderModifData::applyToBox(CBox& box) {
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "../helpers/Timer.hpp"
|
#include "../helpers/Timer.hpp"
|
||||||
#include "../helpers/math/Math.hpp"
|
#include "../helpers/math/Math.hpp"
|
||||||
#include "../helpers/Format.hpp"
|
#include "../helpers/Format.hpp"
|
||||||
|
#include "../helpers/sync/SyncTimeline.hpp"
|
||||||
|
#include <cstdint>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -152,7 +154,8 @@ class CHyprOpenGLImpl {
|
||||||
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false);
|
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false);
|
||||||
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
|
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
|
||||||
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||||
void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false,
|
||||||
|
SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0);
|
||||||
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
||||||
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
|
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
|
||||||
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
|
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
|
||||||
|
@ -203,6 +206,7 @@ class CHyprOpenGLImpl {
|
||||||
std::vector<SDRMFormat> getDRMFormats();
|
std::vector<SDRMFormat> getDRMFormats();
|
||||||
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
||||||
SP<CEGLSync> createEGLSync(int fenceFD);
|
SP<CEGLSync> createEGLSync(int fenceFD);
|
||||||
|
bool waitForTimelinePoint(SP<CSyncTimeline> timeline, uint64_t point);
|
||||||
|
|
||||||
SCurrentRenderData m_RenderData;
|
SCurrentRenderData m_RenderData;
|
||||||
|
|
||||||
|
@ -284,7 +288,7 @@ class CHyprOpenGLImpl {
|
||||||
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
||||||
|
|
||||||
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
|
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
|
||||||
bool allowCustomUV = false, bool allowDim = false);
|
bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0);
|
||||||
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
|
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
|
||||||
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "../protocols/DRMSyncobj.hpp"
|
#include "../protocols/DRMSyncobj.hpp"
|
||||||
#include "../protocols/LinuxDMABUF.hpp"
|
#include "../protocols/LinuxDMABUF.hpp"
|
||||||
#include "../helpers/sync/SyncTimeline.hpp"
|
#include "../helpers/sync/SyncTimeline.hpp"
|
||||||
|
#include "debug/Log.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
|
@ -114,21 +115,8 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
|
||||||
|
|
||||||
// explicit sync: wait for the timeline, if any
|
// explicit sync: wait for the timeline, if any
|
||||||
if (surface->syncobj && surface->syncobj->acquireTimeline) {
|
if (surface->syncobj && surface->syncobj->acquireTimeline) {
|
||||||
int fd = surface->syncobj->acquireTimeline->timeline->exportAsSyncFileFD(surface->syncobj->acquirePoint);
|
if (!g_pHyprOpenGL->waitForTimelinePoint(surface->syncobj->acquireTimeline->timeline, surface->syncobj->acquirePoint)) {
|
||||||
if (fd < 0) {
|
Debug::log(ERR, "Renderer: failed to wait for explicit timeline");
|
||||||
Debug::log(ERR, "Renderer: failed to get a fd from explicit timeline");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto sync = g_pHyprOpenGL->createEGLSync(fd);
|
|
||||||
close(fd);
|
|
||||||
if (!sync) {
|
|
||||||
Debug::log(ERR, "Renderer: failed to get an eglsync from explicit timeline");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sync->wait()) {
|
|
||||||
Debug::log(ERR, "Renderer: failed to wait on an eglsync from explicit timeline");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,8 +179,10 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windowBox.width <= 1 || windowBox.height <= 1) {
|
if (windowBox.width <= 1 || windowBox.height <= 1) {
|
||||||
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback)
|
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
|
||||||
|
Debug::log(TRACE, "presentFeedback for invisible surface");
|
||||||
surface->presentFeedback(RDATA->when, RDATA->pMonitor);
|
surface->presentFeedback(RDATA->when, RDATA->pMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
return; // invisible
|
return; // invisible
|
||||||
}
|
}
|
||||||
|
@ -245,8 +235,10 @@ static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* da
|
||||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true);
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback)
|
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
|
||||||
|
Debug::log(TRACE, "presentFeedback for visible surface");
|
||||||
surface->presentFeedback(RDATA->when, RDATA->pMonitor);
|
surface->presentFeedback(RDATA->when, RDATA->pMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
g_pHyprOpenGL->blend(true);
|
g_pHyprOpenGL->blend(true);
|
||||||
|
|
||||||
|
@ -1099,8 +1091,10 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
|
||||||
if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked)
|
if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked)
|
||||||
return false; // do not DS if this monitor is being mirrored. Will break the functionality.
|
return false; // do not DS if this monitor is being mirrored. Will break the functionality.
|
||||||
|
|
||||||
if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock()))
|
if (g_pPointerManager->softwareLockedFor(pMonitor->self.lock())) {
|
||||||
|
Debug::log(TRACE, "Direct scanout failed: soft locked / HW cursors failed");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const auto PCANDIDATE = pMonitor->solitaryClient.lock();
|
const auto PCANDIDATE = pMonitor->solitaryClient.lock();
|
||||||
|
|
||||||
|
@ -1126,7 +1120,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
|
||||||
|
|
||||||
timespec now;
|
timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
PSURFACE->presentFeedback(&now, pMonitor);
|
Debug::log(TRACE, "presentFeedback for DS");
|
||||||
|
PSURFACE->presentFeedback(&now, pMonitor, true);
|
||||||
|
|
||||||
if (pMonitor->state.commit()) {
|
if (pMonitor->state.commit()) {
|
||||||
if (m_pLastScanout.expired()) {
|
if (m_pLastScanout.expired()) {
|
||||||
|
@ -1458,16 +1453,27 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) {
|
||||||
// apply timelines for explicit sync
|
// apply timelines for explicit sync
|
||||||
bool anyExplicit = !explicitPresented.empty();
|
bool anyExplicit = !explicitPresented.empty();
|
||||||
if (anyExplicit) {
|
if (anyExplicit) {
|
||||||
pMonitor->output->state->setExplicitInFence(pMonitor->inTimeline->exportAsSyncFileFD(pMonitor->lastWaitPoint));
|
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) {
|
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)
|
if (!e->syncobj || !e->syncobj->releaseTimeline)
|
||||||
continue;
|
continue;
|
||||||
e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint);
|
e->syncobj->releaseTimeline->timeline->transfer(pMonitor->outTimeline, pMonitor->commitSeq, e->syncobj->releasePoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
explicitPresented.clear();
|
explicitPresented.clear();
|
||||||
pMonitor->output->state->setExplicitOutFence(pMonitor->outTimeline->exportAsSyncFileFD(pMonitor->commitSeq));
|
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;
|
pMonitor->lastWaitPoint = 0;
|
||||||
|
@ -1475,23 +1481,25 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(CMonitor* pMonitor) {
|
||||||
const auto COMMITTED_OUT = pMonitor->output->state->state().explicitOutFence;
|
const auto COMMITTED_OUT = pMonitor->output->state->state().explicitOutFence;
|
||||||
const auto COMMITTED_IN = pMonitor->output->state->state().explicitInFence;
|
const auto COMMITTED_IN = pMonitor->output->state->state().explicitInFence;
|
||||||
|
|
||||||
if (!pMonitor->state.commit()) {
|
bool commited = pMonitor->state.commit();
|
||||||
|
if (!commited) {
|
||||||
|
Debug::log(TRACE, "Monitor state commit failed");
|
||||||
// rollback the buffer to avoid writing to the front buffer that is being
|
// rollback the buffer to avoid writing to the front buffer that is being
|
||||||
// displayed
|
// displayed
|
||||||
pMonitor->output->swapchain->rollback();
|
pMonitor->output->swapchain->rollback();
|
||||||
pMonitor->damage.damageEntire();
|
pMonitor->damage.damageEntire();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (COMMITTED_IN >= 0)
|
if (COMMITTED_IN >= 0)
|
||||||
close(COMMITTED_IN);
|
close(COMMITTED_IN);
|
||||||
|
|
||||||
if (COMMITTED_OUT >= 0) {
|
if (COMMITTED_OUT >= 0) {
|
||||||
|
if (commited)
|
||||||
pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, COMMITTED_OUT);
|
pMonitor->outTimeline->importFromSyncFileFD(pMonitor->commitSeq, COMMITTED_OUT);
|
||||||
close(COMMITTED_OUT);
|
close(COMMITTED_OUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return commited;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) {
|
void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) {
|
||||||
|
@ -2687,13 +2695,10 @@ void CHyprRenderer::endRender() {
|
||||||
if (m_eRenderMode == RENDER_MODE_FULL_FAKE)
|
if (m_eRenderMode == RENDER_MODE_FULL_FAKE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
|
||||||
glFinish();
|
|
||||||
|
|
||||||
if (m_eRenderMode == RENDER_MODE_NORMAL) {
|
if (m_eRenderMode == RENDER_MODE_NORMAL) {
|
||||||
PMONITOR->output->state->setBuffer(m_pCurrentBuffer);
|
PMONITOR->output->state->setBuffer(m_pCurrentBuffer);
|
||||||
|
|
||||||
if (PMONITOR->output->state->state().explicitOutFence >= 0) {
|
if (PMONITOR->inTimeline) {
|
||||||
auto sync = g_pHyprOpenGL->createEGLSync(-1);
|
auto sync = g_pHyprOpenGL->createEGLSync(-1);
|
||||||
if (!sync) {
|
if (!sync) {
|
||||||
m_pCurrentRenderbuffer->unbind();
|
m_pCurrentRenderbuffer->unbind();
|
||||||
|
@ -2713,7 +2718,7 @@ void CHyprRenderer::endRender() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = PMONITOR->outTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd);
|
bool ok = PMONITOR->inTimeline->importFromSyncFileFD(PMONITOR->commitSeq, dupedfd);
|
||||||
close(dupedfd);
|
close(dupedfd);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
m_pCurrentRenderbuffer->unbind();
|
m_pCurrentRenderbuffer->unbind();
|
||||||
|
@ -2722,9 +2727,13 @@ void CHyprRenderer::endRender() {
|
||||||
Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender");
|
Debug::log(ERR, "renderer: couldn't import from sync file fd in endRender");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
|
if (isNvidia() && *PNVIDIAANTIFLICKER)
|
||||||
|
glFinish();
|
||||||
|
else
|
||||||
glFlush();
|
glFlush();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_pCurrentRenderbuffer->unbind();
|
m_pCurrentRenderbuffer->unbind();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue