mirror of
https://github.com/hyprwm/aquamarine.git
synced 2024-11-17 02:35:59 +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;
|
bool scanout = false, cursor = false, multigpu = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum eAllocatorType {
|
||||||
|
AQ_ALLOCATOR_TYPE_GBM = 0,
|
||||||
|
};
|
||||||
|
|
||||||
class IAllocator {
|
class IAllocator {
|
||||||
public:
|
public:
|
||||||
virtual ~IAllocator() = default;
|
virtual ~IAllocator() = default;
|
||||||
virtual Hyprutils::Memory::CSharedPointer<IBuffer> acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain) = 0;
|
virtual Hyprutils::Memory::CSharedPointer<IBuffer> acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain) = 0;
|
||||||
virtual Hyprutils::Memory::CSharedPointer<CBackend> getBackend() = 0;
|
virtual Hyprutils::Memory::CSharedPointer<CBackend> getBackend() = 0;
|
||||||
virtual int drmFD() = 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<IBuffer> acquire(const SAllocatorBufferParams& params, Hyprutils::Memory::CSharedPointer<CSwapchain> swapchain_);
|
||||||
virtual Hyprutils::Memory::CSharedPointer<CBackend> getBackend();
|
virtual Hyprutils::Memory::CSharedPointer<CBackend> getBackend();
|
||||||
virtual int drmFD();
|
virtual int drmFD();
|
||||||
|
virtual eAllocatorType type();
|
||||||
|
|
||||||
//
|
//
|
||||||
Hyprutils::Memory::CWeakPointer<CGBMAllocator> self;
|
Hyprutils::Memory::CWeakPointer<CGBMAllocator> self;
|
||||||
|
|
|
@ -374,11 +374,10 @@ namespace Aquamarine {
|
||||||
Hyprutils::Memory::CSharedPointer<IDRMImplementation> impl;
|
Hyprutils::Memory::CSharedPointer<IDRMImplementation> impl;
|
||||||
Hyprutils::Memory::CWeakPointer<CDRMBackend> primary;
|
Hyprutils::Memory::CWeakPointer<CDRMBackend> primary;
|
||||||
|
|
||||||
// multigpu state, only present if this backend is not primary, aka if this->primary != nullptr
|
|
||||||
struct {
|
struct {
|
||||||
Hyprutils::Memory::CSharedPointer<IAllocator> allocator;
|
Hyprutils::Memory::CSharedPointer<IAllocator> allocator;
|
||||||
Hyprutils::Memory::CSharedPointer<CDRMRenderer> renderer;
|
Hyprutils::Memory::CSharedPointer<CDRMRenderer> renderer;
|
||||||
} mgpu;
|
} rendererState;
|
||||||
|
|
||||||
Hyprutils::Memory::CWeakPointer<CBackend> backend;
|
Hyprutils::Memory::CWeakPointer<CBackend> backend;
|
||||||
|
|
||||||
|
@ -415,5 +414,6 @@ namespace Aquamarine {
|
||||||
friend class CDRMAtomicImpl;
|
friend class CDRMAtomicImpl;
|
||||||
friend class CDRMAtomicRequest;
|
friend class CDRMAtomicRequest;
|
||||||
friend class CDRMLease;
|
friend class CDRMLease;
|
||||||
|
friend class CGBMBuffer;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
#include <aquamarine/allocator/GBM.hpp>
|
#include <aquamarine/allocator/GBM.hpp>
|
||||||
#include <aquamarine/backend/Backend.hpp>
|
#include <aquamarine/backend/Backend.hpp>
|
||||||
|
#include <aquamarine/backend/DRM.hpp>
|
||||||
#include <aquamarine/allocator/Swapchain.hpp>
|
#include <aquamarine/allocator/Swapchain.hpp>
|
||||||
#include "FormatUtils.hpp"
|
#include "FormatUtils.hpp"
|
||||||
#include "Shared.hpp"
|
#include "Shared.hpp"
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include "../backend/drm/Renderer.hpp"
|
||||||
|
|
||||||
using namespace Aquamarine;
|
using namespace Aquamarine;
|
||||||
using namespace Hyprutils::Memory;
|
using namespace Hyprutils::Memory;
|
||||||
|
@ -186,6 +188,12 @@ Aquamarine::CGBMBuffer::CGBMBuffer(const SAllocatorBufferParams& params, Hypruti
|
||||||
modName ? modName : "Unknown"));
|
modName ? modName : "Unknown"));
|
||||||
|
|
||||||
free(modName);
|
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() {
|
Aquamarine::CGBMBuffer::~CGBMBuffer() {
|
||||||
|
@ -305,3 +313,7 @@ Hyprutils::Memory::CSharedPointer<CBackend> Aquamarine::CGBMAllocator::getBacken
|
||||||
int Aquamarine::CGBMAllocator::drmFD() {
|
int Aquamarine::CGBMAllocator::drmFD() {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eAllocatorType Aquamarine::CGBMAllocator::type() {
|
||||||
|
return AQ_ALLOCATOR_TYPE_GBM;
|
||||||
|
}
|
||||||
|
|
|
@ -493,27 +493,30 @@ bool Aquamarine::CDRMBackend::shouldBlit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Aquamarine::CDRMBackend::initMgpu() {
|
bool Aquamarine::CDRMBackend::initMgpu() {
|
||||||
if (!primary)
|
SP<CGBMAllocator> newAllocator;
|
||||||
return true;
|
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);
|
if (!rendererState.allocator) {
|
||||||
mgpu.allocator = newAllocator;
|
|
||||||
|
|
||||||
if (!mgpu.allocator) {
|
|
||||||
backend->log(AQ_LOG_ERROR, "drm: initMgpu: no allocator");
|
backend->log(AQ_LOG_ERROR, "drm: initMgpu: no allocator");
|
||||||
return false;
|
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");
|
backend->log(AQ_LOG_ERROR, "drm: initMgpu: no renderer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mgpu.renderer->self = mgpu.renderer;
|
rendererState.renderer->self = rendererState.renderer;
|
||||||
|
|
||||||
buildGlFormats(mgpu.renderer->formats);
|
buildGlFormats(rendererState.renderer->formats);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1463,7 +1466,7 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) {
|
||||||
|
|
||||||
if (!mgpu.swapchain) {
|
if (!mgpu.swapchain) {
|
||||||
TRACE(backend->backend->log(AQ_LOG_TRACE, "drm: No swapchain for blit, creating"));
|
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();
|
auto OPTIONS = swapchain->currentOptions();
|
||||||
|
@ -1480,8 +1483,8 @@ bool Aquamarine::CDRMOutput::commitState(bool onlyTest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto NEWAQBUF = mgpu.swapchain->next(nullptr);
|
auto NEWAQBUF = mgpu.swapchain->next(nullptr);
|
||||||
auto blitResult = backend->mgpu.renderer->blit(STATE.buffer, NEWAQBUF,
|
auto blitResult = backend->rendererState.renderer->blit(
|
||||||
(COMMITTED & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_EXPLICIT_IN_FENCE) ? STATE.explicitInFence : -1);
|
STATE.buffer, NEWAQBUF, (COMMITTED & COutputState::eOutputStateProperties::AQ_OUTPUT_STATE_EXPLICIT_IN_FENCE) ? STATE.explicitInFence : -1);
|
||||||
if (!blitResult.success) {
|
if (!blitResult.success) {
|
||||||
backend->backend->log(AQ_LOG_ERROR, "drm: Backend requires blit, but blit failed");
|
backend->backend->log(AQ_LOG_ERROR, "drm: Backend requires blit, but blit failed");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1623,7 +1626,7 @@ bool Aquamarine::CDRMOutput::setCursor(SP<IBuffer> buffer, const Vector2D& hotsp
|
||||||
|
|
||||||
if (!mgpu.cursorSwapchain) {
|
if (!mgpu.cursorSwapchain) {
|
||||||
TRACE(backend->backend->log(AQ_LOG_TRACE, "drm: No cursorSwapchain for blit, creating"));
|
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();
|
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);
|
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");
|
backend->backend->log(AQ_LOG_ERROR, "drm: Backend requires blit, but cursor blit failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -561,6 +561,52 @@ int CDRMRenderer::recreateBlitSync() {
|
||||||
return fd;
|
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) {
|
CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, int waitFD) {
|
||||||
setEGL();
|
setEGL();
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,13 @@ namespace Aquamarine {
|
||||||
};
|
};
|
||||||
|
|
||||||
SBlitResult blit(Hyprutils::Memory::CSharedPointer<IBuffer> from, Hyprutils::Memory::CSharedPointer<IBuffer> to, int waitFD = -1);
|
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 setEGL();
|
||||||
void restoreEGL();
|
void restoreEGL();
|
||||||
|
|
||||||
void onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment);
|
void onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct SShader {
|
struct SShader {
|
||||||
|
|
Loading…
Reference in a new issue