diff --git a/src/core/renderbackend.cpp b/src/core/renderbackend.cpp index f05f72b830..845abc6e9d 100644 --- a/src/core/renderbackend.cpp +++ b/src/core/renderbackend.cpp @@ -83,18 +83,6 @@ std::unique_ptr RenderBackend::createSurfaceTextureWayland(Surfa return nullptr; } -PresentationFeedback::PresentationFeedback(std::vector> &&feedbacks) - : m_subFeedbacks(std::move(feedbacks)) -{ -} - -void PresentationFeedback::presented(std::chrono::nanoseconds refreshCycleDuration, std::chrono::nanoseconds timestamp, PresentationMode mode) -{ - for (const auto &feedback : m_subFeedbacks) { - feedback->presented(refreshCycleDuration, timestamp, mode); - } -} - } // namespace KWin #include "moc_renderbackend.cpp" diff --git a/src/core/renderbackend.h b/src/core/renderbackend.h index 8d18ae542b..28534540cc 100644 --- a/src/core/renderbackend.h +++ b/src/core/renderbackend.h @@ -31,15 +31,11 @@ class PresentationFeedback { public: explicit PresentationFeedback() = default; - explicit PresentationFeedback(std::vector> &&feedbacks); PresentationFeedback(const PresentationFeedback ©) = delete; PresentationFeedback(PresentationFeedback &&move) = default; virtual ~PresentationFeedback() = default; - virtual void presented(std::chrono::nanoseconds refreshCycleDuration, std::chrono::nanoseconds timestamp, PresentationMode mode); - -private: - std::vector> m_subFeedbacks; + virtual void presented(std::chrono::nanoseconds refreshCycleDuration, std::chrono::nanoseconds timestamp, PresentationMode mode) = 0; }; class KWIN_EXPORT OutputFrame diff --git a/src/wayland/presentationtime.cpp b/src/wayland/presentationtime.cpp index 44aa90adf1..8520f276f4 100644 --- a/src/wayland/presentationtime.cpp +++ b/src/wayland/presentationtime.cpp @@ -32,29 +32,37 @@ void PresentationTime::wp_presentation_feedback(Resource *resource, wl_resource { SurfaceInterface *surf = SurfaceInterface::get(surface); SurfaceInterfacePrivate *surfPriv = SurfaceInterfacePrivate::get(surf); - surfPriv->pending->presentationFeedbacks.push_back(std::make_unique(surf, resource->client(), callback)); + + auto &feedback = surfPriv->pending->presentationFeedback; + if (!feedback) { + feedback = std::make_unique(); + } + + wl_resource *feedbackResource = wl_resource_create(resource->client(), &wp_presentation_feedback_interface, resource->version(), callback); + wl_resource_set_implementation(feedbackResource, nullptr, nullptr, [](wl_resource *resource) { + wl_list_remove(wl_resource_get_link(resource)); + }); + + wl_list_insert(feedback->resources.prev, wl_resource_get_link(feedbackResource)); } -PresentationTimeFeedback::PresentationTimeFeedback(SurfaceInterface *surface, wl_client *client, uint32_t id) - : QtWaylandServer::wp_presentation_feedback(client, id, 1) - , m_surface(surface) +PresentationTimeFeedback::PresentationTimeFeedback() { + wl_list_init(&resources); } PresentationTimeFeedback::~PresentationTimeFeedback() { - if (m_destroyed) { - return; + wl_resource *resource; + wl_resource *tmp; + wl_resource_for_each_safe (resource, tmp, &resources) { + wp_presentation_feedback_send_discarded(resource); + wl_resource_destroy(resource); } - send_discarded(); - wl_resource_destroy(resource()->handle); } void PresentationTimeFeedback::presented(std::chrono::nanoseconds refreshCycleDuration, std::chrono::nanoseconds timestamp, PresentationMode mode) { - if (m_destroyed) { - return; - } const auto secs = std::chrono::duration_cast(timestamp); const uint32_t tvSecHi = secs.count() >> 32; const uint32_t tvSecLo = secs.count() & 0xffffffff; @@ -67,13 +75,11 @@ void PresentationTimeFeedback::presented(std::chrono::nanoseconds refreshCycleDu flags |= WP_PRESENTATION_FEEDBACK_KIND_VSYNC; } - send_presented(resource()->handle, tvSecHi, tvSecLo, tvNsec, refreshDuration, 0, 0, flags); - wl_resource_destroy(resource()->handle); - m_destroyed = true; -} - -void PresentationTimeFeedback::wp_presentation_feedback_destroy_resource(Resource *resource) -{ - m_destroyed = true; + wl_resource *resource; + wl_resource *tmp; + wl_resource_for_each_safe (resource, tmp, &resources) { + wp_presentation_feedback_send_presented(resource, tvSecHi, tvSecLo, tvNsec, refreshDuration, 0, 0, flags); + wl_resource_destroy(resource); + } } } diff --git a/src/wayland/presentationtime.h b/src/wayland/presentationtime.h index 2d12e54630..d53116b152 100644 --- a/src/wayland/presentationtime.h +++ b/src/wayland/presentationtime.h @@ -30,19 +30,15 @@ private: void wp_presentation_feedback(Resource *resource, wl_resource *surface, uint32_t callback) override; }; -class PresentationTimeFeedback : public PresentationFeedback, public QtWaylandServer::wp_presentation_feedback +class PresentationTimeFeedback : public PresentationFeedback { public: - explicit PresentationTimeFeedback(SurfaceInterface *surface, wl_client *client, uint32_t id); + PresentationTimeFeedback(); ~PresentationTimeFeedback() override; + wl_list resources; + void presented(std::chrono::nanoseconds refreshCycleDuration, std::chrono::nanoseconds timestamp, PresentationMode mode) override; - -private: - void wp_presentation_feedback_destroy_resource(Resource *resource) override; - - SurfaceInterface *const m_surface; - bool m_destroyed = false; }; } diff --git a/src/wayland/surface.cpp b/src/wayland/surface.cpp index d974668ca9..2e3107e0d5 100644 --- a/src/wayland/surface.cpp +++ b/src/wayland/surface.cpp @@ -474,10 +474,7 @@ std::unique_ptr SurfaceInterface::takePresentationFeedback if (output && (!d->primaryOutput || d->primaryOutput->handle() != output)) { return nullptr; } - std::vector> feedbacks; - std::move(d->current->presentationFeedbacks.begin(), d->current->presentationFeedbacks.end(), std::back_inserter(feedbacks)); - d->current->presentationFeedbacks.clear(); - return std::make_unique(std::move(feedbacks)); + return std::move(d->current->presentationFeedback); } bool SurfaceInterface::hasFrameCallbacks() const @@ -652,10 +649,9 @@ void SurfaceState::mergeInto(SurfaceState *target) target->colorDescription = colorDescription; target->colorDescriptionIsSet = true; } - for (auto &f : presentationFeedbacks) { - target->presentationFeedbacks.push_back(std::move(f)); + if (presentationFeedback) { + target->presentationFeedback = std::move(presentationFeedback); } - presentationFeedbacks.clear(); *this = SurfaceState{}; serial = target->serial; @@ -683,7 +679,7 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next) const QRegion oldInputRegion = inputRegion; if (!next->damage.isEmpty() || !next->bufferDamage.isEmpty()) { - current->presentationFeedbacks.clear(); + current->presentationFeedback.reset(); } next->mergeInto(current.get()); bufferRef = current->buffer; diff --git a/src/wayland/surface_p.h b/src/wayland/surface_p.h index 03ded68d49..034a14279c 100644 --- a/src/wayland/surface_p.h +++ b/src/wayland/surface_p.h @@ -69,7 +69,7 @@ struct SurfaceState ContentType contentType = ContentType::None; PresentationHint presentationHint = PresentationHint::VSync; ColorDescription colorDescription = ColorDescription::sRGB; - std::vector> presentationFeedbacks; + std::unique_ptr presentationFeedback; struct {