From 9994b73ad0af5c9ba5fc4058234cea77d0a1ddb1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 8 Jun 2024 17:27:50 +0200 Subject: [PATCH] buffer: track asynchronous buffers and don't release them until unref synchronous buffers are read instantly and we can release them, but asynchronous ones have to be locked until they are unref'd from .current to avoid reading from a buffer after .release() --- src/protocols/core/Compositor.cpp | 16 ++++++++++++---- src/protocols/core/Shm.cpp | 4 ++++ src/protocols/core/Shm.hpp | 1 + src/protocols/types/Buffer.hpp | 1 + src/protocols/types/DMABuffer.cpp | 4 ++++ src/protocols/types/DMABuffer.hpp | 1 + 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index e8503ae8..db6e3258 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -107,6 +107,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso pending.damage.intersect(CBox{{}, pending.size}); + auto previousBuffer = current.buffer; CRegion previousBufferDamage = accumulateCurrentBufferDamage(); current = pending; @@ -119,11 +120,12 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso // current.damage.copy().scale(current.scale).transform(current.transform, current.size.x, current.size.y).add(current.bufferDamage).add(previousBufferDamage); current.buffer->update(CBox{{}, {INT32_MAX, INT32_MAX}}); // FIXME: figure this out to not use this hack. QT apps are wonky without this. - // release the buffer, glTexImage2D is synchronous (as in, data is consumed after the call returns) + // release the buffer if it's synchronous as update() has done everything thats needed // so we can let the app know we're done. - // for dma buffers, this doesn't matter. - current.buffer->sendRelease(); - bufferReleased = true; + if (current.buffer->isSynchronous()) { + current.buffer->sendRelease(); + bufferReleased = true; + } } // TODO: we should _accumulate_ and not replace above if sync @@ -146,6 +148,12 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso }, nullptr); } + + // for async buffers, we can only release the buffer once we are unrefing it from current. + if (previousBuffer && !previousBuffer->isSynchronous() && !bufferReleased) { + previousBuffer->sendRelease(); + bufferReleased = true; + } }); resource->setDamage([this](CWlSurface* r, int32_t x, int32_t y, int32_t w, int32_t h) { pending.damage.add(CBox{x, y, w, h}); }); diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 0c01cf80..ce7d3a61 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -49,6 +49,10 @@ eBufferType CWLSHMBuffer::type() { return BUFFER_TYPE_SHM; } +bool CWLSHMBuffer::isSynchronous() { + return true; +} + SSHMAttrs CWLSHMBuffer::shm() { SSHMAttrs attrs; attrs.success = true; diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index 862ea112..687e2031 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -37,6 +37,7 @@ class CWLSHMBuffer : public IWLBuffer { virtual eBufferCapability caps(); virtual eBufferType type(); virtual void update(const CRegion& damage); + virtual bool isSynchronous(); virtual SSHMAttrs shm(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index c9902f8d..9999a4e9 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -49,6 +49,7 @@ class IWLBuffer { virtual eBufferCapability caps() = 0; virtual eBufferType type() = 0; virtual void update(const CRegion& damage) = 0; + virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu virtual SDMABUFAttrs dmabuf(); virtual SSHMAttrs shm(); virtual std::tuple beginDataPtr(uint32_t flags); diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index 930e71e6..f26328e9 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -43,6 +43,10 @@ void CDMABuffer::update(const CRegion& damage) { ; } +bool CDMABuffer::isSynchronous() { + return false; +} + SDMABUFAttrs CDMABuffer::dmabuf() { return attrs; } diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp index e06b5791..dac89493 100644 --- a/src/protocols/types/DMABuffer.hpp +++ b/src/protocols/types/DMABuffer.hpp @@ -9,6 +9,7 @@ class CDMABuffer : public IWLBuffer { virtual eBufferCapability caps(); virtual eBufferType type(); + virtual bool isSynchronous(); virtual void update(const CRegion& damage); virtual SDMABUFAttrs dmabuf(); virtual std::tuple beginDataPtr(uint32_t flags);