diff --git a/Plugins/ZShell/Wallpaper/vaapiplayer.cpp b/Plugins/ZShell/Wallpaper/vaapiplayer.cpp index bd6ea2c..f4e6b4d 100644 --- a/Plugins/ZShell/Wallpaper/vaapiplayer.cpp +++ b/Plugins/ZShell/Wallpaper/vaapiplayer.cpp @@ -1,4 +1,3 @@ -#define EGL_EGLEXT_PROTOTYPES #include "vaapiplayer.hpp" #ifdef ZHAVE_FFMPEG @@ -50,6 +49,42 @@ GLEGLImageTargetProc glEGLImageTarget() { return fn; } +// eglCreateImageKHR/eglDestroyImageKHR are EGL extension entry points. Fetch +// them through eglGetProcAddress rather than linking them directly, so the +// shared library does not carry a hard undefined reference to symbols libEGL +// may not export on every platform. +using PfnCreateImageKHR = EGLImageKHR (*)( + EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*); +using PfnDestroyImageKHR = EGLBoolean (*)(EGLDisplay, EGLImageKHR); + +PfnCreateImageKHR eglCreateImageProc() { + static PfnCreateImageKHR fn = reinterpret_cast( + eglGetProcAddress("eglCreateImageKHR")); + return fn; +} + +PfnDestroyImageKHR eglDestroyImageProc() { + static PfnDestroyImageKHR fn = reinterpret_cast( + eglGetProcAddress("eglDestroyImageKHR")); + return fn; +} + +void destroyEglImage(EGLDisplay dpy, EGLImageKHR image) { + if (image == EGL_NO_IMAGE_KHR) return; + PfnDestroyImageKHR fn = eglDestroyImageProc(); + if (!fn) { + static bool warned = false; + if (!warned) { + warned = true; + qCWarning( + vaapiLog, + "VideoPlayer: eglDestroyImageKHR unavailable, EGL images leak"); + } + return; + } + fn(dpy, image); +} + EGLImageKHR createDmaImage( EGLDisplay dpy, int fd, @@ -57,6 +92,9 @@ EGLImageKHR createDmaImage( uint32_t pitch, uint32_t fourcc, uint64_t modifier) { + PfnCreateImageKHR fn = eglCreateImageProc(); + if (!fn) return EGL_NO_IMAGE_KHR; + EGLint attrs[16]; int n = 0; attrs[n++] = EGL_LINUX_DRM_FOURCC_EXT; @@ -75,8 +113,8 @@ EGLImageKHR createDmaImage( } attrs[n] = EGL_NONE; - EGLImageKHR image = eglCreateImageKHR( - dpy, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attrs); + EGLImageKHR image = + fn(dpy, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attrs); if (image == EGL_NO_IMAGE_KHR) return EGL_NO_IMAGE_KHR; return image; } @@ -105,11 +143,11 @@ VaapiPlayer::~VaapiPlayer() { #ifdef ZHAVE_VAAPI if (m_imageY != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(m_eglDisplay, m_imageY); + destroyEglImage(m_eglDisplay, m_imageY); m_imageY = EGL_NO_IMAGE_KHR; } if (m_imageUV != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(m_eglDisplay, m_imageUV); + destroyEglImage(m_eglDisplay, m_imageUV); m_imageUV = EGL_NO_IMAGE_KHR; } #endif @@ -339,11 +377,11 @@ void VaapiPlayer::stop() { void VaapiPlayer::deleteTexture() { #ifdef ZHAVE_VAAPI if (m_imageY != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(m_eglDisplay, m_imageY); + destroyEglImage(m_eglDisplay, m_imageY); m_imageY = EGL_NO_IMAGE_KHR; } if (m_imageUV != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(m_eglDisplay, m_imageUV); + destroyEglImage(m_eglDisplay, m_imageUV); m_imageUV = EGL_NO_IMAGE_KHR; } #endif @@ -569,11 +607,11 @@ bool VaapiPlayer::importEglImages(AVFrame* frame) { const QSize sz = QSize(int(frame->width), int(frame->height)); if (m_texSize != sz || m_texY == 0) { if (m_imageY != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(m_eglDisplay, m_imageY); + destroyEglImage(m_eglDisplay, m_imageY); m_imageY = EGL_NO_IMAGE_KHR; } if (m_imageUV != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(m_eglDisplay, m_imageUV); + destroyEglImage(m_eglDisplay, m_imageUV); m_imageUV = EGL_NO_IMAGE_KHR; } if (m_texY == 0) glGenTextures(1, &m_texY); @@ -595,10 +633,8 @@ bool VaapiPlayer::importEglImages(AVFrame* frame) { EGLImageKHR imageUV = bindLayer(1, m_texUV); if (imageY == EGL_NO_IMAGE_KHR || imageUV == EGL_NO_IMAGE_KHR) { - if (imageY != EGL_NO_IMAGE_KHR) - eglDestroyImageKHR(m_eglDisplay, imageY); - if (imageUV != EGL_NO_IMAGE_KHR) - eglDestroyImageKHR(m_eglDisplay, imageUV); + destroyEglImage(m_eglDisplay, imageY); + destroyEglImage(m_eglDisplay, imageUV); for (uint32_t i = 0; i < desc.num_objects; ++i) if (desc.objects[i].fd >= 0) close(desc.objects[i].fd); static int logged = 0; @@ -608,10 +644,8 @@ bool VaapiPlayer::importEglImages(AVFrame* frame) { return false; } - if (m_imageY != EGL_NO_IMAGE_KHR) - eglDestroyImageKHR(m_eglDisplay, m_imageY); - if (m_imageUV != EGL_NO_IMAGE_KHR) - eglDestroyImageKHR(m_eglDisplay, m_imageUV); + if (m_imageY != EGL_NO_IMAGE_KHR) destroyEglImage(m_eglDisplay, m_imageY); + if (m_imageUV != EGL_NO_IMAGE_KHR) destroyEglImage(m_eglDisplay, m_imageUV); m_imageY = imageY; m_imageUV = imageUV;