diff --git a/include/aquamarine/renderer/EGLRenderer.hpp b/include/aquamarine/renderer/EGLRenderer.hpp index 5b9a755..af2233e 100644 --- a/include/aquamarine/renderer/EGLRenderer.hpp +++ b/include/aquamarine/renderer/EGLRenderer.hpp @@ -41,6 +41,23 @@ namespace Aquamarine { Hyprutils::Memory::CWeakPointer renderer; }; + class CEGLSync { + public: + ~CEGLSync(); + + EGLSyncKHR sync = nullptr; + + int fd(); + bool wait(); + + private: + CEGLSync() = default; + + int m_iFd = -1; + + friend class CEGLRenderer; + }; + class CEGLRenderer { public: ~CEGLRenderer(); @@ -123,6 +140,7 @@ namespace Aquamarine { CEGLRenderer() = default; EGLImageKHR createEGLImage(const SDMABUFAttrs& attrs); + Hyprutils::Memory::CSharedPointer createEGLSync(int fenceFD); bool verifyDestinationDMABUF(const SDMABUFAttrs& attrs); void waitOnSync(int fd); int recreateBlitSync(); diff --git a/src/renderer/EGLRenderer.cpp b/src/renderer/EGLRenderer.cpp index d4976c5..235c926 100644 --- a/src/renderer/EGLRenderer.cpp +++ b/src/renderer/EGLRenderer.cpp @@ -16,6 +16,18 @@ using namespace Hyprutils::Math; #define SP CSharedPointer #define WP CWeakPointer +// macros +#define GLCALL(__CALL__) \ + { \ + __CALL__; \ + auto err = glGetError(); \ + if (err != GL_NO_ERROR) { \ + backend->log(AQ_LOG_ERROR, \ + std::format("[GLES] Error in call at {}@{}: 0x{:x}", __LINE__, \ + ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })(), err)); \ + } \ + } + // static funcs static WP gBackend; @@ -584,6 +596,45 @@ void CEGLRenderer::restoreEGL() { backend->log(AQ_LOG_WARNING, "CEGLRenderer: restoreEGL eglMakeCurrent failed"); } +SP CEGLRenderer::createEGLSync(int fenceFD) { + std::vector attribs; + int dupFd = -1; + if (fenceFD > 0) { + dupFd = fcntl(fenceFD, F_DUPFD_CLOEXEC, 0); + if (dupFd < 0) { + backend->log(AQ_LOG_ERROR, "createEGLSync: dup failed"); + return nullptr; + } + // reserve number of elements to avoid reallocations + attribs.reserve(3); + attribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID); + attribs.push_back(dupFd); + attribs.push_back(EGL_NONE); + } + + EGLSyncKHR sync = proc.eglCreateSyncKHR(egl.display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs.data()); + if (sync == EGL_NO_SYNC_KHR) { + backend->log(AQ_LOG_ERROR, "eglCreateSyncKHR failed"); + if (dupFd >= 0) + close(dupFd); + return nullptr; + } + + // we need to flush otherwise we might not get a valid fd + glFlush(); + + int fd = proc.eglDupNativeFenceFDANDROID(egl.display, sync); + if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { + backend->log(AQ_LOG_ERROR, "eglDupNativeFenceFDANDROID failed"); + return nullptr; + } + + auto eglsync = SP(new CEGLSync); + eglsync->sync = sync; + eglsync->m_iFd = fd; + return eglsync; +} + EGLImageKHR CEGLRenderer::createEGLImage(const SDMABUFAttrs& attrs) { std::vector attribs; @@ -652,17 +703,6 @@ EGLImageKHR CEGLRenderer::createEGLImage(const SDMABUFAttrs& attrs) { return image; } -#define GLCALL(__CALL__) \ - { \ - __CALL__; \ - auto err = glGetError(); \ - if (err != GL_NO_ERROR) { \ - backend->log(AQ_LOG_ERROR, \ - std::format("[GLES] Error in call at {}@{}: 0x{:x}", __LINE__, \ - ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })(), err)); \ - } \ - } - SGLTex CEGLRenderer::glTex(Hyprutils::Memory::CSharedPointer buffa) { SGLTex tex;