Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 61 additions & 10 deletions src/protocols/PresentationTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include "core/Output.hpp"
#include <aquamarine/output/Output.hpp>

CQueuedPresentationData::CQueuedPresentationData(SP<CWLSurfaceResource> surf) : m_surface(surf) {
CQueuedPresentationData::CQueuedPresentationData(SP<CWLSurfaceResource> surf, std::vector<WP<CPresentationFeedback>> feedbacks) :
m_surface(surf), m_feedbacks(std::move(feedbacks)) {
;
}

Expand Down Expand Up @@ -76,9 +77,23 @@ void CPresentationFeedback::sendQueued(WP<CQueuedPresentationData> data, const t
m_done = true;
}

void CPresentationFeedback::sendDiscarded() {
if (m_done)
return;

m_resource->sendDiscarded();
m_done = true;
}

CPresentationProtocol::CPresentationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
static auto P = Event::bus()->m_events.monitor.removed.listen(
[this](PHLMONITOR mon) { std::erase_if(m_queue, [mon](const auto& other) { return !other->m_surface || other->m_monitor == mon; }); });
static auto P = Event::bus()->m_events.monitor.removed.listen([this](PHLMONITOR mon) {
for (auto& data : m_queue) {
if (!data->m_surface || data->m_monitor == mon)
discardFeedbacks(data->m_feedbacks);
}

std::erase_if(m_queue, [mon](const auto& other) { return !other->m_surface || other->m_monitor == mon; });
});
}

void CPresentationProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
Expand All @@ -95,33 +110,41 @@ void CPresentationProtocol::onManagerResourceDestroy(wl_resource* res) {
}

void CPresentationProtocol::destroyResource(CPresentationFeedback* feedback) {
feedback->m_done = true;
Comment thread
vaxerski marked this conversation as resolved.
std::erase_if(m_feedbacks, [&](const auto& other) { return other.get() == feedback; });
}

void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* surf, uint32_t id) {
const auto CLIENT = pMgr->client();
const auto& RESOURCE =
m_feedbacks.emplace_back(makeUnique<CPresentationFeedback>(makeUnique<CWpPresentationFeedback>(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf))).get();
m_feedbacks.emplace_back(makeUnique<CPresentationFeedback>(makeUnique<CWpPresentationFeedback>(CLIENT, pMgr->version(), id), CWLSurfaceResource::fromResource(surf)));

if UNLIKELY (!RESOURCE->good()) {
pMgr->noMemory();
m_feedbacks.pop_back();
return;
}

if (const auto SURFACE = CWLSurfaceResource::fromResource(surf); SURFACE)
SURFACE->m_pending.presentationFeedbacks.emplace_back(RESOURCE);
}

