Skip to content

Commit 466f6bc

Browse files
authored
protocols/presentation: associate feedback with committed surface state, attempt 2 (#15459)
* Revert "presentation: revert "associate feedback with committed surface state (#15243)"" This reverts commit 4a753ea. * presentation: fix WP locks and discard failed draws the reason it stopped working is last change that PR did was moving from raw ptrs to UP's with WP's but tried to .lock() the WP, we cant lock a WP that points to a UP. also ensure all draws that isnt visible or simply failed creating texture or invalid sizes discard in elementrenderer. and all others present.
1 parent 116e636 commit 466f6bc

8 files changed

Lines changed: 117 additions & 22 deletions

File tree

‎src/protocols/PresentationTime.cpp‎

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
#include "core/Output.hpp"
77
#include <aquamarine/output/Output.hpp>
88

9-
CQueuedPresentationData::CQueuedPresentationData(SP surf) : m_surface(surf) {
9+
CQueuedPresentationData::CQueuedPresentationData(SP surf, std::vector<WP> feedbacks) :
10+
m_surface(surf), m_feedbacks(std::move(feedbacks)) {
1011
;
1112
}
1213

@@ -76,9 +77,23 @@ void CPresentationFeedback::sendQueued(WP data, const t
7677
m_done = true;
7778
}
7879

80+
void CPresentationFeedback::sendDiscarded() {
81+
if (m_done)
82+
return;
83+
84+
m_resource->sendDiscarded();
85+
m_done = true;
86+
}
87+
7988
CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
80-
static auto P = Event::bus()->m_events.monitor.removed.listen(
81-
[this](PHLMONITOR mon) { std::erase_if(m_queue, [mon](const auto& other) { return !other->m_surface || other->m_monitor == mon; }); });
89+
static auto P = Event::bus()->m_events.monitor.removed.listen([this](PHLMONITOR mon) {
90+
for (auto& data : m_queue) {
91+
if (!data->m_surface || data->m_monitor == mon)
92+
discardFeedbacks(data->m_feedbacks);
93+
}
94+
95+
std::erase_if(m_queue, [mon](const auto& other) { return !other->m_surface || other->m_monitor == mon; });
96+
});
8297
}
8398

8499
void CPresentationProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
@@ -95,33 +110,40 @@ void CPresentationProtocol::onManagerResourceDestroy(wl_resource* res) {
95110
}
96111

97112
void CPresentationProtocol::destroyResource(CPresentationFeedback* feedback) {
113+
feedback->m_done = true;
98114
std::erase_if(m_feedbacks, [&](const auto& other) { return other.get() == feedback; });
99115
}
100116

101117
void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* surf, uint32_t id) {
102118
const auto CLIENT = pMgr->client();
103119
const auto& RESOURCE =
104-
m_feedbacks.emplace_back(makeUnique(makeUnique(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf))).get();
120+
m_feedbacks.emplace_back(makeUnique(makeUnique(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf)));
105121

106122
if UNLIKELY (!RESOURCE->good()) {
107123
pMgr->noMemory();
108124
m_feedbacks.pop_back();
109125
return;
110126
}
127+
128+
if (const auto SURFACE = CWLSurfaceResource::fromResource(surf); SURFACE)
129+
SURFACE->m_pending.presentationFeedbacks.emplace_back(RESOURCE);
111130
}
112131

113132
void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, const timespec& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) {
114-
for (auto const& feedback : m_feedbacks) {
115-
if (!feedback->m_surface)
133+
for (auto const& data : m_queue) {
134+
if (!data->m_surface || !data->m_monitor) {
135+
discardFeedbacks(data->m_feedbacks);
116136
continue;
137+
}
117138

118-
for (auto const& data : m_queue) {
119-
if (!data->m_surface || data->m_surface != feedback->m_surface || (data->m_monitor && data->m_monitor != pMonitor))
139+
if (data->m_monitor != pMonitor)
140+
continue;
141+
142+
for (auto const& feedback : data->m_feedbacks) {
143+
if (!feedback || feedback->m_done)
120144
continue;
121145

122146
feedback->sendQueued(data, when, untilRefreshNs, seq, reportedFlags);
123-
feedback->m_done = true;
124-
break;
125147
}
126148
}
127149

@@ -147,6 +169,33 @@ void CPresentationProtocol::queueData(UP&& data) {
147169
m_queue.emplace_back(std::move(data));
148170
}
149171

172+
void CPresentationProtocol::discardFeedbacks(std::vector<WP>& feedbacks) {
173+
for (auto const& feedback : feedbacks) {
174+
if (!feedback || feedback->m_done)
175+
continue;
176+
177+
feedback->sendDiscarded();
178+
}
179+
180+
feedbacks.clear();
181+
std::erase_if(m_feedbacks, [](const auto& other) { return !other->m_surface || other->m_done; });
182+
}
183+
184+
void CPresentationProtocol::discardFeedbacksForSurface(WP surface) {
185+
if (!surface)
186+
return;
187+
188+
for (auto const& feedback : m_feedbacks) {
189+
if (feedback->m_surface != surface)
190+
continue;
191+
192+
feedback->sendDiscarded();
193+
}
194+
195+
std::erase_if(m_queue, [surface](const auto& other) { return !other->m_surface || other->m_surface == surface; });
196+
std::erase_if(m_feedbacks, [](const auto& other) { return !other->m_surface || other->m_done; });
197+
}
198+
150199
bool CPresentationProtocol::hasPendingFeedbacks() const {
151200
return !m_feedbacks.empty();
152201
}

‎src/protocols/PresentationTime.hpp‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
#include "../helpers/time/Time.hpp"
99

1010
class CWLSurfaceResource;
11+
class CPresentationFeedback;
1112

1213
class CQueuedPresentationData {
1314
public:
14-
CQueuedPresentationData(SP surf);
15+
CQueuedPresentationData(SP surf, std::vector<WP> feedbacks);
1516

1617
void setPresentationType(bool zeroCopy);
1718
void attachMonitor(PHLMONITOR pMonitor);
@@ -22,10 +23,11 @@ class CQueuedPresentationData {
2223
bool m_done = false;
2324

2425
private:
25-
bool m_wasPresented = false;
26-
bool m_zeroCopy = false;
27-
PHLMONITORREF m_monitor;
28-
WP m_surface;
26+
bool m_wasPresented = false;
27+
bool m_zeroCopy = false;
28+
PHLMONITORREF m_monitor;
29+
WP m_surface;
30+
std::vector<WP> m_feedbacks;
2931

3032
friend class CPresentationFeedback;
3133
friend class CPresentationProtocol;
@@ -38,6 +40,7 @@ class CPresentationFeedback {
3840
bool good();
3941

4042
void sendQueued(WP data, const timespec& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags);
43+
void sendDiscarded();
4144

4245
private:
4346
UP m_resource;
@@ -55,6 +58,8 @@ class CPresentationProtocol : public IWaylandProtocol {
5558

5659
void onPresented(PHLMONITOR pMonitor, const timespec& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags);
5760
void queueData(UP&& data);
61+
void discardFeedbacks(std::vector<WP>& feedbacks);
62+
void discardFeedbacksForSurface(WP surface);
5863
bool hasPendingFeedbacks() const;
5964

6065
private:

‎src/protocols/core/Compositor.cpp‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : m_resource(re
146146
m_events.precommit.emit();
147147
if (m_pending.rejected) {
148148
m_pending.rejected = false;
149+
PROTO::presentation->discardFeedbacks(m_pending.presentationFeedbacks);
149150
dropPendingBuffer();
150151
return;
151152
}
@@ -253,10 +254,19 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : m_resource(re
253254
}
254255

255256
CWLSurfaceResource::~CWLSurfaceResource() {
257+
discardPresentationFeedbacks();
256258
m_events.destroy.emit();
257259
}
258260

261+
void CWLSurfaceResource::discardPresentationFeedbacks() {
262+
PROTO::presentation->discardFeedbacks(m_pending.presentationFeedbacks);
263+
PROTO::presentation->discardFeedbacks(m_current.presentationFeedbacks);
264+
PROTO::presentation->discardFeedbacksForSurface(m_self);
265+
}
266+
259267
void CWLSurfaceResource::destroy() {
268+
discardPresentationFeedbacks();
269+
260270
if (m_mapped) {
261271
m_events.unmap.emit();
262272
unmap();
@@ -514,6 +524,10 @@ void CWLSurfaceResource::unmap() {
514524
if UNLIKELY (!m_mapped)
515525
return;
516526

527+
// unmapped content will never be displayed: terminate outstanding feedbacks,
528+
// or clients blocking on them (present_wait) stall forever.
529+
discardPresentationFeedbacks();
530+
517531
m_mapped = false;
518532
m_lastTransform = std::nullopt;
519533
m_lastScale = std::nullopt;
@@ -607,6 +621,9 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) {
607621
if (!state.updated.all && m_mapped && state.fifoScheduled)
608622
return;
609623

624+
if (state.updated.all)
625+
PROTO::presentation->discardFeedbacks(m_current.presentationFeedbacks);
626+
610627
auto lastTexture = m_current.texture;
611628
m_current.updateFrom(state);
612629

@@ -777,7 +794,7 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) {
777794
void CWLSurfaceResource::presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded) {
778795
frame(when);
779796

780-
auto FEEDBACK = makeUnique(m_self.lock());
797+
auto FEEDBACK = makeUnique(m_self.lock(), std::move(m_current.presentationFeedbacks));
781798
FEEDBACK->attachMonitor(pMonitor);
782799
if (discarded)
783800
FEEDBACK->discarded();

‎src/protocols/core/Compositor.hpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ class CWLSurfaceResource {
145145
void releaseBuffers(bool onlyCurrent = true);
146146
void dropPendingBuffer();
147147
void dropCurrentBuffer();
148+
void discardPresentationFeedbacks();
148149
void bfHelper(std::span<const SP> nodes, std::function<void(SP, const Vector2D&, void*)> fn, void* data);
149150
SP findFirstPreorderHelper(SP root, std::function<bool(SP)> fn);
150151
void updateCursorShm(CRegion damage = CBox{0, 0, INT16_MAX, INT16_MAX});

‎src/protocols/types/SurfaceState.cpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ void SSurfaceState::reset() {
7373
bufferDamage.clear();
7474

7575
callbacks.clear();
76+
presentationFeedbacks.clear();
7677
lockMask = LOCK_REASON_NONE;
7778

7879
barrierSet = false;
@@ -134,6 +135,12 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) {
134135
ref.callbacks.clear();
135136
}
136137

138+
if (!ref.presentationFeedbacks.empty()) {
139+
presentationFeedbacks.insert(presentationFeedbacks.end(), std::make_move_iterator(ref.presentationFeedbacks.begin()),
140+
std::make_move_iterator(ref.presentationFeedbacks.end()));
141+
ref.presentationFeedbacks.clear();
142+
}
143+
137144
if (ref.barrierSet)
138145
barrierSet = ref.barrierSet;
139146
}

‎src/protocols/types/SurfaceState.hpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Render {
1111
}
1212
class CDRMSyncPointState;
1313
class CWLCallbackResource;
14+
class CPresentationFeedback;
1415

1516
enum eLockReason : uint8_t {
1617
LOCK_REASON_NONE = 0,
@@ -77,6 +78,9 @@ struct SSurfaceState {
7778
// for wl_surface::frame callbacks.
7879
std::vector<SP> callbacks;
7980

81+
// for wp_presentation feedbacks, tied to this commit.
82+
std::vector<WP> presentationFeedbacks;
83+
8084
// viewporter protocol surface state
8185
struct {
8286
bool hasDestination = false;

‎src/protocols/types/SurfaceStateQueue.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
#include "SurfaceStateQueue.hpp"
22
#include "../core/Compositor.hpp"
3+
#include "../PresentationTime.hpp"
34
#include "SurfaceState.hpp"
45

56
CSurfaceStateQueue::CSurfaceStateQueue(WP surf) : m_surface(std::move(surf)) {}
67

78
void CSurfaceStateQueue::clear() {
9+
for (auto& state : m_queue)
10+
PROTO::presentation->discardFeedbacks(state->presentationFeedbacks);
11+
812
m_queue.clear();
913
}
1014

@@ -17,6 +21,8 @@ void CSurfaceStateQueue::dropState(const WP& state) {
1721
if (it == m_queue.end())
1822
return;
1923

24+
PROTO::presentation->discardFeedbacks((*it)->presentationFeedbacks);
25+
2026
m_queue.erase(it);
2127
}
2228

‎src/render/ElementRenderer.cpp‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,15 +225,19 @@ void IElementRenderer::drawSurface(WP element, const CRegio
225225
g_pHyprRenderer->m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
226226
}};
227227

228-
if (!m_data.texture)
228+
if (!m_data.texture) {
229+
element->discard();
229230
return;
231+
}
230232

231233
const auto& TEXTURE = m_data.texture;
232234

233235
// this is bad, probably has been logged elsewhere. Means the texture failed
234236
// uploading to the GPU.
235-
if (!TEXTURE->ok())
237+
if (!TEXTURE->ok()) {
238+
element->discard();
236239
return;
240+
}
237241

238242
const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_layoutManager->dragController()->target() && g_layoutManager->dragController()->mode() == MBIND_RESIZE;
239243
TRACY_GPU_ZONE("RenderSurface");
@@ -266,8 +270,10 @@ void IElementRenderer::drawSurface(WP element, const CRegio
266270

267271
auto cancelRender = false;
268272
auto clipRegion = element->visibleRegion(cancelRender);
269-
if (cancelRender)
273+
if (cancelRender) {
274+
element->discard();
270275
return;
276+
}
271277

272278
// check for fractional scale surfaces misaligning the buffer size
273279
// in those cases it's better to just force nearest neighbor
@@ -380,6 +386,9 @@ void IElementRenderer::drawSurface(WP element, const CRegio
380386
}
381387

382388
g_pHyprRenderer->blend(true);
389+
390+
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback)
391+
element->m_data.surface->presentFeedback(element->m_data.when, element->m_data.pMonitor->m_self.lock());
383392
};
384393

385394
void IElementRenderer::preDrawSurface(WP element, const CRegion& damage) {
@@ -391,9 +400,6 @@ void IElementRenderer::preDrawSurface(WP element, const CRe
391400

392401
drawSurface(element, damage);
393402

394-
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback)
395-
element->m_data.surface->presentFeedback(element->m_data.when, element->m_data.pMonitor->m_self.lock());
396-
397403
// add async (dmabuf) buffers to usedBuffers so we can handle release later
398404
// sync (shm) buffers will be released in commitState, so no need to track them here
399405
if (element->m_data.surface->m_current.buffer && !element->m_data.surface->m_current.buffer->isSynchronous())

0 commit comments

Comments
 (0)