Skip to content

Commit

Permalink
drm: Use RAII to manage EGL context (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
PlasmaPower authored Feb 28, 2025
1 parent e62592f commit 76508fe
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 33 deletions.
37 changes: 13 additions & 24 deletions src/backend/drm/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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");
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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)));
Expand All @@ -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) {
Expand Down
34 changes: 25 additions & 9 deletions src/backend/drm/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -135,5 +149,7 @@ namespace Aquamarine {
bool hasModifiers = false;

Hyprutils::Memory::CWeakPointer<CBackend> backend;

friend class CEglContextGuard;
};
};

0 comments on commit 76508fe

Please sign in to comment.