mirror of
https://github.com/hyprwm/aquamarine.git
synced 2024-11-16 23:15:57 +01:00
drm: clear buffer on creation for scanout DRM buffers (#51)
This commit is contained in:
parent
cd152140fd
commit
71d49670fe
7 changed files with 89 additions and 20 deletions
|
@ -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<IBuffer> acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain) = 0;
|
||||
virtual Hyprutils::Memory::CSharedPointer<CBackend> getBackend() = 0;
|
||||
virtual int drmFD() = 0;
|
||||
virtual eAllocatorType type() = 0;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace Aquamarine {
|
|||
virtual Hyprutils::Memory::CSharedPointer<IBuffer> acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain_);
|
||||
virtual Hyprutils::Memory::CSharedPointer<CBackend> getBackend();
|
||||
virtual int drmFD();
|
||||
virtual eAllocatorType type();
|
||||
|
||||
//
|
||||
Hyprutils::Memory::CWeakPointer<CGBMAllocator> self;
|
||||
|
|
|
@ -374,11 +374,10 @@ namespace Aquamarine {
|
|||
Hyprutils::Memory::CSharedPointer<IDRMImplementation> impl;
|
||||
Hyprutils::Memory::CWeakPointer<CDRMBackend> primary;
|
||||
|
||||
// multigpu state, only present if this backend is not primary, aka if this->primary != nullptr
|
||||
struct {
|
||||
Hyprutils::Memory::CSharedPointer<IAllocator> allocator;
|
||||
Hyprutils::Memory::CSharedPointer<CDRMRenderer> renderer;
|
||||
} mgpu;
|
||||
} rendererState;
|
||||
|
||||
Hyprutils::Memory::CWeakPointer<CBackend> backend;
|
||||
|
||||
|
@ -415,5 +414,6 @@ namespace Aquamarine {
|
|||
friend class CDRMAtomicImpl;
|
||||
friend class CDRMAtomicRequest;
|
||||
friend class CDRMLease;
|
||||
friend class CGBMBuffer;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#include <aquamarine/allocator/GBM.hpp>
|
||||
#include <aquamarine/backend/Backend.hpp>
|
||||
#include <aquamarine/backend/DRM.hpp>
|
||||
#include <aquamarine/allocator/Swapchain.hpp>
|
||||
#include "FormatUtils.hpp"
|
||||
#include "Shared.hpp"
|
||||
#include <xf86drm.h>
|
||||
#include <gbm.h>
|
||||
#include <unistd.h>
|
||||
#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<CBackend> Aquamarine::CGBMAllocator::getBacken
|
|||
int Aquamarine::CGBMAllocator::drmFD() {
|
||||
return fd;
|
||||
}
|
||||
|
||||
eAllocatorType Aquamarine::CGBMAllocator::type() {
|
||||
return AQ_ALLOCATOR_TYPE_GBM;
|
||||
}
|
||||
|
|
|
@ -493,27 +493,30 @@ bool Aquamarine::CDRMBackend::shouldBlit() {
|
|||
}
|
||||
|
||||
bool Aquamarine::CDRMBackend::initMgpu() {
|
||||
if (!primary)
|
||||
return true;
|
||||
SP<CGBMAllocator> 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<IBuffer> 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<IBuffer> 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;
|
||||
}
|
||||
|
|
|
@ -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<IBuffer> from, SP<IBuffer> to, int waitFD) {
|
||||
setEGL();
|
||||
|
||||
|
|
|
@ -53,11 +53,13 @@ namespace Aquamarine {
|
|||
};
|
||||
|
||||
SBlitResult blit(Hyprutils::Memory::CSharedPointer<IBuffer> from, Hyprutils::Memory::CSharedPointer<IBuffer> 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 {
|
||||
|
|
Loading…
Reference in a new issue