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.
This commit is contained in:
Tom Englund 2025-10-08 22:25:55 +02:00 committed by GitHub
parent 0dc45b54f3
commit 82759d4095
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 53 additions and 45 deletions

View file

@ -103,9 +103,6 @@ CLinuxDMABuffer::CLinuxDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDM
m_listeners.bufferResourceDestroy.reset(); m_listeners.bufferResourceDestroy.reset();
PROTO::linuxDma->destroyResource(this); PROTO::linuxDma->destroyResource(this);
}); });
if (!m_buffer->m_success)
LOGM(ERR, "Possibly compositor bug: buffer failed to create");
} }
CLinuxDMABuffer::~CLinuxDMABuffer() { CLinuxDMABuffer::~CLinuxDMABuffer() {
@ -217,7 +214,7 @@ void CLinuxDMABUFParamsResource::create(uint32_t id) {
auto& buf = PROTO::linuxDma->m_buffers.emplace_back(makeUnique<CLinuxDMABuffer>(id, m_resource->client(), *m_attrs)); auto& buf = PROTO::linuxDma->m_buffers.emplace_back(makeUnique<CLinuxDMABuffer>(id, m_resource->client(), *m_attrs));
if UNLIKELY (!buf->good() || !buf->m_buffer->m_success) { if UNLIKELY (!buf->good()) {
m_resource->sendFailed(); m_resource->sendFailed();
PROTO::linuxDma->m_buffers.pop_back(); PROTO::linuxDma->m_buffers.pop_back();
return; return;

View file

@ -18,9 +18,6 @@ CMesaDRMBufferResource::CMesaDRMBufferResource(uint32_t id, wl_client* client, A
m_listeners.bufferResourceDestroy.reset(); m_listeners.bufferResourceDestroy.reset();
PROTO::mesaDRM->destroyResource(this); PROTO::mesaDRM->destroyResource(this);
}); });
if (!m_buffer->m_success)
LOGM(ERR, "Possibly compositor bug: buffer failed to create");
} }
CMesaDRMBufferResource::~CMesaDRMBufferResource() { CMesaDRMBufferResource::~CMesaDRMBufferResource() {

View file

@ -12,16 +12,9 @@ CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColo
m_opaque = col_.a >= 1.F; m_opaque = col_.a >= 1.F;
m_texture = makeShared<CTexture>(DRM_FORMAT_ARGB8888, rc<uint8_t*>(&m_color), 4, Vector2D{1, 1});
m_resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id)); m_resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id));
m_success = m_texture->m_texID;
size = {1, 1}; size = {1, 1};
if (!m_success)
Debug::log(ERR, "Failed creating a single pixel texture: null texture id");
} }
CSinglePixelBuffer::~CSinglePixelBuffer() { CSinglePixelBuffer::~CSinglePixelBuffer() {
@ -57,6 +50,17 @@ void CSinglePixelBuffer::endDataPtr() {
; ;
} }
SP<CTexture> CSinglePixelBuffer::createTexture() {
auto tex = makeShared<CTexture>(DRM_FORMAT_ARGB8888, rc<uint8_t*>(&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() { bool CSinglePixelBuffer::good() {
return m_resource->good(); return m_resource->good();
} }

View file

@ -18,6 +18,7 @@ class CSinglePixelBuffer : public IHLBuffer {
virtual Aquamarine::SDMABUFAttrs dmabuf(); virtual Aquamarine::SDMABUFAttrs dmabuf();
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags); virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr(); virtual void endDataPtr();
virtual SP<CTexture> createTexture();
// //
bool good(); bool good();
bool m_success = false; bool m_success = false;

View file

@ -91,12 +91,10 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
if (buf && buf->m_buffer) { if (buf && buf->m_buffer) {
m_pending.buffer = CHLBufferReference(buf->m_buffer.lock()); 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.size = buf->m_buffer->size;
m_pending.bufferSize = buf->m_buffer->size; m_pending.bufferSize = buf->m_buffer->size;
} else { } else {
m_pending.buffer = {}; m_pending.buffer = {};
m_pending.texture.reset();
m_pending.size = Vector2D{}; m_pending.size = Vector2D{};
m_pending.bufferSize = Vector2D{}; m_pending.bufferSize = Vector2D{};
} }
@ -132,7 +130,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : m_resource(re
} }
// null buffer attached // 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); commitState(m_pending);
// remove any pending states. // remove any pending states.
@ -528,6 +526,8 @@ void CWLSurfaceResource::commitState(SSurfaceState& state) {
if (m_current.buffer) { if (m_current.buffer) {
if (m_current.buffer->isSynchronous()) if (m_current.buffer->isSynchronous())
m_current.updateSynchronousTexture(lastTexture); 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 // if the surface is a cursor, update the shm buffer
// TODO: don't update the entire texture // TODO: don't update the entire texture

View file

@ -69,6 +69,10 @@ void CWLSHMBuffer::endDataPtr() {
; ;
} }
SP<CTexture> CWLSHMBuffer::createTexture() {
return nullptr;
}
bool CWLSHMBuffer::good() { bool CWLSHMBuffer::good() {
return true; return true;
} }

View file

@ -43,6 +43,7 @@ class CWLSHMBuffer : public IHLBuffer {
virtual Aquamarine::SSHMAttrs shm(); virtual Aquamarine::SSHMAttrs shm();
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags); virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr(); virtual void endDataPtr();
virtual SP<CTexture> createTexture();
bool good(); bool good();

View file

@ -22,11 +22,11 @@ class IHLBuffer : public Aquamarine::IBuffer {
virtual void lock(); virtual void lock();
virtual void unlock(); virtual void unlock();
virtual bool locked(); virtual bool locked();
virtual SP<CTexture> createTexture() = 0;
void onBackendRelease(const std::function<void()>& fn); void onBackendRelease(const std::function<void()>& fn);
void addReleasePoint(CDRMSyncPointState& point); void addReleasePoint(CDRMSyncPointState& point);
SP<CTexture> m_texture;
bool m_opaque = false; bool m_opaque = false;
SP<CWLBufferResource> m_resource; SP<CWLBufferResource> m_resource;
std::vector<UP<CSyncReleaser>> m_syncReleasers; std::vector<UP<CSyncReleaser>> m_syncReleasers;
@ -38,7 +38,6 @@ class IHLBuffer : public Aquamarine::IBuffer {
private: private:
int m_locks = 0; int m_locks = 0;
std::function<void()> m_backendReleaseQueuedFn; std::function<void()> m_backendReleaseQueuedFn;
friend class CHLBufferReference; friend class CHLBufferReference;

View file

@ -13,34 +13,14 @@
using namespace Hyprutils::OS; using namespace Hyprutils::OS;
CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_) : m_attrs(attrs_) { 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] { m_listeners.resourceDestroy = events.destroy.listen([this] {
closeFDs(); closeFDs();
m_listeners.resourceDestroy.reset(); m_listeners.resourceDestroy.reset();
}); });
size = m_attrs.size; size = m_attrs.size;
m_opaque = NFormatUtils::isFormatOpaque(m_attrs.format);
m_resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id)); m_resource = CWLBufferResource::create(makeShared<CWlBuffer>(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<CTexture>(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() { CDMABuffer::~CDMABuffer() {
@ -79,8 +59,32 @@ void CDMABuffer::endDataPtr() {
// FIXME: // FIXME:
} }
SP<CTexture> 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<CTexture>(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() { bool CDMABuffer::good() {
return m_success; return m_attrs.success;
} }
void CDMABuffer::closeFDs() { void CDMABuffer::closeFDs() {

View file

@ -15,12 +15,11 @@ class CDMABuffer : public IHLBuffer {
virtual Aquamarine::SDMABUFAttrs dmabuf(); virtual Aquamarine::SDMABUFAttrs dmabuf();
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags); virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr(); virtual void endDataPtr();
virtual SP<CTexture> createTexture();
bool good(); bool good();
void closeFDs(); void closeFDs();
Hyprutils::OS::CFileDescriptor exportSyncFile(); Hyprutils::OS::CFileDescriptor exportSyncFile();
bool m_success = false;
private: private:
Aquamarine::SDMABUFAttrs m_attrs; Aquamarine::SDMABUFAttrs m_attrs;

View file

@ -68,8 +68,10 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) {
updated = ref.updated; updated = ref.updated;
if (ref.updated.bits.buffer) { if (ref.updated.bits.buffer) {
if (!ref.buffer.m_buffer)
texture.reset(); // null buffer reset texture.
buffer = ref.buffer; buffer = ref.buffer;
texture = ref.texture;
size = ref.size; size = ref.size;
bufferSize = ref.bufferSize; bufferSize = ref.bufferSize;
} }