void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, const timespec& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) {
for (auto const& feedback : m_feedbacks) {
if (!feedback->m_surface)
for (auto const& data : m_queue) {
if (!data->m_surface || !data->m_monitor) {
discardFeedbacks(data->m_feedbacks);
continue;
}

for (auto const& data : m_queue) {
if (!data->m_surface || data->m_surface != feedback->m_surface || (data->m_monitor && data->m_monitor != pMonitor))
if (data->m_monitor != pMonitor)
continue;

for (auto const& feedbackRef : data->m_feedbacks) {
const auto feedback = feedbackRef.lock();
if (!feedback || feedback->m_done)
continue;

feedback->sendQueued(data, when, untilRefreshNs, seq, reportedFlags);
feedback->m_done = true;
break;
}
}

Expand All @@ -147,6 +170,34 @@ void CPresentationProtocol::queueData(UP<CQueuedPresentationData>&& data) {
m_queue.emplace_back(std::move(data));
}

void CPresentationProtocol::discardFeedbacks(std::vector<WP<CPresentationFeedback>>& feedbacks) {
for (auto const& feedbackRef : feedbacks) {
const auto feedback = feedbackRef.lock();
if (!feedback || feedback->m_done)
continue;

feedback->sendDiscarded();
}

feedbacks.clear();
std::erase_if(m_feedbacks, [](const auto& other) { return !other->m_surface || other->m_done; });
}

void CPresentationProtocol::discardFeedbacksForSurface(WP<CWLSurfaceResource> surface) {
if (!surface)
return;

for (auto const& feedback : m_feedbacks) {
if (feedback->m_surface != surface)
continue;

feedback->sendDiscarded();
}

std::erase_if(m_queue, [surface](const auto& other) { return !other->m_surface || other->m_surface == surface; });
std::erase_if(m_feedbacks, [](const auto& other) { return !other->m_surface || other->m_done; });
}

bool CPresentationProtocol::hasPendingFeedbacks() const {
return !m_feedbacks.empty();
}
15 changes: 10 additions & 5 deletions src/protocols/PresentationTime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
#include "../helpers/time/Time.hpp"

class CWLSurfaceResource;
class CPresentationFeedback;

class CQueuedPresentationData {
public:
CQueuedPresentationData(SP<CWLSurfaceResource> surf);
CQueuedPresentationData(SP<CWLSurfaceResource> surf, std::vector<WP<CPresentationFeedback>> feedbacks);

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

private:
bool m_wasPresented = false;
bool m_zeroCopy = false;
PHLMONITORREF m_monitor;
WP<CWLSurfaceResource> m_surface;
bool m_wasPresented = false;
bool m_zeroCopy = false;
PHLMONITORREF m_monitor;
WP<CWLSurfaceResource> m_surface;
std::vector<WP<CPresentationFeedback>> m_feedbacks;

friend class CPresentationFeedback;
friend class CPresentationProtocol;
Expand All @@ -38,6 +40,7 @@ class CPresentationFeedback {
bool good();

void sendQueued(WP<CQueuedPresentationData> data, const timespec& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags);
void sendDiscarded();

private:
UP<CWpPresentationFeedback> m_resource;
Expand All @@ -55,6 +58,8 @@ class CPresentationProtocol : public IWaylandProtocol {

void onPresented(PHLMONITOR pMonitor, const timespec& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags);
void queueData(UP<CQueuedPresentationData>&& data);
void discardFeedbacks(std::vector<WP<CPresentationFeedback>>& feedbacks);
void discardFeedbacksForSurface(WP<CWLSurfaceResource> surface);
bool hasPendingFeedbacks() const;

private:
Expand Down
15 changes: 14 additions & 1 deletion src/protocols/core/Compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
m_events.precommit.emit();
if (m_pending.rejected) {
m_pending.rejected = false;
PROTO::presentation->discardFeedbacks(m_pending.presentationFeedbacks);
dropPendingBuffer();
return;
}
Expand Down Expand Up @@ -253,10 +254,19 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
}

CWLSurfaceResource::~CWLSurfaceResource() {
discardPresentationFeedbacks();
m_events.destroy.emit();
}

void CWLSurfaceResource::discardPresentationFeedbacks() {
PROTO::presentation->discardFeedbacks(m_pending.presentationFeedbacks);
PROTO::presentation->discardFeedbacks(m_current.presentationFeedbacks);
PROTO::presentation->discardFeedbacksForSurface(m_self);
}

void CWLSurfaceResource::destroy() {
discardPresentationFeedbacks();

if (m_mapped) {
m_events.unmap.emit();
unmap();
Expand Down Expand Up @@ -607,6 +617,9 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) {
if (!state.updated.all && m_mapped && state.fifoScheduled)
return;

if (state.updated.all)
PROTO::presentation->discardFeedbacks(m_current.presentationFeedbacks);

auto lastTexture = m_current.texture;
m_current.updateFrom(state);

Expand Down Expand Up @@ -776,7 +789,7 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) {
void CWLSurfaceResource::presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded) {
frame(when);

auto FEEDBACK = makeUnique<CQueuedPresentationData>(m_self.lock());
auto FEEDBACK = makeUnique<CQueuedPresentationData>(m_self.lock(), std::move(m_current.presentationFeedbacks));
FEEDBACK->attachMonitor(pMonitor);
if (discarded)
FEEDBACK->discarded();
Expand Down
1 change: 1 addition & 0 deletions src/protocols/core/Compositor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class CWLSurfaceResource {
void releaseBuffers(bool onlyCurrent = true);
void dropPendingBuffer();
void dropCurrentBuffer();
void discardPresentationFeedbacks();
void bfHelper(std::span<const SP<CWLSurfaceResource>> nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
SP<CWLSurfaceResource> findFirstPreorderHelper(SP<CWLSurfaceResource> root, std::function<bool(SP<CWLSurfaceResource>)> fn);
void updateCursorShm(CRegion damage = CBox{0, 0, INT16_MAX, INT16_MAX});
Expand Down
7 changes: 7 additions & 0 deletions src/protocols/types/SurfaceState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ void SSurfaceState::reset() {
bufferDamage.clear();

callbacks.clear();
presentationFeedbacks.clear();
lockMask = LOCK_REASON_NONE;

barrierSet = false;
Expand Down Expand Up @@ -133,6 +134,12 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) {
ref.callbacks.clear();
}

if (!ref.presentationFeedbacks.empty()) {
presentationFeedbacks.insert(presentationFeedbacks.end(), std::make_move_iterator(ref.presentationFeedbacks.begin()),
std::make_move_iterator(ref.presentationFeedbacks.end()));
ref.presentationFeedbacks.clear();
}

if (ref.barrierSet)
barrierSet = ref.barrierSet;
}
4 changes: 4 additions & 0 deletions src/protocols/types/SurfaceState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Render {
}
class CDRMSyncPointState;
class CWLCallbackResource;
class CPresentationFeedback;

enum eLockReason : uint8_t {
LOCK_REASON_NONE = 0,
Expand Down Expand Up @@ -77,6 +78,9 @@ struct SSurfaceState {
// for wl_surface::frame callbacks.
std::vector<SP<CWLCallbackResource>> callbacks;

// for wp_presentation feedbacks, tied to this commit.
std::vector<WP<CPresentationFeedback>> presentationFeedbacks;

// viewporter protocol surface state
struct {
bool hasDestination = false;
Expand Down
6 changes: 6 additions & 0 deletions src/protocols/types/SurfaceStateQueue.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#include "SurfaceStateQueue.hpp"
#include "../core/Compositor.hpp"
#include "../PresentationTime.hpp"
#include "SurfaceState.hpp"

CSurfaceStateQueue::CSurfaceStateQueue(WP<CWLSurfaceResource> surf) : m_surface(std::move(surf)) {}

void CSurfaceStateQueue::clear() {
for (auto& state : m_queue)
PROTO::presentation->discardFeedbacks(state->presentationFeedbacks);

m_queue.clear();
}

Expand All @@ -17,6 +21,8 @@ void CSurfaceStateQueue::dropState(const WP<SSurfaceState>& state) {
if (it == m_queue.end())
return;

PROTO::presentation->discardFeedbacks((*it)->presentationFeedbacks);

m_queue.erase(it);
}

Expand Down
Loading