Skip to content

Commit 76508fe

Browse files
authored
drm: Use RAII to manage EGL context (#150)
1 parent e62592f commit 76508fe

File tree

2 files changed

+38
-33
lines changed

2 files changed

+38
-33
lines changed

src/backend/drm/Renderer.cpp

+13-24
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ void CDRMRenderer::initContext(bool GLES2) {
447447
backend->log(AQ_LOG_DEBUG, "CDRMRenderer: Got a high priority context");
448448
}
449449

450-
setEGL();
450+
CEglContextGuard eglContext(*this);
451451

452452
EGLEXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
453453

@@ -466,12 +466,10 @@ void CDRMRenderer::initContext(bool GLES2) {
466466

467467
exts.EXT_read_format_bgra = EGLEXTENSIONS.contains("GL_EXT_read_format_bgra");
468468
exts.EXT_texture_format_BGRA8888 = EGLEXTENSIONS.contains("GL_EXT_texture_format_BGRA8888");
469-
470-
restoreEGL();
471469
}
472470

473471
void CDRMRenderer::initResources() {
474-
setEGL();
472+
CEglContextGuard eglContext(*this);
475473

476474
if (!exts.EXT_image_dma_buf_import || !initDRMFormats())
477475
backend->log(AQ_LOG_ERROR, "CDRMRenderer: initDRMFormats failed, dma-buf won't work");
@@ -493,8 +491,6 @@ void CDRMRenderer::initResources() {
493491
gl.shaderExt.posAttrib = glGetAttribLocation(gl.shaderExt.program, "pos");
494492
gl.shaderExt.texAttrib = glGetAttribLocation(gl.shaderExt.program, "texcoord");
495493
gl.shaderExt.tex = glGetUniformLocation(gl.shaderExt.program, "tex");
496-
497-
restoreEGL();
498494
}
499495

500496
SP<CDRMRenderer> CDRMRenderer::attempt(SP<CBackend> backend_, int drmFD, bool GLES2) {
@@ -575,25 +571,25 @@ SP<CDRMRenderer> CDRMRenderer::attempt(SP<CBackend> backend_, Hyprutils::Memory:
575571
return renderer;
576572
}
577573

578-
void CDRMRenderer::setEGL() {
574+
CEglContextGuard::CEglContextGuard(const CDRMRenderer& renderer_) : renderer(renderer_) {
579575
savedEGLState.display = eglGetCurrentDisplay();
580576
savedEGLState.context = eglGetCurrentContext();
581577
savedEGLState.draw = eglGetCurrentSurface(EGL_DRAW);
582578
savedEGLState.read = eglGetCurrentSurface(EGL_READ);
583579

584-
if (!eglMakeCurrent(egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl.context))
585-
backend->log(AQ_LOG_WARNING, "CDRMRenderer: setEGL eglMakeCurrent failed");
580+
if (!eglMakeCurrent(renderer.egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, renderer.egl.context))
581+
renderer.backend->log(AQ_LOG_WARNING, "CDRMRenderer: setEGL eglMakeCurrent failed");
586582
}
587583

588-
void CDRMRenderer::restoreEGL() {
589-
EGLDisplay dpy = savedEGLState.display ? savedEGLState.display : egl.display;
584+
CEglContextGuard::~CEglContextGuard() {
585+
EGLDisplay dpy = savedEGLState.display ? savedEGLState.display : renderer.egl.display;
590586

591587
// egl can't handle this
592588
if (dpy == EGL_NO_DISPLAY)
593589
return;
594590

595591
if (!eglMakeCurrent(dpy, savedEGLState.draw, savedEGLState.read, savedEGLState.context))
596-
backend->log(AQ_LOG_WARNING, "CDRMRenderer: restoreEGL eglMakeCurrent failed");
592+
renderer.backend->log(AQ_LOG_WARNING, "CDRMRenderer: restoreEGL eglMakeCurrent failed");
597593
}
598594

599595
EGLImageKHR CDRMRenderer::createEGLImage(const SDMABUFAttrs& attrs) {
@@ -783,10 +779,9 @@ int CDRMRenderer::recreateBlitSync() {
783779
}
784780

785781
void CDRMRenderer::clearBuffer(IBuffer* buf) {
786-
setEGL();
787-
788-
auto dmabuf = buf->dmabuf();
789-
GLuint rboID = 0, fboID = 0;
782+
CEglContextGuard eglContext(*this);
783+
auto dmabuf = buf->dmabuf();
784+
GLuint rboID = 0, fboID = 0;
790785

791786
if (!dmabuf.success) {
792787
backend->log(AQ_LOG_ERROR, "EGL (clear): cannot clear a non-dmabuf");
@@ -824,12 +819,10 @@ void CDRMRenderer::clearBuffer(IBuffer* buf) {
824819
glDeleteFramebuffers(1, &fboID);
825820
glDeleteRenderbuffers(1, &rboID);
826821
proc.eglDestroyImageKHR(egl.display, rboImage);
827-
828-
restoreEGL();
829822
}
830823

831824
CDRMRenderer::SBlitResult CDRMRenderer::blit(SP<IBuffer> from, SP<IBuffer> to, int waitFD) {
832-
setEGL();
825+
CEglContextGuard eglContext(*this);
833826

834827
if (from->dmabuf().size != to->dmabuf().size) {
835828
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
997990
GLCALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
998991
GLCALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
999992

1000-
restoreEGL();
1001-
1002993
return {.success = true, .syncFD = explicitFD == -1 ? std::nullopt : std::optional<int>{explicitFD}};
1003994
}
1004995

1005996
void CDRMRenderer::onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment) {
1006-
setEGL();
997+
CEglContextGuard eglContext(*this);
1007998

1008999
TRACE(backend->log(AQ_LOG_TRACE,
10091000
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
10181009
proc.eglDestroyImageKHR(egl.display, attachment->eglImage);
10191010
if (attachment->tex.image)
10201011
proc.eglDestroyImageKHR(egl.display, attachment->tex.image);
1021-
1022-
restoreEGL();
10231012
}
10241013

10251014
bool CDRMRenderer::verifyDestinationDMABUF(const SDMABUFAttrs& attrs) {

src/backend/drm/Renderer.hpp

+25-9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,29 @@ namespace Aquamarine {
4040
Hyprutils::Memory::CWeakPointer<CDRMRenderer> renderer;
4141
};
4242

43+
// CEglContextGuard is a RAII abstraction for the EGL context.
44+
// On initialization, it sets the EGL context to the renderer's display,
45+
// and on destruction, it restores the previous EGL context.
46+
class CEglContextGuard {
47+
public:
48+
CEglContextGuard(const CDRMRenderer& renderer_);
49+
~CEglContextGuard();
50+
51+
// No copy or move constructors
52+
CEglContextGuard(const CEglContextGuard&) = delete;
53+
CEglContextGuard& operator=(const CEglContextGuard&) = delete;
54+
CEglContextGuard(CEglContextGuard&&) = delete;
55+
CEglContextGuard& operator=(CEglContextGuard&&) = delete;
56+
57+
private:
58+
const CDRMRenderer& renderer;
59+
struct {
60+
EGLDisplay display = nullptr;
61+
EGLContext context = nullptr;
62+
EGLSurface draw = nullptr, read = nullptr;
63+
} savedEGLState;
64+
};
65+
4366
class CDRMRenderer {
4467
public:
4568
~CDRMRenderer();
@@ -59,9 +82,6 @@ namespace Aquamarine {
5982
// can't be a SP<> because we call it from buf's ctor...
6083
void clearBuffer(IBuffer* buf);
6184

62-
void setEGL();
63-
void restoreEGL();
64-
6585
void onBufferAttachmentDrop(CDRMRendererBufferAttachment* attachment);
6686

6787
struct {
@@ -107,12 +127,6 @@ namespace Aquamarine {
107127
int lastBlitSyncFD = -1;
108128
} egl;
109129

110-
struct {
111-
EGLDisplay display = nullptr;
112-
EGLContext context = nullptr;
113-
EGLSurface draw = nullptr, read = nullptr;
114-
} savedEGLState;
115-
116130
SGLTex glTex(Hyprutils::Memory::CSharedPointer<IBuffer> buf);
117131

118132
Hyprutils::Memory::CWeakPointer<CDRMRenderer> self;
@@ -135,5 +149,7 @@ namespace Aquamarine {
135149
bool hasModifiers = false;
136150

137151
Hyprutils::Memory::CWeakPointer<CBackend> backend;
152+
153+
friend class CEglContextGuard;
138154
};
139155
};

0 commit comments

Comments
 (0)