Skip to content

Commit

Permalink
drm: clear buffer on creation for scanout DRM buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Aug 17, 2024
1 parent cd15214 commit 2619ba5
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 20 deletions.
5 changes: 5 additions & 0 deletions include/aquamarine/allocator/Allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
};
1 change: 1 addition & 0 deletions include/aquamarine/allocator/GBM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions include/aquamarine/backend/DRM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -415,5 +414,6 @@ namespace Aquamarine {
friend class CDRMAtomicImpl;
friend class CDRMAtomicRequest;
friend class CDRMLease;
friend class CGBMBuffer;
};
};
12 changes: 12 additions & 0 deletions src/allocator/GBM.cpp
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}
33 changes: 18 additions & 15 deletions src/backend/drm/DRM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,27 +493,30 @@ bool Aquamarine::CDRMBackend::shouldBlit() {
}

bool Aquamarine::CDRMBackend::initMgpu() {
if (!primary)
return true;

auto newAllocator = CGBMAllocator::create(backend->reopenDRMNode(gpu->fd), backend);
mgpu.allocator = newAllocator;
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;
}

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;
}
Expand Down Expand Up @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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;
}
Expand Down
46 changes: 46 additions & 0 deletions src/backend/drm/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
8 changes: 5 additions & 3 deletions src/backend/drm/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 2619ba5

Please sign in to comment.