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);