Fix a crash in eglDestroyImageKHR()
Apparently, libepoxy requires a current EGL display in order to resolve EGL functions. This is unexpected as most of the EGL functions require no current opengl context. This change makes kwin bypass libepoxy for problematic cases. BUG: 470980
This commit is contained in:
parent
192ec437df
commit
13c092d671
4 changed files with 42 additions and 20 deletions
|
@ -79,8 +79,13 @@ EglDisplay::EglDisplay(::EGLDisplay display, const QList<QByteArray> &extensions
|
|||
, m_owning(owning)
|
||||
, m_supportsBufferAge(extensions.contains(QByteArrayLiteral("EGL_EXT_buffer_age")) && qgetenv("KWIN_USE_BUFFER_AGE") != "0")
|
||||
, m_supportsNativeFence(extensions.contains(QByteArrayLiteral("EGL_ANDROID_native_fence_sync")))
|
||||
, m_importFormats(queryImportFormats())
|
||||
{
|
||||
m_functions.createImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
|
||||
m_functions.destroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
|
||||
m_functions.queryDmaBufFormatsEXT = reinterpret_cast<PFNEGLQUERYDMABUFFORMATSEXTPROC>(eglGetProcAddress("eglQueryDmaBufFormatsEXT"));
|
||||
m_functions.queryDmaBufModifiersEXT = reinterpret_cast<PFNEGLQUERYDMABUFMODIFIERSEXTPROC>(eglGetProcAddress("eglQueryDmaBufModifiersEXT"));
|
||||
|
||||
m_importFormats = queryImportFormats();
|
||||
}
|
||||
|
||||
EglDisplay::~EglDisplay()
|
||||
|
@ -212,7 +217,7 @@ EGLImageKHR EglDisplay::importDmaBufAsImage(const DmaBufAttributes &dmabuf) cons
|
|||
|
||||
attribs << EGL_NONE;
|
||||
|
||||
return eglCreateImageKHR(m_handle, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data());
|
||||
return createImage(EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data());
|
||||
}
|
||||
|
||||
EGLImageKHR EglDisplay::importDmaBufAsImage(const DmaBufAttributes &dmabuf, int plane, int format, const QSize &size) const
|
||||
|
@ -233,7 +238,7 @@ EGLImageKHR EglDisplay::importDmaBufAsImage(const DmaBufAttributes &dmabuf, int
|
|||
}
|
||||
attribs << EGL_NONE;
|
||||
|
||||
return eglCreateImageKHR(m_handle, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data());
|
||||
return createImage(EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data());
|
||||
}
|
||||
|
||||
QHash<uint32_t, EglDisplay::DrmFormatInfo> EglDisplay::allSupportedDrmFormats() const
|
||||
|
@ -266,37 +271,31 @@ QHash<uint32_t, EglDisplay::DrmFormatInfo> EglDisplay::queryImportFormats() cons
|
|||
return {};
|
||||
}
|
||||
|
||||
typedef EGLBoolean (*eglQueryDmaBufFormatsEXT_func)(EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
|
||||
typedef EGLBoolean (*eglQueryDmaBufModifiersEXT_func)(EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
|
||||
eglQueryDmaBufFormatsEXT_func eglQueryDmaBufFormatsEXT = nullptr;
|
||||
eglQueryDmaBufModifiersEXT_func eglQueryDmaBufModifiersEXT = nullptr;
|
||||
eglQueryDmaBufFormatsEXT = (eglQueryDmaBufFormatsEXT_func)eglGetProcAddress("eglQueryDmaBufFormatsEXT");
|
||||
eglQueryDmaBufModifiersEXT = (eglQueryDmaBufModifiersEXT_func)eglGetProcAddress("eglQueryDmaBufModifiersEXT");
|
||||
if (eglQueryDmaBufFormatsEXT == nullptr) {
|
||||
if (m_functions.queryDmaBufFormatsEXT == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
EGLint count = 0;
|
||||
EGLBoolean success = eglQueryDmaBufFormatsEXT(m_handle, 0, nullptr, &count);
|
||||
EGLBoolean success = m_functions.queryDmaBufFormatsEXT(m_handle, 0, nullptr, &count);
|
||||
if (!success || count == 0) {
|
||||
qCCritical(KWIN_OPENGL) << "eglQueryDmaBufFormatsEXT failed!" << getEglErrorString();
|
||||
return {};
|
||||
}
|
||||
QList<uint32_t> formats(count);
|
||||
if (!eglQueryDmaBufFormatsEXT(m_handle, count, (EGLint *)formats.data(), &count)) {
|
||||
if (!m_functions.queryDmaBufFormatsEXT(m_handle, count, (EGLint *)formats.data(), &count)) {
|
||||
qCCritical(KWIN_OPENGL) << "eglQueryDmaBufFormatsEXT with count" << count << "failed!" << getEglErrorString();
|
||||
return {};
|
||||
}
|
||||
QHash<uint32_t, DrmFormatInfo> ret;
|
||||
for (const auto format : std::as_const(formats)) {
|
||||
if (eglQueryDmaBufModifiersEXT != nullptr) {
|
||||
if (m_functions.queryDmaBufModifiersEXT != nullptr) {
|
||||
EGLint count = 0;
|
||||
const EGLBoolean success = eglQueryDmaBufModifiersEXT(m_handle, format, 0, nullptr, nullptr, &count);
|
||||
const EGLBoolean success = m_functions.queryDmaBufModifiersEXT(m_handle, format, 0, nullptr, nullptr, &count);
|
||||
if (success && count > 0) {
|
||||
DrmFormatInfo drmFormatInfo;
|
||||
drmFormatInfo.allModifiers.resize(count);
|
||||
QList<EGLBoolean> externalOnly(count);
|
||||
if (eglQueryDmaBufModifiersEXT(m_handle, format, count, drmFormatInfo.allModifiers.data(), externalOnly.data(), &count)) {
|
||||
if (m_functions.queryDmaBufModifiersEXT(m_handle, format, count, drmFormatInfo.allModifiers.data(), externalOnly.data(), &count)) {
|
||||
drmFormatInfo.externalOnlyModifiers = drmFormatInfo.allModifiers;
|
||||
drmFormatInfo.nonExternalOnlyModifiers = drmFormatInfo.allModifiers;
|
||||
for (int i = drmFormatInfo.allModifiers.size() - 1; i >= 0; i--) {
|
||||
|
@ -325,4 +324,15 @@ QHash<uint32_t, EglDisplay::DrmFormatInfo> EglDisplay::queryImportFormats() cons
|
|||
return ret;
|
||||
}
|
||||
|
||||
EGLImageKHR EglDisplay::createImage(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) const
|
||||
{
|
||||
Q_ASSERT(m_functions.createImageKHR);
|
||||
return m_functions.createImageKHR(m_handle, ctx, target, buffer, attrib_list);
|
||||
}
|
||||
|
||||
void EglDisplay::destroyImage(EGLImageKHR image) const
|
||||
{
|
||||
Q_ASSERT(m_functions.destroyImageKHR);
|
||||
m_functions.destroyImageKHR(m_handle, image);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,9 @@ public:
|
|||
QHash<uint32_t, DrmFormatInfo> allSupportedDrmFormats() const;
|
||||
bool isExternalOnly(uint32_t format, uint64_t modifier) const;
|
||||
|
||||
EGLImageKHR createImage(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) const;
|
||||
void destroyImage(EGLImageKHR image) const;
|
||||
|
||||
EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &dmabuf) const;
|
||||
EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &dmabuf, int plane, int format, const QSize &size) const;
|
||||
|
||||
|
@ -62,7 +65,16 @@ private:
|
|||
|
||||
const bool m_supportsBufferAge;
|
||||
const bool m_supportsNativeFence;
|
||||
const QHash<uint32_t, DrmFormatInfo> m_importFormats;
|
||||
QHash<uint32_t, DrmFormatInfo> m_importFormats;
|
||||
|
||||
struct
|
||||
{
|
||||
PFNEGLCREATEIMAGEKHRPROC createImageKHR = nullptr;
|
||||
PFNEGLDESTROYIMAGEKHRPROC destroyImageKHR = nullptr;
|
||||
|
||||
PFNEGLQUERYDMABUFFORMATSEXTPROC queryDmaBufFormatsEXT = nullptr;
|
||||
PFNEGLQUERYDMABUFMODIFIERSEXTPROC queryDmaBufModifiersEXT = nullptr;
|
||||
} m_functions;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ EGLImageTexture::EGLImageTexture(EglDisplay *display, EGLImage image, uint textu
|
|||
|
||||
EGLImageTexture::~EGLImageTexture()
|
||||
{
|
||||
eglDestroyImageKHR(m_display->handle(), m_image);
|
||||
m_display->destroyImage(m_image);
|
||||
}
|
||||
|
||||
std::shared_ptr<EGLImageTexture> EGLImageTexture::create(EglDisplay *display, EGLImageKHR image, int internalFormat, const QSize &size, bool externalOnly)
|
||||
|
|
|
@ -82,7 +82,7 @@ void AbstractEglBackend::teardown()
|
|||
void AbstractEglBackend::cleanup()
|
||||
{
|
||||
for (const EGLImageKHR &image : m_importedBuffers) {
|
||||
eglDestroyImageKHR(m_display->handle(), image);
|
||||
m_display->destroyImage(image);
|
||||
}
|
||||
|
||||
cleanupSurfaces();
|
||||
|
@ -302,7 +302,7 @@ EGLImageKHR AbstractEglBackend::importBufferAsImage(GraphicsBuffer *buffer, int
|
|||
if (image != EGL_NO_IMAGE_KHR) {
|
||||
m_importedBuffers[key] = image;
|
||||
connect(buffer, &QObject::destroyed, this, [this, key]() {
|
||||
eglDestroyImageKHR(m_display->handle(), m_importedBuffers.take(key));
|
||||
m_display->destroyImage(m_importedBuffers.take(key));
|
||||
});
|
||||
} else {
|
||||
qCWarning(KWIN_OPENGL) << "failed to import dmabuf" << buffer;
|
||||
|
@ -324,7 +324,7 @@ EGLImageKHR AbstractEglBackend::importBufferAsImage(GraphicsBuffer *buffer)
|
|||
if (image != EGL_NO_IMAGE_KHR) {
|
||||
m_importedBuffers[key] = image;
|
||||
connect(buffer, &QObject::destroyed, this, [this, key]() {
|
||||
eglDestroyImageKHR(m_display->handle(), m_importedBuffers.take(key));
|
||||
m_display->destroyImage(m_importedBuffers.take(key));
|
||||
});
|
||||
} else {
|
||||
qCWarning(KWIN_OPENGL) << "failed to import dmabuf" << buffer;
|
||||
|
|
Loading…
Reference in a new issue