From 82759d4095dc95a0d10aefe87072385dce9a4bf1 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Wed, 8 Oct 2025 22:25:55 +0200 Subject: [PATCH] buffer: move texture creation to commit time (#11964) * buffer: move texture creation to commit time move creating texture away from buffer attach into commitstate in an attempt to postpone gpu work until its really needed. best case scenario gpu clocks have ramped up before because we are actively doing things causing surface states and a commit to happend meaning less visible lag. * buffer: simplify texture creation make createTexture return a shared ptr directly, remove not needed member variables as m_success and m_texture. --- src/protocols/LinuxDMABUF.cpp | 5 +-- src/protocols/MesaDRM.cpp | 3 -- src/protocols/SinglePixel.cpp | 18 +++++++---- src/protocols/SinglePixel.hpp | 1 + src/protocols/core/Compositor.cpp | 8 ++--- src/protocols/core/Shm.cpp | 4 +++ src/protocols/core/Shm.hpp | 1 + src/protocols/types/Buffer.hpp | 3 +- src/protocols/types/DMABuffer.cpp | 48 +++++++++++++++------------- src/protocols/types/DMABuffer.hpp | 3 +- src/protocols/types/SurfaceState.cpp | 4 ++- 11 files changed, 53 insertions(+), 45 deletions(-) diff --git a/src/protocols/LinuxDMABUF.cpp b/src/protocols/LinuxDMABUF.cpp index c7de03a2..0ad804c3 100644 --- a/src/protocols/LinuxDMABUF.cpp +++ b/src/protocols/LinuxDMABUF.cpp @@ -103,9 +103,6 @@ CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDM m_listeners.bufferResourceDestroy.reset(); PROTO::linuxDma->destroyResource(this); }); - - if (!m_buffer->m_success) - LOGM(ERR, "Possibly compositor bug: buffer failed to create"); } CLinuxDMABuffer::~CLinuxDMABuffer() { @@ -217,7 +214,7 @@ void CLinuxDMABUFParamsResource::create(uint32_t id) { auto& buf = PROTO::linuxDma->m_buffers.emplace_back(makeUnique(id, m_resource->client(), *m_attrs)); - if UNLIKELY (!buf->good() || !buf->m_buffer->m_success) { + if UNLIKELY (!buf->good()) { m_resource->sendFailed(); PROTO::linuxDma->m_buffers.pop_back(); return; diff --git a/src/protocols/MesaDRM.cpp b/src/protocols/MesaDRM.cpp index 789f90b6..7595d57f 100644 --- a/src/protocols/MesaDRM.cpp +++ b/src/protocols/MesaDRM.cpp @@ -18,9 +18,6 @@ CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, A m_listeners.bufferResourceDestroy.reset(); PROTO::mesaDRM->destroyResource(this); }); - - if (!m_buffer->m_success) - LOGM(ERR, "Possibly compositor bug: buffer failed to create"); } CMesaDRMBufferResource::~CMesaDRMBufferResource() { diff --git a/src/protocols/SinglePixel.cpp b/src/protocols/SinglePixel.cpp index 6ca48a35..9abde68a 100644 --- a/src/protocols/SinglePixel.cpp +++ b/src/protocols/SinglePixel.cpp @@ -12,16 +12,9 @@ CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColo m_opaque = col_.a >= 1.F; - m_texture = makeShared(DRM_FORMAT_ARGB8888, rc(&m_color), 4, Vector2D{1, 1}); - m_resource = CWLBufferResource::create(makeShared(client, 1, id)); - m_success = m_texture->m_texID; - size = {1, 1}; - - if (!m_success) - Debug::log(ERR, "Failed creating a single pixel texture: null texture id"); } CSinglePixelBuffer::~CSinglePixelBuffer() { @@ -57,6 +50,17 @@ void CSinglePixelBuffer::endDataPtr() { ; } +SP CSinglePixelBuffer::createTexture() { + auto tex = makeShared(DRM_FORMAT_ARGB8888, rc(&m_color), 4, Vector2D{1, 1}); + + if (!tex->m_texID) { + Debug::log(ERR, "Failed creating a single pixel texture: null texture id"); + return nullptr; + } + + return tex; +} + bool CSinglePixelBuffer::good() { return m_resource->good(); } diff --git a/src/protocols/SinglePixel.hpp b/src/protocols/SinglePixel.hpp index f8bbfba9..40fbb968 100644 --- a/src/protocols/SinglePixel.hpp +++ b/src/protocols/SinglePixel.hpp @@ -18,6 +18,7 @@ class CSinglePixelBuffer : public IHLBuffer { virtual Aquamarine::SDMABUFAttrs dmabuf(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); + virtual SP createTexture(); // bool good(); bool m_success = false; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 955ba5ca..8ad2a373 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -91,12 +91,10 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : m_resource(re if (buf && buf->m_buffer) { m_pending.buffer = CHLBufferReference(buf->m_buffer.lock()); - m_pending.texture = buf->m_buffer->m_texture; m_pending.size = buf->m_buffer->size; m_pending.bufferSize = buf->m_buffer->size; } else { - m_pending.buffer = {}; - m_pending.texture.reset(); + m_pending.buffer = {}; m_pending.size = Vector2D{}; m_pending.bufferSize = Vector2D{}; } @@ -132,7 +130,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : m_resource(re } // null buffer attached - if (!m_pending.buffer && !m_pending.texture && m_pending.updated.bits.buffer) { + if (!m_pending.buffer && m_pending.updated.bits.buffer) { commitState(m_pending); // remove any pending states. @@ -528,6 +526,8 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) { if (m_current.buffer) { if (m_current.buffer->isSynchronous()) m_current.updateSynchronousTexture(lastTexture); + else if (!m_current.buffer->isSynchronous() && state.updated.bits.buffer) // only get a new texture when a new buffer arrived + m_current.texture = m_current.buffer->createTexture(); // if the surface is a cursor, update the shm buffer // TODO: don't update the entire texture diff --git a/src/protocols/core/Shm.cpp b/src/protocols/core/Shm.cpp index 43c087bc..30189d8b 100644 --- a/src/protocols/core/Shm.cpp +++ b/src/protocols/core/Shm.cpp @@ -69,6 +69,10 @@ void CWLSHMBuffer::endDataPtr() { ; } +SP CWLSHMBuffer::createTexture() { + return nullptr; +} + bool CWLSHMBuffer::good() { return true; } diff --git a/src/protocols/core/Shm.hpp b/src/protocols/core/Shm.hpp index 37210398..fba3de8d 100644 --- a/src/protocols/core/Shm.hpp +++ b/src/protocols/core/Shm.hpp @@ -43,6 +43,7 @@ class CWLSHMBuffer : public IHLBuffer { virtual Aquamarine::SSHMAttrs shm(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); + virtual SP createTexture(); bool good(); diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp index f5c1d848..428132c5 100644 --- a/src/protocols/types/Buffer.hpp +++ b/src/protocols/types/Buffer.hpp @@ -22,11 +22,11 @@ class IHLBuffer : public Aquamarine::IBuffer { virtual void lock(); virtual void unlock(); virtual bool locked(); + virtual SP createTexture() = 0; void onBackendRelease(const std::function& fn); void addReleasePoint(CDRMSyncPointState& point); - SP m_texture; bool m_opaque = false; SP m_resource; std::vector> m_syncReleasers; @@ -38,7 +38,6 @@ class IHLBuffer : public Aquamarine::IBuffer { private: int m_locks = 0; - std::function m_backendReleaseQueuedFn; friend class CHLBufferReference; diff --git a/src/protocols/types/DMABuffer.cpp b/src/protocols/types/DMABuffer.cpp index 464008f4..b361c6c8 100644 --- a/src/protocols/types/DMABuffer.cpp +++ b/src/protocols/types/DMABuffer.cpp @@ -13,34 +13,14 @@ using namespace Hyprutils::OS; CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_) : m_attrs(attrs_) { - g_pHyprRenderer->makeEGLCurrent(); - m_listeners.resourceDestroy = events.destroy.listen([this] { closeFDs(); m_listeners.resourceDestroy.reset(); }); size = m_attrs.size; + m_opaque = NFormatUtils::isFormatOpaque(m_attrs.format); m_resource = CWLBufferResource::create(makeShared(client, 1, id)); - - auto eglImage = g_pHyprOpenGL->createEGLImage(m_attrs); - - if UNLIKELY (!eglImage) { - Debug::log(ERR, "CDMABuffer: failed to import EGLImage, retrying as implicit"); - m_attrs.modifier = DRM_FORMAT_MOD_INVALID; - eglImage = g_pHyprOpenGL->createEGLImage(m_attrs); - if UNLIKELY (!eglImage) { - Debug::log(ERR, "CDMABuffer: failed to import EGLImage"); - return; - } - } - - m_texture = makeShared(m_attrs, eglImage); // texture takes ownership of the eglImage - m_opaque = NFormatUtils::isFormatOpaque(m_attrs.format); - m_success = m_texture->m_texID; - - if UNLIKELY (!m_success) - Debug::log(ERR, "Failed to create a dmabuf: texture is null"); } CDMABuffer::~CDMABuffer() { @@ -79,8 +59,32 @@ void CDMABuffer::endDataPtr() { // FIXME: } +SP CDMABuffer::createTexture() { + g_pHyprRenderer->makeEGLCurrent(); + auto eglImage = g_pHyprOpenGL->createEGLImage(m_attrs); + + if UNLIKELY (!eglImage) { + Debug::log(ERR, "CDMABuffer: failed to import EGLImage, retrying as implicit"); + m_attrs.modifier = DRM_FORMAT_MOD_INVALID; + eglImage = g_pHyprOpenGL->createEGLImage(m_attrs); + if UNLIKELY (!eglImage) { + Debug::log(ERR, "CDMABuffer: failed to import EGLImage"); + return nullptr; + } + } + + auto tex = makeShared(m_attrs, eglImage); // texture takes ownership of the eglImage + + if UNLIKELY (!tex->m_texID) { + Debug::log(ERR, "Failed to create a dmabuf: texture is null"); + return nullptr; + } + + return tex; +} + bool CDMABuffer::good() { - return m_success; + return m_attrs.success; } void CDMABuffer::closeFDs() { diff --git a/src/protocols/types/DMABuffer.hpp b/src/protocols/types/DMABuffer.hpp index 19f2ddf7..14c1eb75 100644 --- a/src/protocols/types/DMABuffer.hpp +++ b/src/protocols/types/DMABuffer.hpp @@ -15,12 +15,11 @@ class CDMABuffer : public IHLBuffer { virtual Aquamarine::SDMABUFAttrs dmabuf(); virtual std::tuple beginDataPtr(uint32_t flags); virtual void endDataPtr(); + virtual SP createTexture(); bool good(); void closeFDs(); Hyprutils::OS::CFileDescriptor exportSyncFile(); - bool m_success = false; - private: Aquamarine::SDMABUFAttrs m_attrs; diff --git a/src/protocols/types/SurfaceState.cpp b/src/protocols/types/SurfaceState.cpp index 6be8e173..248ce835 100644 --- a/src/protocols/types/SurfaceState.cpp +++ b/src/protocols/types/SurfaceState.cpp @@ -68,8 +68,10 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) { updated = ref.updated; if (ref.updated.bits.buffer) { + if (!ref.buffer.m_buffer) + texture.reset(); // null buffer reset texture. + buffer = ref.buffer; - texture = ref.texture; size = ref.size; bufferSize = ref.bufferSize; }