mirror of
https://github.com/hyprwm/Hyprland
synced 2025-12-20 07:30:05 +01:00
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:
parent
0dc45b54f3
commit
82759d4095
11 changed files with 53 additions and 45 deletions
|
|
@ -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<CLinuxDMABuffer>(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;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -12,16 +12,9 @@ CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColo
|
|||
|
||||
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_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<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() {
|
||||
return m_resource->good();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class CSinglePixelBuffer : public IHLBuffer {
|
|||
virtual Aquamarine::SDMABUFAttrs dmabuf();
|
||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||
virtual void endDataPtr();
|
||||
virtual SP<CTexture> createTexture();
|
||||
//
|
||||
bool good();
|
||||
bool m_success = false;
|
||||
|
|
|
|||
|
|
@ -91,12 +91,10 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> 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.size = Vector2D{};
|
||||
m_pending.bufferSize = Vector2D{};
|
||||
}
|
||||
|
|
@ -132,7 +130,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> 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
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ void CWLSHMBuffer::endDataPtr() {
|
|||
;
|
||||
}
|
||||
|
||||
SP<CTexture> CWLSHMBuffer::createTexture() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CWLSHMBuffer::good() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class CWLSHMBuffer : public IHLBuffer {
|
|||
virtual Aquamarine::SSHMAttrs shm();
|
||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||
virtual void endDataPtr();
|
||||
virtual SP<CTexture> createTexture();
|
||||
|
||||
bool good();
|
||||
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ class IHLBuffer : public Aquamarine::IBuffer {
|
|||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual bool locked();
|
||||
virtual SP<CTexture> createTexture() = 0;
|
||||
|
||||
void onBackendRelease(const std::function<void()>& fn);
|
||||
void addReleasePoint(CDRMSyncPointState& point);
|
||||
|
||||
SP<CTexture> m_texture;
|
||||
bool m_opaque = false;
|
||||
SP<CWLBufferResource> m_resource;
|
||||
std::vector<UP<CSyncReleaser>> m_syncReleasers;
|
||||
|
|
@ -38,7 +38,6 @@ class IHLBuffer : public Aquamarine::IBuffer {
|
|||
|
||||
private:
|
||||
int m_locks = 0;
|
||||
|
||||
std::function<void()> m_backendReleaseQueuedFn;
|
||||
|
||||
friend class CHLBufferReference;
|
||||
|
|
|
|||
|
|
@ -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_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");
|
||||
m_resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id));
|
||||
}
|
||||
|
||||
CDMABuffer::~CDMABuffer() {
|
||||
|
|
@ -79,8 +59,32 @@ void CDMABuffer::endDataPtr() {
|
|||
// 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() {
|
||||
return m_success;
|
||||
return m_attrs.success;
|
||||
}
|
||||
|
||||
void CDMABuffer::closeFDs() {
|
||||
|
|
|
|||
|
|
@ -15,12 +15,11 @@ class CDMABuffer : public IHLBuffer {
|
|||
virtual Aquamarine::SDMABUFAttrs dmabuf();
|
||||
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
|
||||
virtual void endDataPtr();
|
||||
virtual SP<CTexture> createTexture();
|
||||
bool good();
|
||||
void closeFDs();
|
||||
Hyprutils::OS::CFileDescriptor exportSyncFile();
|
||||
|
||||
bool m_success = false;
|
||||
|
||||
private:
|
||||
Aquamarine::SDMABUFAttrs m_attrs;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue