diff --git a/include/aquamarine/allocator/Allocator.hpp b/include/aquamarine/allocator/Allocator.hpp index fbfc554..5ca54af 100644 --- a/include/aquamarine/allocator/Allocator.hpp +++ b/include/aquamarine/allocator/Allocator.hpp @@ -14,11 +14,16 @@ namespace Aquamarine { bool scanout = false, cursor = false, multigpu = false; }; + enum eAllocatorType { + AQ_ALLOCATOR_TYPE_GBM = 0, + }; + class IAllocator { public: virtual ~IAllocator() = default; virtual Hyprutils::Memory::CSharedPointer acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer swapchain) = 0; virtual Hyprutils::Memory::CSharedPointer getBackend() = 0; virtual int drmFD() = 0; + virtual eAllocatorType type() = 0; }; }; diff --git a/include/aquamarine/allocator/GBM.hpp b/include/aquamarine/allocator/GBM.hpp index 3f1af0b..6e95c5b 100644 --- a/include/aquamarine/allocator/GBM.hpp +++ b/include/aquamarine/allocator/GBM.hpp @@ -45,6 +45,7 @@ namespace Aquamarine { virtual Hyprutils::Memory::CSharedPointer acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer swapchain_); virtual Hyprutils::Memory::CSharedPointer getBackend(); virtual int drmFD(); + virtual eAllocatorType type(); // Hyprutils::Memory::CWeakPointer self; diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index 7a452e5..7847eac 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -374,11 +374,10 @@ namespace Aquamarine { Hyprutils::Memory::CSharedPointer impl; Hyprutils::Memory::CWeakPointer primary; - // multigpu state, only present if this backend is not primary, aka if this->primary != nullptr struct { Hyprutils::Memory::CSharedPointer allocator; Hyprutils::Memory::CSharedPointer renderer; - } mgpu; + } rendererState; Hyprutils::Memory::CWeakPointer backend; @@ -415,5 +414,6 @@ namespace Aquamarine { friend class CDRMAtomicImpl; friend class CDRMAtomicRequest; friend class CDRMLease; + friend class CGBMBuffer; }; }; diff --git a/src/allocator/GBM.cpp b/src/allocator/GBM.cpp index 8cb2c2a..d22d3a8 100644 --- a/src/allocator/GBM.cpp +++ b/src/allocator/GBM.cpp @@ -1,11 +1,13 @@ #include #include +#include #include #include "FormatUtils.hpp" #include "Shared.hpp" #include #include #include +#include "../backend/drm/Renderer.hpp" using namespace Aquamarine; using namespace Hyprutils::Memory; @@ -186,6 +188,12 @@ Aquamarine::CGBMBuffer::CGBMBuffer(const SAllocatorBufferParams& params, Hypruti modName ? modName : "Unknown")); free(modName); + + if (params.scanout && swapchain->backendImpl->type() == AQ_BACKEND_DRM) { + // clear the buffer using the DRM renderer to avoid uninitialized mem + auto impl = (CDRMBackend*)swapchain->backendImpl.get(); + impl->rendererState.renderer->clearBuffer(this); + } } Aquamarine::CGBMBuffer::~CGBMBuffer() { @@ -305,3 +313,7 @@ Hyprutils::Memory::CSharedPointer Aquamarine::CGBMAllocator::getBacken int Aquamarine::CGBMAllocator::drmFD() { return fd; } + +eAllocatorType Aquamarine::CGBMAllocator::type() { + return AQ_ALLOCATOR_TYPE_GBM; +} diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index f35afb0..aa51487 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -493,27 +493,30 @@ bool Aquamarine::CDRMBackend::shouldBlit() { } bool Aquamarine::CDRMBackend::initMgpu() { - if (!primary) - return true; + SP newAllocator; + if (primary || backend->primaryAllocator->type() != AQ_ALLOCATOR_TYPE_GBM) { + newAllocator = CGBMAllocator::create(backend->reopenDRMNode(gpu->fd), backend); + rendererState.allocator = newAllocator; + } else { + newAllocator = ((CGBMAllocator*)backend->primaryAllocator.get())->self.lock(); + rendererState.allocator = newAllocator; + } - auto newAllocator = CGBMAllocator::create(backend->reopenDRMNode(gpu->fd), backend); - mgpu.allocator = newAllocator; - - if (!mgpu.allocator) { + if (!rendererState.allocator) { backend->log(AQ_LOG_ERROR, "drm: initMgpu: no allocator"); return false; } - mgpu.renderer = CDRMRenderer::attempt(newAllocator, backend.lock()); + rendererState.renderer = CDRMRenderer::attempt(newAllocator, backend.lock()); - if (!mgpu.renderer) { + if (!rendererState.renderer) { backend->log(AQ_LOG_ERROR, "drm: initMgpu: no renderer"); return false; } - mgpu.renderer->self = mgpu.renderer; + rendererState.renderer->self = rendererState.renderer; - buildGlFormats(mgpu.renderer->formats); + buildGlFormats(rendererState.renderer->formats); return true; } @@ -1463,7 +1466,7 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) { if (!mgpu.swapchain) { TRACE(backend->backend->log(AQ_LOG_TRACE, "drm: No swapchain for blit, creating")); - mgpu.swapchain = CSwapchain::create(backend->mgpu.allocator, backend.lock()); + mgpu.swapchain = CSwapchain::create(backend->rendererState.allocator, backend.lock()); } auto OPTIONS = swapchain->currentOptions(); @@ -1480,8 +1483,8 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) { } auto NEWAQBUF = mgpu.swapchain->next(nullptr); - auto blitResult = backend->mgpu.renderer->blit(STATE.buffer, NEWAQBUF, - (COMMITTED & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_EXPLICIT_IN_FENCE) ? STATE.explicitInFence : -1); + auto blitResult = backend->rendererState.renderer->blit( + STATE.buffer, NEWAQBUF, (COMMITTED & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_EXPLICIT_IN_FENCE) ? STATE.explicitInFence : -1); if (!blitResult.success) { backend->backend->log(AQ_LOG_ERROR, "drm: Backend requires blit, but blit failed"); return false; @@ -1623,7 +1626,7 @@ bool Aquamarine::CDRMOutput::setCursor(SP buffer, const Vector2D& hotsp if (!mgpu.cursorSwapchain) { TRACE(backend->backend->log(AQ_LOG_TRACE, "drm: No cursorSwapchain for blit, creating")); - mgpu.cursorSwapchain = CSwapchain::create(backend->mgpu.allocator, backend.lock()); + mgpu.cursorSwapchain = CSwapchain::create(backend->rendererState.allocator, backend.lock()); } auto OPTIONS = mgpu.cursorSwapchain->currentOptions(); @@ -1640,7 +1643,7 @@ bool Aquamarine::CDRMOutput::setCursor(SP buffer, const Vector2D& hotsp } auto NEWAQBUF = mgpu.cursorSwapchain->next(nullptr); - if (!backend->mgpu.renderer->blit(buffer, NEWAQBUF).success) { + if (!backend->rendererState.renderer->blit(buffer, NEWAQBUF).success) { backend->backend->log(AQ_LOG_ERROR, "drm: Backend requires blit, but cursor blit failed"); return false; } diff --git a/src/backend/drm/Renderer.cpp b/src/backend/drm/Renderer.cpp index c6b2c90..901ab8c 100644 --- a/src/backend/drm/Renderer.cpp +++ b/src/backend/drm/Renderer.cpp @@ -561,6 +561,52 @@ int CDRMRenderer::recreateBlitSync() { return fd; } +void CDRMRenderer::clearBuffer(IBuffer* buf) { + setEGL(); + + auto dmabuf = buf->dmabuf(); + GLuint rboID = 0, fboID = 0; + + if (!dmabuf.success) { + backend->log(AQ_LOG_ERROR, "EGL (clear): cannot clear a non-dmabuf"); + return; + } + + auto rboImage = createEGLImage(dmabuf); + if (rboImage == EGL_NO_IMAGE_KHR) { + backend->log(AQ_LOG_ERROR, std::format("EGL (clear): createEGLImage failed: {}", eglGetError())); + return; + } + + GLCALL(glGenRenderbuffers(1, &rboID)); + GLCALL(glBindRenderbuffer(GL_RENDERBUFFER, rboID)); + GLCALL(egl.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)rboImage)); + GLCALL(glBindRenderbuffer(GL_RENDERBUFFER, 0)); + + GLCALL(glGenFramebuffers(1, &fboID)); + GLCALL(glBindFramebuffer(GL_FRAMEBUFFER, fboID)); + GLCALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboID)); + + GLCALL(glBindRenderbuffer(GL_RENDERBUFFER, rboID)); + GLCALL(glBindFramebuffer(GL_FRAMEBUFFER, fboID)); + + TRACE(backend->log(AQ_LOG_TRACE, std::format("EGL (clear): fbo {} rbo {}", fboID, rboID))); + + glClearColor(0.F, 0.F, 0.F, 1.F); + glClear(GL_COLOR_BUFFER_BIT); + + glFlush(); + + GLCALL(glBindFramebuffer(GL_FRAMEBUFFER, 0)); + GLCALL(glBindRenderbuffer(GL_RENDERBUFFER, 0)); + + glDeleteFramebuffers(1, &fboID); + glDeleteRenderbuffers(1, &rboID); + egl.eglDestroyImageKHR(egl.display, rboImage); + + restoreEGL(); +} + CDRMRenderer::SBlitResult CDRMRenderer::blit(SP from, SP to, int waitFD) { setEGL(); diff --git a/src/backend/drm/Renderer.hpp b/src/backend/drm/Renderer.hpp index b7dbe57..3819c5e 100644 --- a/src/backend/drm/Renderer.hpp +++ b/src/backend/drm/Renderer.hpp @@ -53,11 +53,13 @@ namespace Aquamarine { }; SBlitResult blit(Hyprutils::Memory::CSharedPointer from, Hyprutils::Memory::CSharedPointer to, int waitFD = -1); + // can't be a SP<> because we call it from buf's ctor... + void clearBuffer(IBuffer* buf); - void setEGL(); - void restoreEGL(); + void setEGL(); + void restoreEGL(); - void onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment); + void onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment); struct { struct SShader {