mirror of
https://github.com/hyprwm/aquamarine.git
synced 2025-12-20 04:40:12 +01:00
drm: Use RAII to manage EGL context (#150)
This commit is contained in:
parent
e62592f0f4
commit
76508fe1ec
2 changed files with 38 additions and 33 deletions
|
|
@ -447,7 +447,7 @@ void CDRMRenderer::initContext(bool GLES2) {
|
|||
backend->log(AQ_LOG_DEBUG, "CDRMRenderer: Got a high priority context");
|
||||
}
|
||||
|
||||
setEGL();
|
||||
CEglContextGuard eglContext(*this);
|
||||
|
||||
EGLEXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
|
||||
|
||||
|
|
@ -466,12 +466,10 @@ void CDRMRenderer::initContext(bool GLES2) {
|
|||
|
||||
exts.EXT_read_format_bgra = EGLEXTENSIONS.contains("GL_EXT_read_format_bgra");
|
||||
exts.EXT_texture_format_BGRA8888 = EGLEXTENSIONS.contains("GL_EXT_texture_format_BGRA8888");
|
||||
|
||||
restoreEGL();
|
||||
}
|
||||
|
||||
void CDRMRenderer::initResources() {
|
||||
setEGL();
|
||||
CEglContextGuard eglContext(*this);
|
||||
|
||||
if (!exts.EXT_image_dma_buf_import || !initDRMFormats())
|
||||
backend->log(AQ_LOG_ERROR, "CDRMRenderer: initDRMFormats failed, dma-buf won't work");
|
||||
|
|
@ -493,8 +491,6 @@ void CDRMRenderer::initResources() {
|
|||
gl.shaderExt.posAttrib = glGetAttribLocation(gl.shaderExt.program, "pos");
|
||||
gl.shaderExt.texAttrib = glGetAttribLocation(gl.shaderExt.program, "texcoord");
|
||||
gl.shaderExt.tex = glGetUniformLocation(gl.shaderExt.program, "tex");
|
||||
|
||||
restoreEGL();
|
||||
}
|
||||
|
||||
SP<CDRMRenderer> CDRMRenderer::attempt(SP<CBackend> backend_, int drmFD, bool GLES2) {
|
||||
|
|
@ -575,25 +571,25 @@ SP<CDRMRenderer> CDRMRenderer::attempt(SP<CBackend> backend_, Hyprutils::Memory:
|
|||
return renderer;
|
||||
}
|
||||
|
||||
void CDRMRenderer::setEGL() {
|
||||
CEglContextGuard::CEglContextGuard(const CDRMRenderer& renderer_) : renderer(renderer_) {
|
||||
savedEGLState.display = eglGetCurrentDisplay();
|
||||
savedEGLState.context = eglGetCurrentContext();
|
||||
savedEGLState.draw = eglGetCurrentSurface(EGL_DRAW);
|
||||
savedEGLState.read = eglGetCurrentSurface(EGL_READ);
|
||||
|
||||
if (!eglMakeCurrent(egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl.context))
|
||||
backend->log(AQ_LOG_WARNING, "CDRMRenderer: setEGL eglMakeCurrent failed");
|
||||
if (!eglMakeCurrent(renderer.egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, renderer.egl.context))
|
||||
renderer.backend->log(AQ_LOG_WARNING, "CDRMRenderer: setEGL eglMakeCurrent failed");
|
||||
}
|
||||
|
||||
void CDRMRenderer::restoreEGL() {
|
||||
EGLDisplay dpy = savedEGLState.display ? savedEGLState.display : egl.display;
|
||||
CEglContextGuard::~CEglContextGuard() {
|
||||
EGLDisplay dpy = savedEGLState.display ? savedEGLState.display : renderer.egl.display;
|
||||
|
||||
// egl can't handle this
|
||||
if (dpy == EGL_NO_DISPLAY)
|
||||
return;
|
||||
|
||||
if (!eglMakeCurrent(dpy, savedEGLState.draw, savedEGLState.read, savedEGLState.context))
|
||||
backend->log(AQ_LOG_WARNING, "CDRMRenderer: restoreEGL eglMakeCurrent failed");
|
||||
renderer.backend->log(AQ_LOG_WARNING, "CDRMRenderer: restoreEGL eglMakeCurrent failed");
|
||||
}
|
||||
|
||||
EGLImageKHR CDRMRenderer::createEGLImage(const SDMABUFAttrs& attrs) {
|
||||
|
|
@ -783,10 +779,9 @@ int CDRMRenderer::recreateBlitSync() {
|
|||
}
|
||||
|
||||
void CDRMRenderer::clearBuffer(IBuffer* buf) {
|
||||
setEGL();
|
||||
|
||||
auto dmabuf = buf->dmabuf();
|
||||
GLuint rboID = 0, fboID = 0;
|
||||
CEglContextGuard eglContext(*this);
|
||||
auto dmabuf = buf->dmabuf();
|
||||
GLuint rboID = 0, fboID = 0;
|
||||
|
||||
if (!dmabuf.success) {
|
||||
backend->log(AQ_LOG_ERROR, "EGL (clear): cannot clear a non-dmabuf");
|
||||
|
|
@ -824,12 +819,10 @@ void CDRMRenderer::clearBuffer(IBuffer* buf) {
|
|||
glDeleteFramebuffers(1, &fboID);
|
||||
glDeleteRenderbuffers(1, &rboID);
|
||||
proc.eglDestroyImageKHR(egl.display, rboImage);
|
||||
|
||||
restoreEGL();
|
||||
}
|
||||
|
||||
CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, int waitFD) {
|
||||
setEGL();
|
||||
CEglContextGuard eglContext(*this);
|
||||
|
||||
if (from->dmabuf().size != to->dmabuf().size) {
|
||||
backend->log(AQ_LOG_ERROR, "EGL (blit): buffer sizes mismatched");
|
||||
|
|
@ -997,13 +990,11 @@ CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, i
|
|||
GLCALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
GLCALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
|
||||
|
||||
restoreEGL();
|
||||
|
||||
return {.success = true, .syncFD = explicitFD == -1 ? std::nullopt : std::optional<int>{explicitFD}};
|
||||
}
|
||||
|
||||
void CDRMRenderer::onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment) {
|
||||
setEGL();
|
||||
CEglContextGuard eglContext(*this);
|
||||
|
||||
TRACE(backend->log(AQ_LOG_TRACE,
|
||||
std::format("EGL (onBufferAttachmentDrop): dropping fbo {} rbo {} image 0x{:x}", attachment->fbo, attachment->rbo, (uintptr_t)attachment->eglImage)));
|
||||
|
|
@ -1018,8 +1009,6 @@ void CDRMRenderer::onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachme
|
|||
proc.eglDestroyImageKHR(egl.display, attachment->eglImage);
|
||||
if (attachment->tex.image)
|
||||
proc.eglDestroyImageKHR(egl.display, attachment->tex.image);
|
||||
|
||||
restoreEGL();
|
||||
}
|
||||
|
||||
bool CDRMRenderer::verifyDestinationDMABUF(const SDMABUFAttrs& attrs) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,29 @@ namespace Aquamarine {
|
|||
Hyprutils::Memory::CWeakPointer<CDRMRenderer> renderer;
|
||||
};
|
||||
|
||||
// CEglContextGuard is a RAII abstraction for the EGL context.
|
||||
// On initialization, it sets the EGL context to the renderer's display,
|
||||
// and on destruction, it restores the previous EGL context.
|
||||
class CEglContextGuard {
|
||||
public:
|
||||
CEglContextGuard(const CDRMRenderer& renderer_);
|
||||
~CEglContextGuard();
|
||||
|
||||
// No copy or move constructors
|
||||
CEglContextGuard(const CEglContextGuard&) = delete;
|
||||
CEglContextGuard& operator=(const CEglContextGuard&) = delete;
|
||||
CEglContextGuard(CEglContextGuard&&) = delete;
|
||||
CEglContextGuard& operator=(CEglContextGuard&&) = delete;
|
||||
|
||||
private:
|
||||
const CDRMRenderer& renderer;
|
||||
struct {
|
||||
EGLDisplay display = nullptr;
|
||||
EGLContext context = nullptr;
|
||||
EGLSurface draw = nullptr, read = nullptr;
|
||||
} savedEGLState;
|
||||
};
|
||||
|
||||
class CDRMRenderer {
|
||||
public:
|
||||
~CDRMRenderer();
|
||||
|
|
@ -59,9 +82,6 @@ namespace Aquamarine {
|
|||
// can't be a SP<> because we call it from buf's ctor...
|
||||
void clearBuffer(IBuffer* buf);
|
||||
|
||||
void setEGL();
|
||||
void restoreEGL();
|
||||
|
||||
void onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment);
|
||||
|
||||
struct {
|
||||
|
|
@ -107,12 +127,6 @@ namespace Aquamarine {
|
|||
int lastBlitSyncFD = -1;
|
||||
} egl;
|
||||
|
||||
struct {
|
||||
EGLDisplay display = nullptr;
|
||||
EGLContext context = nullptr;
|
||||
EGLSurface draw = nullptr, read = nullptr;
|
||||
} savedEGLState;
|
||||
|
||||
SGLTex glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buf);
|
||||
|
||||
Hyprutils::Memory::CWeakPointer<CDRMRenderer> self;
|
||||
|
|
@ -135,5 +149,7 @@ namespace Aquamarine {
|
|||
bool hasModifiers = false;
|
||||
|
||||
Hyprutils::Memory::CWeakPointer<CBackend> backend;
|
||||
|
||||
friend class CEglContextGuard;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue