scene/workspacescene: do occlusion testing for direct scanout

Some clients have two or more completely opaque surfaces stacked on top of each other,
optimizing the lower ones out makes direct scanout happen more often and more efficiently
when multiple planes are involved
This commit is contained in:
Xaver Hugl 2024-08-02 20:46:39 +02:00
parent 4ebb8530e6
commit def0bde5e9

View file

@ -151,12 +151,15 @@ Item *WorkspaceScene::overlayItem() const
return m_overlayItem.get(); return m_overlayItem.get();
} }
static bool addCandidates(SurfaceItem *item, QList<SurfaceItem *> &candidates, ssize_t maxCount) static bool addCandidates(SurfaceItem *item, QList<SurfaceItem *> &candidates, ssize_t maxCount, QRegion &occluded)
{ {
const QList<Item *> children = item->sortedChildItems(); const QList<Item *> children = item->sortedChildItems();
for (const auto &child : children | std::views::reverse) { for (const auto &child : children | std::views::reverse) {
if (child->z() >= 0 && child->isVisible()) { if (child->z() < 0) {
if (!addCandidates(static_cast<SurfaceItem *>(child), candidates, maxCount)) { break;
}
if (child->isVisible() && !occluded.contains(child->mapToScene(child->boundingRect()).toAlignedRect())) {
if (!addCandidates(static_cast<SurfaceItem *>(child), candidates, maxCount, occluded)) {
return false; return false;
} }
} }
@ -165,9 +168,13 @@ static bool addCandidates(SurfaceItem *item, QList<SurfaceItem *> &candidates, s
return false; return false;
} }
candidates.push_back(item); candidates.push_back(item);
occluded += item->mapToScene(item->opaque());
for (const auto &child : children | std::views::reverse) { for (const auto &child : children | std::views::reverse) {
if (child->z() < 0 && child->isVisible()) { if (child->z() >= 0) {
if (!addCandidates(static_cast<SurfaceItem *>(child), candidates, maxCount)) { continue;
}
if (child->isVisible() && !occluded.contains(child->mapToScene(child->boundingRect()).toAlignedRect())) {
if (!addCandidates(static_cast<SurfaceItem *>(child), candidates, maxCount, occluded)) {
return false; return false;
} }
} }
@ -192,7 +199,8 @@ QList<SurfaceItem *> WorkspaceScene::scanoutCandidates(ssize_t maxCount) const
if (!windowItem->surfaceItem()) { if (!windowItem->surfaceItem()) {
continue; continue;
} }
if (!addCandidates(windowItem->surfaceItem(), ret, maxCount)) { QRegion occlusion;
if (!addCandidates(windowItem->surfaceItem(), ret, maxCount, occlusion)) {
return {}; return {};
} }
return ret; return ret;