From 43db107bcc29a54044b020544e3874048687d8e7 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 30 Apr 2014 18:16:26 +0200 Subject: Check properly for EGL extensions before using them Always check both EGL_EXTENSIONS and the validity of the returned function pointers. Otherwise bad things happen on EGL implementations that do not have the extension. Fix also linking to EGL. CONFIG+=egl has to be in core_module.pro too. Change-Id: I5e3dc54675d83123fc79e2d27a7af19fcc7f936a Reviewed-by: Jocelyn Turcotte --- src/core/core_module.pro | 2 ++ src/core/delegated_frame_node.cpp | 27 ++++++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/core/core_module.pro b/src/core/core_module.pro index ef9721a11..7aad0de92 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -19,3 +19,5 @@ load(qt_module) # Using -Wl,-Bsymbolic-functions seems to confuse the dynamic linker # and doesn't let Chromium get access to libc symbols through dlsym. CONFIG -= bsymbolic_functions + +contains(QT_CONFIG, egl): CONFIG += egl diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index 6573c99a5..173e2d4c8 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -213,6 +213,15 @@ static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState return layerChain; } +#if !defined(QT_NO_EGL) +static bool hasEGLExtension(EGLDisplay display, const char *name) +{ + QList extensions = QByteArray(reinterpret_cast( + eglQueryString(display, EGL_EXTENSIONS))).split(' '); + return extensions.contains(name); +} +#endif + static void waitAndDeleteChromiumSync(FenceSync *sync) { // Chromium uses its own GL bindings and stores in in thread local storage. @@ -229,16 +238,20 @@ static void waitAndDeleteChromiumSync(FenceSync *sync) static PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = 0; if (!resolved) { - QOpenGLContext *context = QOpenGLContext::currentContext(); - eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)context->getProcAddress("eglClientWaitSyncKHR"); - eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)context->getProcAddress("eglDestroySyncKHR"); + if (hasEGLExtension(sync->egl.display, "EGL_KHR_reusable_sync")) { + QOpenGLContext *context = QOpenGLContext::currentContext(); + eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)context->getProcAddress("eglClientWaitSyncKHR"); + eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)context->getProcAddress("eglDestroySyncKHR"); + } resolved = true; } - // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync. - eglClientWaitSyncKHR(sync->egl.display, sync->egl.sync, 0, EGL_FOREVER_KHR); - eglDestroySyncKHR(sync->egl.display, sync->egl.sync); - sync->reset(); + if (eglClientWaitSyncKHR && eglDestroySyncKHR) { + // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync. + eglClientWaitSyncKHR(sync->egl.display, sync->egl.sync, 0, EGL_FOREVER_KHR); + eglDestroySyncKHR(sync->egl.display, sync->egl.sync); + sync->reset(); + } } #endif break; -- cgit v1.2.3