core/compositor: Correctly track SHM buffer damage (#9678)

This commit is contained in:
Lee Bousfield 2025-03-22 11:13:44 -05:00 committed by GitHub
parent 4600043a49
commit 6384f4acf4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 103 additions and 82 deletions

View file

@ -0,0 +1,58 @@
#include "SurfaceState.hpp"
#include "helpers/Format.hpp"
#include "protocols/types/Buffer.hpp"
#include "render/Texture.hpp"
Vector2D SSurfaceState::sourceSize() {
if UNLIKELY (!texture)
return {};
if UNLIKELY (viewport.hasSource)
return viewport.source.size();
Vector2D trc = transform % 2 == 1 ? Vector2D{bufferSize.y, bufferSize.x} : bufferSize;
return trc / scale;
}
CRegion SSurfaceState::accumulateBufferDamage() {
if (damage.empty())
return bufferDamage;
CRegion surfaceDamage = damage;
if (viewport.hasDestination) {
Vector2D scale = sourceSize() / viewport.destination;
surfaceDamage.scale(scale);
}
if (viewport.hasSource)
surfaceDamage.translate(viewport.source.pos());
Vector2D trc = transform % 2 == 1 ? Vector2D{bufferSize.y, bufferSize.x} : bufferSize;
bufferDamage = surfaceDamage.scale(scale).transform(wlTransformToHyprutils(invertTransform(transform)), trc.x, trc.y).add(bufferDamage);
damage.clear();
return bufferDamage;
}
void SSurfaceState::updateSynchronousTexture(SP<CTexture> lastTexture) {
auto [dataPtr, fmt, size] = buffer->buffer->beginDataPtr(0);
if (dataPtr) {
auto drmFmt = NFormatUtils::shmToDRM(fmt);
auto stride = bufferSize.y ? size / bufferSize.y : 0;
if (lastTexture && lastTexture->m_isSynchronous && lastTexture->m_vSize == bufferSize) {
texture = lastTexture;
texture->update(drmFmt, dataPtr, stride, accumulateBufferDamage());
} else
texture = makeShared<CTexture>(drmFmt, dataPtr, stride, bufferSize);
}
buffer->buffer->endDataPtr();
}
void SSurfaceState::reset() {
damage.clear();
bufferDamage.clear();
transform = WL_OUTPUT_TRANSFORM_NORMAL;
scale = 1;
offset = {};
size = {};
}

View file

@ -20,16 +20,12 @@ struct SSurfaceState {
Vector2D destination;
CBox source;
} viewport;
bool rejected = false;
bool newBuffer = false;
bool rejected = false;
bool newBuffer = false;
//
void reset() {
damage.clear();
bufferDamage.clear();
transform = WL_OUTPUT_TRANSFORM_NORMAL;
scale = 1;
offset = {};
size = {};
}
Vector2D sourceSize();
// Translates damage into bufferDamage, clearing damage and returning the updated bufferDamage
CRegion accumulateBufferDamage();
void updateSynchronousTexture(SP<CTexture> lastTexture);
void reset();
};