diff --git a/krita/ui/opengl/kis_opengl.h b/krita/ui/opengl/kis_opengl.h --- a/krita/ui/opengl/kis_opengl.h +++ b/krita/ui/opengl/kis_opengl.h @@ -50,6 +50,12 @@ static bool supportsGLSL13(); /** + * @brief supportsFilter + * @return True if OpenGL provides fence sync methods. + */ + static bool supportsFenceSync(); + + /** * Returns true if we have a driver that has bugged support to sync objects (a fence) * and false otherwise. */ diff --git a/krita/ui/opengl/kis_opengl.cpp b/krita/ui/opengl/kis_opengl.cpp --- a/krita/ui/opengl/kis_opengl.cpp +++ b/krita/ui/opengl/kis_opengl.cpp @@ -104,6 +104,11 @@ #endif } +bool KisOpenGL::supportsFenceSync() +{ + // return glVersion > 302; + return true; +} bool KisOpenGL::supportsGLSL13() { diff --git a/krita/ui/opengl/kis_opengl_canvas2_p.h b/krita/ui/opengl/kis_opengl_canvas2_p.h --- a/krita/ui/opengl/kis_opengl_canvas2_p.h +++ b/krita/ui/opengl/kis_opengl_canvas2_p.h @@ -39,8 +39,8 @@ #include #include #include -#include -#include +#include +#include #ifndef GL_NUM_EXTENSIONS #define GL_NUM_EXTENSIONS 0x821D @@ -56,172 +56,44 @@ namespace VSyncWorkaround { - class QGLExtensionMatcher - { - public: - QGLExtensionMatcher(const char *str); - QGLExtensionMatcher(); - - bool match(const char *str) const { - int str_length = qstrlen(str); - - Q_ASSERT(str); - Q_ASSERT(str_length > 0); - Q_ASSERT(str[str_length-1] != ' '); - - for (int i = 0; i < m_offsets.size(); ++i) { - const char *extension = m_extensions.constData() + m_offsets.at(i); - if (qstrncmp(extension, str, str_length) == 0 && extension[str_length] == ' ') - return true; - } - return false; - } - - private: - void init(const char *str); - - QByteArray m_extensions; - QVector m_offsets; - }; - - - typedef const GLubyte * (*qt_glGetStringi)(GLenum, GLuint); - - QGLExtensionMatcher::QGLExtensionMatcher(const char *str) - { - init(str); - } - - QGLExtensionMatcher::QGLExtensionMatcher() - { - const char *extensionStr = reinterpret_cast(glGetString(GL_EXTENSIONS)); - - if (extensionStr) { - init(extensionStr); - } else { - // clear error state - while (glGetError()) {} - - const QOpenGLContext *ctx = QOpenGLContext::currentContext(); -// if (ctx) { -// qt_glGetStringi glGetStringi = (qt_glGetStringi)ctx->getProcAddress(QLatin1String("glGetStringi")); - -// GLint numExtensions; -// glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); - -// for (int i = 0; i < numExtensions; ++i) { -// const char *str = reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); - -// m_offsets << m_extensions.size(); - -// while (*str != 0) -// m_extensions.append(*str++); -// m_extensions.append(' '); -// } -// } - } - } - - void QGLExtensionMatcher::init(const char *str) - { - m_extensions = str; - - // make sure extension string ends with a space - if (!m_extensions.endsWith(' ')) - m_extensions.append(' '); - - int index = 0; - int next = 0; - while ((next = m_extensions.indexOf(' ', index)) >= 0) { - m_offsets << index; - index = next + 1; - } - } - - void* qglx_getProcAddress(const char* procName) - { - // On systems where the GL driver is pluggable (like Mesa), we have to use - // the glXGetProcAddressARB extension to resolve other function pointers as - // the symbols wont be in the GL library, but rather in a plugin loaded by - // the GL library. - typedef void* (*qt_glXGetProcAddressARB)(const char *); - static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; - static bool triedResolvingGlxGetProcAddress = false; - if (!triedResolvingGlxGetProcAddress) { - triedResolvingGlxGetProcAddress = true; - QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)); - if (extensions.match("GLX_ARB_get_proc_address")) { - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); - dlclose(handle); - } - if (!glXGetProcAddressARB) - { - QLibrary lib(gl_library_name()); - //lib.setLoadHints(QLibrary::ImprovedSearchHeuristics); - glXGetProcAddressARB = (qt_glXGetProcAddressARB)(void*)lib.resolve("glXGetProcAddressARB"); - } - } - } - - void *procAddress = 0; - if (glXGetProcAddressARB) { - procAddress = glXGetProcAddressARB(procName); - } - - // If glXGetProcAddress didn't work, try looking the symbol up in the GL library - if (!procAddress) { - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - procAddress = dlsym(handle, procName); - dlclose(handle); - } - } - if (!procAddress) { - - QLibrary lib(gl_library_name()); - //lib.setLoadHints(QLibrary::ImprovedSearchHeuristics); - procAddress = (void*)lib.resolve(procName); - } - - return procAddress; - } - - - bool tryDisableVSync(QWidget *widget) { + bool tryDisableVSync(QOpenGLContext* ctx) { bool result = false; bool triedDisable = false; Display *dpy = QX11Info::display(); - WId wid = widget->winId(); - - QGLExtensionMatcher extensions(glXQueryExtensionsString(dpy, QX11Info::appScreen())); + qDebug() << "OpenGL architecture is" << gl_library_name(); - if (extensions.match("GLX_EXT_swap_control")) { + if (ctx->hasExtension("GLX_EXT_swap_control")) { + qDebug() << "Swap control extension found."; + typedef WId (*k_glXGetCurrentDrawable)(void); typedef void (*kis_glXSwapIntervalEXT)(Display*, WId, int); - kis_glXSwapIntervalEXT glXSwapIntervalEXT = (kis_glXSwapIntervalEXT)qglx_getProcAddress("glXSwapIntervalEXT"); + typedef int (*k_glXQueryDrawable)(Display *, WId, int, unsigned int *); + k_glXGetCurrentDrawable kis_glXGetCurrentDrawable = (k_glXGetCurrentDrawable)ctx->getProcAddress("glXGetCurrentDrawable"); + kis_glXSwapIntervalEXT glXSwapIntervalEXT = (kis_glXSwapIntervalEXT)ctx->getProcAddress("glXSwapIntervalEXT"); + k_glXQueryDrawable kis_glXQueryDrawable = (k_glXQueryDrawable)ctx->getProcAddress("glXQueryDrawable"); + WId wid = kis_glXGetCurrentDrawable(); if (glXSwapIntervalEXT) { glXSwapIntervalEXT(dpy, wid, 0); triedDisable = true; unsigned int swap = 1; #ifdef GLX_SWAP_INTERVAL_EXT - glXQueryDrawable(dpy, wid, GLX_SWAP_INTERVAL_EXT, &swap); + kis_glXQueryDrawable(dpy, wid, GLX_SWAP_INTERVAL_EXT, &swap); #endif result = !swap; } else { qDebug() << "Couldn't load glXSwapIntervalEXT extension function"; } - } else if (extensions.match("GLX_MESA_swap_control")) { + } else if (ctx->hasExtension("GLX_MESA_swap_control")) { + qDebug() << "MESA swap control extension found."; typedef int (*kis_glXSwapIntervalMESA)(unsigned int); typedef int (*kis_glXGetSwapIntervalMESA)(void); - kis_glXSwapIntervalMESA glXSwapIntervalMESA = (kis_glXSwapIntervalMESA)qglx_getProcAddress("glXSwapIntervalMESA"); - kis_glXGetSwapIntervalMESA glXGetSwapIntervalMESA = (kis_glXGetSwapIntervalMESA)qglx_getProcAddress("glXGetSwapIntervalMESA"); + kis_glXSwapIntervalMESA glXSwapIntervalMESA = (kis_glXSwapIntervalMESA)ctx->getProcAddress("glXSwapIntervalMESA"); + kis_glXGetSwapIntervalMESA glXGetSwapIntervalMESA = (kis_glXGetSwapIntervalMESA)ctx->getProcAddress("glXGetSwapIntervalMESA"); if (glXSwapIntervalMESA) { int retval = glXSwapIntervalMESA(0); @@ -324,27 +196,24 @@ //Initialise the function pointers for glFenceSync and glGetSynciv //Note: Assumes a current OpenGL context. void init() { + QOpenGLContext* ctx = QOpenGLContext::currentContext(); #if defined Q_OS_WIN - if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_3_2) { + if (KisOpenGL::supportsFenceSync()) { #ifdef ENV64BIT - k_glFenceSync = (kis_glFenceSync)wglGetProcAddress("glFenceSync"); - k_glGetSynciv = (kis_glGetSynciv)wglGetProcAddress("glGetSynciv"); - k_glDeleteSync = (kis_glDeleteSync)wglGetProcAddress("glDeleteSync"); + k_glFenceSync = (kis_glFenceSync)ctx->getProcAddress("glFenceSync"); + k_glGetSynciv = (kis_glGetSynciv)ctx->getProcAddress("glGetSynciv"); + k_glDeleteSync = (kis_glDeleteSync)ctx->getProcAddress("glDeleteSync"); #else - k_glFenceSync = (kis_glFenceSync)wglGetProcAddress("glFenceSyncARB"); - k_glGetSynciv = (kis_glGetSynciv)wglGetProcAddress("glGetSyncivARB"); - k_glDeleteSync = (kis_glDeleteSync)wglGetProcAddress("glDeleteSyncARB"); + k_glFenceSync = (kis_glFenceSync)ctx->getProcAddress("glFenceSyncARB"); + k_glGetSynciv = (kis_glGetSynciv)ctx->getProcAddress("glGetSyncivARB"); + k_glDeleteSync = (kis_glDeleteSync)ctx->getProcAddress("glDeleteSyncARB"); #endif } #elif defined Q_OS_LINUX -#ifdef HAVE_GLEW - if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_3_2) || GLEW_ARB_sync) { -#else - if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_3_2)) { -#endif - k_glFenceSync = (kis_glFenceSync)VSyncWorkaround::qglx_getProcAddress("glFenceSync"); - k_glGetSynciv = (kis_glGetSynciv)VSyncWorkaround::qglx_getProcAddress("glGetSynciv"); - k_glDeleteSync = (kis_glDeleteSync)VSyncWorkaround::qglx_getProcAddress("glDeleteSync"); + if (KisOpenGL::supportsFenceSync()) { + k_glFenceSync = (kis_glFenceSync)ctx->getProcAddress("glFenceSync"); + k_glGetSynciv = (kis_glGetSynciv)ctx->getProcAddress("glGetSynciv"); + k_glDeleteSync = (kis_glDeleteSync)ctx->getProcAddress("glDeleteSync"); } #endif if (k_glFenceSync == 0 || k_glGetSynciv == 0 || k_glDeleteSync == 0) {