wayland: Make SurfaceInterface::{frameRendered,takePresentationFeedback} not touch subsurface tree

This gives us greater flexibility and in general more cleaner code.
This commit is contained in:
Vlad Zahorodnii 2023-11-14 08:58:00 +02:00
parent 9e047059c1
commit 79d5a70c01
8 changed files with 45 additions and 48 deletions

View file

@ -580,11 +580,6 @@ void TestSubSurface::testSyncMode()
QCOMPARE(childDamagedSpy.count(), 1);
QVERIFY(childSurface->isMapped());
QVERIFY(parentSurface->isMapped());
// sending frame rendered to parent should also send it to child
QSignalSpy frameRenderedSpy(surface.get(), &KWayland::Client::Surface::frameRendered);
parentSurface->frameRendered(100);
QVERIFY(frameRenderedSpy.wait());
}
void TestSubSurface::testDeSyncMode()

View file

@ -941,9 +941,10 @@ void CursorImage::updateCursorOutputs(const QPointF &pos)
void CursorImage::markAsRendered(std::chrono::milliseconds timestamp)
{
if (m_currentSource == m_serverCursor.surface.get()) {
auto cursorSurface = m_serverCursor.surface->surface();
if (cursorSurface) {
cursorSurface->frameRendered(timestamp.count());
if (auto cursorSurface = m_serverCursor.surface->surface()) {
cursorSurface->traverseTree([&timestamp](SurfaceInterface *surface) {
surface->frameRendered(timestamp.count());
});
}
}
}

View file

@ -30,16 +30,9 @@ DragAndDropIconItem::~DragAndDropIconItem()
{
}
void DragAndDropIconItem::frameRendered(quint32 timestamp)
SurfaceInterface *DragAndDropIconItem::surface() const
{
if (m_surfaceItem) {
m_surfaceItem->surface()->frameRendered(timestamp);
}
}
std::unique_ptr<PresentationFeedback> DragAndDropIconItem::takePresentationFeedback(Output *output)
{
return m_surfaceItem ? m_surfaceItem->surface()->takePresentationFeedback(output) : nullptr;
return m_surfaceItem ? m_surfaceItem->surface() : nullptr;
}
void DragAndDropIconItem::setOutput(Output *output)

View file

@ -25,8 +25,7 @@ public:
explicit DragAndDropIconItem(DragAndDropIcon *icon, Scene *scene, Item *parent = nullptr);
~DragAndDropIconItem() override;
void frameRendered(quint32 timestamp);
std::unique_ptr<PresentationFeedback> takePresentationFeedback(Output *output);
SurfaceInterface *surface() const;
void setOutput(Output *output);

View file

@ -201,17 +201,23 @@ void WorkspaceScene::frame(SceneDelegate *delegate, OutputFrame *frame)
continue;
}
if (auto surface = window->surface()) {
surface->frameRendered(frameTime.count());
if (auto feedback = surface->takePresentationFeedback(output)) {
frame->addFeedback(std::move(feedback));
}
surface->traverseTree([&frameTime, &frame, &output](SurfaceInterface *surface) {
surface->frameRendered(frameTime.count());
if (auto feedback = surface->takePresentationFeedback(output)) {
frame->addFeedback(std::move(feedback));
}
});
}
}
if (m_dndIcon) {
m_dndIcon->frameRendered(frameTime.count());
if (auto feedback = m_dndIcon->takePresentationFeedback(output)) {
frame->addFeedback(std::move(feedback));
if (auto surface = m_dndIcon->surface()) {
surface->traverseTree([&frameTime, &frame, &output](SurfaceInterface *surface) {
surface->frameRendered(frameTime.count());
if (auto feedback = surface->takePresentationFeedback(output)) {
frame->addFeedback(std::move(feedback));
}
});
}
}
}

View file

@ -467,13 +467,6 @@ void SurfaceInterface::frameRendered(quint32 msec)
wl_callback_send_done(resource, msec);
wl_resource_destroy(resource);
}
for (SubSurfaceInterface *subsurface : std::as_const(d->current->subsurface.below)) {
subsurface->surface()->frameRendered(msec);
}
for (SubSurfaceInterface *subsurface : std::as_const(d->current->subsurface.above)) {
subsurface->surface()->frameRendered(msec);
}
}
std::unique_ptr<PresentationFeedback> SurfaceInterface::takePresentationFeedback(Output *output)
@ -484,16 +477,6 @@ std::unique_ptr<PresentationFeedback> SurfaceInterface::takePresentationFeedback
std::vector<std::unique_ptr<PresentationFeedback>> feedbacks;
std::move(d->current->presentationFeedbacks.begin(), d->current->presentationFeedbacks.end(), std::back_inserter(feedbacks));
d->current->presentationFeedbacks.clear();
for (SubSurfaceInterface *subsurface : std::as_const(d->current->subsurface.below)) {
auto &subSurfaceFeedbacks = subsurface->surface()->d->current->presentationFeedbacks;
std::move(subSurfaceFeedbacks.begin(), subSurfaceFeedbacks.end(), std::back_inserter(feedbacks));
subSurfaceFeedbacks.clear();
}
for (SubSurfaceInterface *subsurface : std::as_const(d->current->subsurface.above)) {
auto &subSurfaceFeedbacks = subsurface->surface()->d->current->presentationFeedbacks;
std::move(subSurfaceFeedbacks.begin(), subSurfaceFeedbacks.end(), std::back_inserter(feedbacks));
subSurfaceFeedbacks.clear();
}
return std::make_unique<PresentationFeedback>(std::move(feedbacks));
}
@ -1260,6 +1243,18 @@ void SurfaceInterface::setLastTransaction(Transaction *transaction)
d->lastTransaction = transaction;
}
void SurfaceInterface::traverseTree(std::function<void(SurfaceInterface *surface)> callback)
{
callback(this);
for (SubSurfaceInterface *subsurface : std::as_const(d->current->subsurface.below)) {
subsurface->surface()->traverseTree(callback);
}
for (SubSurfaceInterface *subsurface : std::as_const(d->current->subsurface.above)) {
subsurface->surface()->traverseTree(callback);
}
}
} // namespace KWin
#include "moc_surface.cpp"

View file

@ -379,6 +379,11 @@ public:
void setPreferredColorDescription(const ColorDescription &descr);
/**
* Traverses the surface sub-tree with this surface as the root.
*/
void traverseTree(std::function<void(SurfaceInterface *surface)> callback);
Q_SIGNALS:
/**
* This signal is emitted when the underlying wl_surface resource is about to be freed.

View file

@ -4197,11 +4197,14 @@ void Window::unrefOffscreenRendering()
void Window::maybeSendFrameCallback()
{
if (m_surface && !m_windowItem->isVisible()) {
m_surface->frameRendered(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
const auto feedback = m_surface->takePresentationFeedback(nullptr);
if (feedback) {
feedback->presented(std::chrono::nanoseconds(1'000'000'000'000 / output()->refreshRate()), std::chrono::steady_clock::now().time_since_epoch(), PresentationMode::VSync);
}
const auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
m_surface->traverseTree([this, &timestamp](SurfaceInterface *surface) {
surface->frameRendered(timestamp);
const auto feedback = surface->takePresentationFeedback(nullptr);
if (feedback) {
feedback->presented(std::chrono::nanoseconds(1'000'000'000'000 / output()->refreshRate()), std::chrono::steady_clock::now().time_since_epoch(), PresentationMode::VSync);
}
});
// update refresh rate, it might have changed
m_offscreenFramecallbackTimer.start(1'000'000 / output()->refreshRate());
}