scene: ensure OpenGL texture is updated after direct scanout

While direct scanout happens, the damage of the SurfaceItem is reset, which
can cause the OpenGL texture to not be updated once direct scanout ends,
and leave the texture outdated until the surface is damaged again.
In order to fix that, make sure the texture is always fully updated after
the SurfaceItem has been used in direct scanout.
This commit is contained in:
Xaver Hugl 2022-12-30 00:20:37 +01:00
parent 501a45a869
commit d49cb64231
5 changed files with 11 additions and 6 deletions

View file

@ -149,6 +149,8 @@ bool EglGbmLayer::scanout(SurfaceItem *surfaceItem)
m_dmabufFeedback.scanoutSuccessful(surface);
m_currentDamage = surfaceItem->damage();
surfaceItem->resetDamage();
// ensure the pixmap is updated when direct scanout ends
surfaceItem->destroyPixmap();
return true;
} else {
m_dmabufFeedback.scanoutFailed(surface, formats);

View file

@ -162,6 +162,8 @@ bool VirtualEglGbmLayer::scanout(SurfaceItem *surfaceItem)
// damage tracking for screen casting
m_currentDamage = m_scanoutSurface == item->surface() ? surfaceItem->damage() : infiniteRegion();
surfaceItem->resetDamage();
// ensure the pixmap is updated when direct scanout ends
surfaceItem->destroyPixmap();
m_scanoutSurface = item->surface();
m_currentBuffer = scanoutBuffer;
return true;

View file

@ -105,6 +105,11 @@ void SurfaceItem::discardPixmap()
addDamage(rect().toAlignedRect());
}
void SurfaceItem::destroyPixmap()
{
m_pixmap.reset();
}
void SurfaceItem::preprocess()
{
updatePixmap();

View file

@ -32,6 +32,7 @@ public:
void discardPixmap();
void updatePixmap();
void destroyPixmap();
SurfacePixmap *pixmap() const;
SurfacePixmap *previousPixmap() const;

View file

@ -165,17 +165,12 @@ SurfaceItem *WorkspaceScene::scanoutCandidate() const
break;
}
SurfaceItem *topMost = findTopMostSurface(windowItem->surfaceItem());
auto pixmap = topMost->pixmap();
if (!pixmap) {
break;
}
pixmap->update();
// the subsurface has to be able to cover the whole window
if (topMost->position() != QPoint(0, 0)) {
break;
}
// and it has to be completely opaque
if (pixmap->hasAlphaChannel() && !topMost->opaque().contains(QRect(0, 0, window->width(), window->height()))) {
if (!topMost->opaque().contains(QRect(0, 0, window->width(), window->height()))) {
break;
}
candidate = topMost;