diff --git a/libs/ui/opengl/kis_opengl.cpp b/libs/ui/opengl/kis_opengl.cpp index 7e3218371e..6bd9b9bb30 100644 --- a/libs/ui/opengl/kis_opengl.cpp +++ b/libs/ui/opengl/kis_opengl.cpp @@ -1,602 +1,564 @@ /* * Copyright (c) 2007 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "opengl/kis_opengl.h" +#include "opengl/kis_opengl_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef GL_RENDERER # define GL_RENDERER 0x1F01 #endif +using namespace KisOpenGLPrivate; + namespace { bool defaultFormatIsSet = false; bool isDebugEnabled = false; bool isDebugSynchronous = false; - struct OpenGLCheckResult { - // bool contextValid = false; - int glMajorVersion = 0; - int glMinorVersion = 0; - bool supportsDeprecatedFunctions = false; - bool isOpenGLES = false; - QString rendererString; - QString driverVersionString; - - OpenGLCheckResult(QOpenGLContext &context) { - if (!context.isValid()) { - return; - } - - QOpenGLFunctions *funcs = context.functions(); // funcs is ready to be used - - rendererString = QString(reinterpret_cast(funcs->glGetString(GL_RENDERER))); - driverVersionString = QString(reinterpret_cast(funcs->glGetString(GL_VERSION))); - glMajorVersion = context.format().majorVersion(); - glMinorVersion = context.format().minorVersion(); - supportsDeprecatedFunctions = (context.format().options() & QSurfaceFormat::DeprecatedFunctions); - isOpenGLES = context.isOpenGLES(); - } - - bool isSupportedVersion() const { - return -#ifdef Q_OS_OSX - ((glMajorVersion * 100 + glMinorVersion) >= 302 - && !rendererString.toLower().contains("amd") - && !rendererString.toLower().contains("radeon")) -#else - (glMajorVersion >= 3 && (supportsDeprecatedFunctions || isOpenGLES)) || - ((glMajorVersion * 100 + glMinorVersion) == 201) -#endif - ; - } - - bool supportsLoD() const { - return (glMajorVersion * 100 + glMinorVersion) >= 300; - } - - bool hasOpenGL3() const { - return (glMajorVersion * 100 + glMinorVersion) >= 302; - } - - bool supportsFenceSync() const { - return glMajorVersion >= 3; - } -#ifdef Q_OS_WIN - // This is only for detecting whether ANGLE is being used. - // For detecting generic OpenGL ES please check isOpenGLES - bool isUsingAngle() const { - return rendererString.startsWith("ANGLE", Qt::CaseInsensitive); - } -#endif - }; boost::optional openGLCheckResult; bool NeedsFenceWorkaround = false; bool NeedsPixmapCacheWorkaround = false; QString debugText("OpenGL Info\n **OpenGL not initialized**"); void openglOnMessageLogged(const QOpenGLDebugMessage& debugMessage) { qDebug() << "OpenGL:" << debugMessage; } } #ifdef Q_OS_WIN namespace { struct WindowsOpenGLStatus { bool supportsDesktopGL = false; bool supportsAngleD3D11 = false; bool isQtPreferAngle = false; bool overridePreferAngle = false; // override Qt to force ANGLE to be preferred }; WindowsOpenGLStatus windowsOpenGLStatus = {}; KisOpenGL::OpenGLRenderer userRendererConfig; KisOpenGL::OpenGLRenderer nextUserRendererConfig; KisOpenGL::OpenGLRenderer currentRenderer; QStringList qpaDetectionLog; boost::optional checkQpaOpenGLStatus() { QWindow surface; surface.setSurfaceType(QSurface::OpenGLSurface); surface.create(); QOpenGLContext context; if (!context.create()) { qDebug() << "OpenGL context cannot be created"; return boost::none; } if (!context.isValid()) { qDebug() << "OpenGL context is not valid while checking Qt's OpenGL status"; return boost::none; } if (!context.makeCurrent(&surface)) { qDebug() << "OpenGL context cannot be made current"; return boost::none; } return OpenGLCheckResult(context); } bool checkIsSupportedDesktopGL(const OpenGLCheckResult &checkResult) { if (checkResult.isUsingAngle()) { qWarning() << "ANGLE was being used when desktop OpenGL was wanted, assuming no desktop OpenGL support"; return false; } - if (checkResult.isOpenGLES) { + if (checkResult.isOpenGLES()) { qWarning() << "Got OpenGL ES instead of desktop OpenGL, this shouldn't happen!"; return false; } return checkResult.isSupportedVersion(); } bool checkIsSupportedAngleD3D11(const OpenGLCheckResult &checkResult) { if (!checkResult.isUsingAngle()) { qWarning() << "Desktop OpenGL was being used when ANGLE was wanted, assuming no ANGLE support"; return false; } - if (!checkResult.isOpenGLES) { + if (!checkResult.isOpenGLES()) { qWarning() << "Got desktop OpenGL instead of OpenGL ES, this shouldn't happen!"; return false; } // HACK: Block ANGLE with Direct3D9 // Direct3D9 does not give OpenGL ES 3.0 // Some versions of ANGLE returns OpenGL version 3.0 incorrectly - if (checkResult.rendererString.contains("Direct3D9", Qt::CaseInsensitive)) { + if (checkResult.rendererString().contains("Direct3D9", Qt::CaseInsensitive)) { qWarning() << "ANGLE tried to use Direct3D9, Krita won't work with it"; return false; } return checkResult.isSupportedVersion(); } void specialOpenGLVendorFilter(WindowsOpenGLStatus &status, const OpenGLCheckResult &checkResult) { if (!status.supportsAngleD3D11) { return; } // HACK: Make ANGLE the preferred renderer for Intel driver versions // between build 4636 and 4729 (exclusive) due to an UI offset bug. // See https://communities.intel.com/thread/116003 // (Build 4636 is known to work from some test results) - if (checkResult.rendererString.startsWith("Intel")) { + if (checkResult.rendererString().startsWith("Intel")) { QRegularExpression regex("\\b\\d{2}\\.\\d{2}\\.\\d{2}\\.(\\d{4})\\b"); - QRegularExpressionMatch match = regex.match(checkResult.driverVersionString); + QRegularExpressionMatch match = regex.match(checkResult.driverVersionString()); if (match.hasMatch()) { int driverBuild = match.captured(1).toInt(); if (driverBuild > 4636 && driverBuild < 4729) { qDebug() << "Detected Intel driver build between 4636 and 4729, making ANGLE the preferred renderer"; status.overridePreferAngle = true; } } } } } // namespace /** * This function probes the Qt Platform Abstraction (QPA) for OpenGL diagnostics * information. The code works under the assumption that the bundled Qt is built * with `-opengl dynamic` and includes support for ANGLE. * * This function is written for Qt 5.9.1. On other versions it might not work * as well. */ void KisOpenGL::probeWindowsQpaOpenGL(int argc, char **argv, QString userRendererConfigString) { KIS_SAFE_ASSERT_RECOVER(defaultFormatIsSet) { qWarning() << "Default OpenGL format was not set before calling KisOpenGL::probeWindowsQpaOpenGL. This might be a BUG!"; setDefaultFormat(); } // Clear env var to prevent affecting tests qunsetenv("QT_OPENGL"); boost::optional qpaDetectionResult; qDebug() << "Probing Qt OpenGL detection:"; { KisLoggingManager::ScopedLogCapturer logCapturer( "qt.qpa.gl", [](QtMsgType type, const QMessageLogContext &context, const QString &msg) { Q_UNUSED(type) Q_UNUSED(context) qpaDetectionLog.append(msg); } ); { QGuiApplication app(argc, argv); qpaDetectionResult = checkQpaOpenGLStatus(); } } if (!qpaDetectionResult) { qWarning() << "Could not initialize OpenGL context!"; return; } qDebug() << "Done probing Qt OpenGL detection"; windowsOpenGLStatus.isQtPreferAngle = qpaDetectionResult->isUsingAngle(); boost::optional checkResultAngle, checkResultDesktopGL; if (qpaDetectionResult->isUsingAngle()) { checkResultAngle = qpaDetectionResult; // We already checked ANGLE, now check desktop OpenGL qputenv("QT_OPENGL", "desktop"); qDebug() << "Checking desktop OpenGL..."; { QGuiApplication app(argc, argv); checkResultDesktopGL = checkQpaOpenGLStatus(); } if (!checkResultDesktopGL) { qWarning() << "Could not initialize OpenGL context!"; } qDebug() << "Done checking desktop OpenGL"; qunsetenv("QT_OPENGL"); } else { checkResultDesktopGL = qpaDetectionResult; // We already checked desktop OpenGL, now check ANGLE qputenv("QT_OPENGL", "angle"); qDebug() << "Checking ANGLE..."; { QGuiApplication app(argc, argv); checkResultAngle = checkQpaOpenGLStatus(); } if (!checkResultAngle) { qWarning() << "Could not initialize OpenGL context!"; } qDebug() << "Done checking ANGLE"; qunsetenv("QT_OPENGL"); } windowsOpenGLStatus.supportsDesktopGL = checkResultDesktopGL && checkIsSupportedDesktopGL(*checkResultDesktopGL); windowsOpenGLStatus.supportsAngleD3D11 = checkResultAngle && checkIsSupportedAngleD3D11(*checkResultAngle); // HACK: Filter specific buggy drivers not handled by Qt OpenGL buglist if (checkResultDesktopGL) { specialOpenGLVendorFilter(windowsOpenGLStatus, *checkResultDesktopGL); } userRendererConfig = convertConfigToOpenGLRenderer(userRendererConfigString); if ((userRendererConfig == RendererDesktopGL && !windowsOpenGLStatus.supportsDesktopGL) || (userRendererConfig == RendererAngle && !windowsOpenGLStatus.supportsAngleD3D11)) { // Set it to auto so we won't get stuck userRendererConfig = RendererAuto; } nextUserRendererConfig = userRendererConfig; switch (userRendererConfig) { case RendererDesktopGL: QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true); currentRenderer = RendererDesktopGL; break; case RendererAngle: QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true); currentRenderer = RendererAngle; break; default: if (windowsOpenGLStatus.isQtPreferAngle && windowsOpenGLStatus.supportsAngleD3D11) { currentRenderer = RendererAngle; } else if (windowsOpenGLStatus.overridePreferAngle && windowsOpenGLStatus.supportsAngleD3D11) { QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true); currentRenderer = RendererAngle; } else if (!windowsOpenGLStatus.isQtPreferAngle && windowsOpenGLStatus.supportsDesktopGL) { currentRenderer = RendererDesktopGL; } else { currentRenderer = RendererNone; } break; } } KisOpenGL::OpenGLRenderer KisOpenGL::getCurrentOpenGLRenderer() { return currentRenderer; } KisOpenGL::OpenGLRenderer KisOpenGL::getQtPreferredOpenGLRenderer() { return (windowsOpenGLStatus.isQtPreferAngle || windowsOpenGLStatus.overridePreferAngle) ? RendererAngle : RendererDesktopGL; } KisOpenGL::OpenGLRenderers KisOpenGL::getSupportedOpenGLRenderers() { return RendererAuto | (windowsOpenGLStatus.supportsDesktopGL ? RendererDesktopGL : static_cast(0)) | (windowsOpenGLStatus.supportsAngleD3D11 ? RendererAngle : static_cast(0)); } KisOpenGL::OpenGLRenderer KisOpenGL::getUserOpenGLRendererConfig() { return userRendererConfig; } KisOpenGL::OpenGLRenderer KisOpenGL::getNextUserOpenGLRendererConfig() { return nextUserRendererConfig; } void KisOpenGL::setNextUserOpenGLRendererConfig(KisOpenGL::OpenGLRenderer renderer) { nextUserRendererConfig = renderer; } QString KisOpenGL::convertOpenGLRendererToConfig(KisOpenGL::OpenGLRenderer renderer) { switch (renderer) { case RendererDesktopGL: return QStringLiteral("desktop"); case RendererAngle: return QStringLiteral("angle"); default: return QStringLiteral("auto"); } } KisOpenGL::OpenGLRenderer KisOpenGL::convertConfigToOpenGLRenderer(QString renderer) { if (renderer == "desktop") { return RendererDesktopGL; } else if (renderer == "angle") { return RendererAngle; } else { return RendererAuto; } } #endif +KisOpenGLPrivate::OpenGLCheckResult::OpenGLCheckResult(QOpenGLContext &context) { + if (!context.isValid()) { + return; + } + + QOpenGLFunctions *funcs = context.functions(); // funcs is ready to be used + + m_rendererString = QString(reinterpret_cast(funcs->glGetString(GL_RENDERER))); + m_driverVersionString = QString(reinterpret_cast(funcs->glGetString(GL_VERSION))); + m_glMajorVersion = context.format().majorVersion(); + m_glMinorVersion = context.format().minorVersion(); + m_supportsDeprecatedFunctions = (context.format().options() & QSurfaceFormat::DeprecatedFunctions); + m_isOpenGLES = context.isOpenGLES(); +} + void KisOpenGL::initialize() { if (openGLCheckResult) return; KIS_SAFE_ASSERT_RECOVER(defaultFormatIsSet) { qWarning() << "Default OpenGL format was not set before calling KisOpenGL::initialize. This might be a BUG!"; setDefaultFormat(); } // we need a QSurface active to get our GL functions from the context QWindow surface; surface.setSurfaceType( QSurface::OpenGLSurface ); surface.create(); QOpenGLContext context; if (!context.create()) { qDebug() << "OpenGL context cannot be created"; return; } if (!context.isValid()) { qDebug() << "OpenGL context is not valid"; return; } if (!context.makeCurrent(&surface)) { qDebug() << "OpenGL context cannot be made current"; return; } QOpenGLFunctions *funcs = context.functions(); openGLCheckResult = OpenGLCheckResult(context); debugText.clear(); QDebug debugOut(&debugText); debugOut << "OpenGL Info"; debugOut << "\n Vendor: " << reinterpret_cast(funcs->glGetString(GL_VENDOR)); - debugOut << "\n Renderer: " << openGLCheckResult->rendererString; - debugOut << "\n Version: " << openGLCheckResult->driverVersionString; + debugOut << "\n Renderer: " << openGLCheckResult->rendererString(); + debugOut << "\n Version: " << openGLCheckResult->driverVersionString(); debugOut << "\n Shading language: " << reinterpret_cast(funcs->glGetString(GL_SHADING_LANGUAGE_VERSION)); debugOut << "\n Requested format: " << QSurfaceFormat::defaultFormat(); debugOut << "\n Current format: " << context.format(); debugOut.nospace(); - debugOut << "\n Version: " << openGLCheckResult->glMajorVersion << "." << openGLCheckResult->glMinorVersion; + debugOut << "\n Version: " << openGLCheckResult->glMajorVersion() << "." << openGLCheckResult->glMinorVersion(); debugOut.resetFormat(); - debugOut << "\n Supports deprecated functions" << openGLCheckResult->supportsDeprecatedFunctions; - debugOut << "\n is OpenGL ES:" << openGLCheckResult->isOpenGLES; + debugOut << "\n Supports deprecated functions" << openGLCheckResult->supportsDeprecatedFunctions(); + debugOut << "\n is OpenGL ES:" << openGLCheckResult->isOpenGLES(); #ifdef Q_OS_WIN debugOut << "\n\nQPA OpenGL Detection Info"; debugOut << "\n supportsDesktopGL:" << windowsOpenGLStatus.supportsDesktopGL; debugOut << "\n supportsAngleD3D11:" << windowsOpenGLStatus.supportsAngleD3D11; debugOut << "\n isQtPreferAngle:" << windowsOpenGLStatus.isQtPreferAngle; debugOut << "\n overridePreferAngle:" << windowsOpenGLStatus.overridePreferAngle; debugOut << "\n== log ==\n"; debugOut.noquote(); debugOut << qpaDetectionLog.join('\n'); debugOut.resetFormat(); debugOut << "\n== end log =="; #endif qDebug().noquote() << debugText; } void KisOpenGL::initializeContext(QOpenGLContext *ctx) { KisConfig cfg; initialize(); dbgUI << "OpenGL: Opening new context"; if (isDebugEnabled) { // Passing ctx for ownership management only, not specifying context. // QOpenGLDebugLogger only function on the current active context. // FIXME: Do we need to make sure ctx is the active context? QOpenGLDebugLogger* openglLogger = new QOpenGLDebugLogger(ctx); if (openglLogger->initialize()) { qDebug() << "QOpenGLDebugLogger is initialized. Check whether you get a message below."; QObject::connect(openglLogger, &QOpenGLDebugLogger::messageLogged, &openglOnMessageLogged); openglLogger->startLogging(isDebugSynchronous ? QOpenGLDebugLogger::SynchronousLogging : QOpenGLDebugLogger::AsynchronousLogging); openglLogger->logMessage(QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("QOpenGLDebugLogger is logging."))); } else { qDebug() << "QOpenGLDebugLogger cannot be initialized."; delete openglLogger; } } // Double check we were given the version we requested QSurfaceFormat format = ctx->format(); QOpenGLFunctions *f = ctx->functions(); f->initializeOpenGLFunctions(); QFile log(QDesktopServices::storageLocation(QDesktopServices::TempLocation) + "/krita-opengl.txt"); log.open(QFile::WriteOnly); QString vendor((const char*)f->glGetString(GL_VENDOR)); log.write(vendor.toLatin1()); log.write(", "); - log.write(openGLCheckResult->rendererString.toLatin1()); + log.write(openGLCheckResult->rendererString().toLatin1()); log.write(", "); QString version((const char*)f->glGetString(GL_VERSION)); log.write(version.toLatin1()); log.close(); // Check if we have a bugged driver that needs fence workaround bool isOnX11 = false; #ifdef HAVE_X11 isOnX11 = true; #endif - if ((isOnX11 && openGLCheckResult->rendererString.startsWith("AMD")) || cfg.forceOpenGLFenceWorkaround()) { + if ((isOnX11 && openGLCheckResult->rendererString().startsWith("AMD")) || cfg.forceOpenGLFenceWorkaround()) { NeedsFenceWorkaround = true; } /** * NVidia + Qt's openGL don't play well together and one cannot * draw a pixmap on a widget more than once in one rendering cycle. * * It can be workarounded by drawing strictly via QPixmapCache and * only when the pixmap size in bigger than doubled size of the * display framebuffer. That is for 8-bit HD display, you should have * a cache bigger than 16 MiB. Don't ask me why. (DK) * * See bug: https://bugs.kde.org/show_bug.cgi?id=361709 * * TODO: check if this workaround is still needed after merging * Qt5+openGL3 branch. */ if (vendor.toUpper().contains("NVIDIA")) { NeedsPixmapCacheWorkaround = true; const QRect screenSize = QApplication::desktop()->screenGeometry(); const int minCacheSize = 20 * 1024; const int cacheSize = 2048 + 2 * 4 * screenSize.width() * screenSize.height() / 1024; //KiB QPixmapCache::setCacheLimit(qMax(minCacheSize, cacheSize)); } } const QString &KisOpenGL::getDebugText() { initialize(); return debugText; } // XXX Temporary function to allow LoD on OpenGL3 without triggering // all of the other 3.2 functionality, can be removed once we move to Qt5.7 bool KisOpenGL::supportsLoD() { initialize(); return openGLCheckResult->supportsLoD(); } bool KisOpenGL::hasOpenGL3() { initialize(); return openGLCheckResult->hasOpenGL3(); } bool KisOpenGL::hasOpenGLES() { initialize(); - return openGLCheckResult->isOpenGLES; + return openGLCheckResult->isOpenGLES(); } bool KisOpenGL::supportsFenceSync() { initialize(); return openGLCheckResult->supportsFenceSync(); } bool KisOpenGL::needsFenceWorkaround() { initialize(); return NeedsFenceWorkaround; } bool KisOpenGL::needsPixmapCacheWorkaround() { initialize(); return NeedsPixmapCacheWorkaround; } void KisOpenGL::setDefaultFormat(bool enableDebug, bool debugSynchronous) { if (defaultFormatIsSet) { return; } defaultFormatIsSet = true; QSurfaceFormat format; #ifdef Q_OS_OSX format.setVersion(3, 2); format.setProfile(QSurfaceFormat::CoreProfile); #else // XXX This can be removed once we move to Qt5.7 format.setVersion(3, 0); format.setProfile(QSurfaceFormat::CompatibilityProfile); format.setOptions(QSurfaceFormat::DeprecatedFunctions); #endif format.setDepthBufferSize(24); format.setStencilBufferSize(8); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); format.setSwapInterval(0); // Disable vertical refresh syncing isDebugEnabled = enableDebug; if (enableDebug) { format.setOption(QSurfaceFormat::DebugContext, true); isDebugSynchronous = debugSynchronous; qDebug() << "QOpenGLDebugLogger will be enabled, synchronous:" << debugSynchronous; } QSurfaceFormat::setDefaultFormat(format); } bool KisOpenGL::hasOpenGL() { return openGLCheckResult->isSupportedVersion(); } diff --git a/libs/ui/opengl/kis_opengl_p.h b/libs/ui/opengl/kis_opengl_p.h new file mode 100644 index 0000000000..1c14162ba6 --- /dev/null +++ b/libs/ui/opengl/kis_opengl_p.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 Alvin Wong + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef KIS_OPENGL_P_H_ +#define KIS_OPENGL_P_H_ + +#include +#include + +class QOpenGLContext; + +namespace KisOpenGLPrivate +{ + +class OpenGLCheckResult { + int m_glMajorVersion = 0; + int m_glMinorVersion = 0; + bool m_supportsDeprecatedFunctions = false; + bool m_isOpenGLES = false; + QString m_rendererString; + QString m_driverVersionString; + +public: + OpenGLCheckResult(QOpenGLContext &context); + + int glMajorVersion() const { + return m_glMajorVersion; + } + + int glMinorVersion() const { + return m_glMinorVersion; + } + + bool supportsDeprecatedFunctions() const { + return m_supportsDeprecatedFunctions; + } + + bool isOpenGLES() const { + return m_isOpenGLES; + } + + QString rendererString() const { + return m_rendererString; + } + + QString driverVersionString() const { + return m_driverVersionString; + } + + bool isSupportedVersion() const { + return +#ifdef Q_OS_OSX + ((glMajorVersion * 100 + glMinorVersion) >= 302 + && !rendererString.toLower().contains("amd") + && !rendererString.toLower().contains("radeon")) +#else + (m_glMajorVersion >= 3 && (m_supportsDeprecatedFunctions || m_isOpenGLES)) || + ((m_glMajorVersion * 100 + m_glMinorVersion) == 201) +#endif + ; + } + + bool supportsLoD() const { + return (m_glMajorVersion * 100 + m_glMinorVersion) >= 300; + } + + bool hasOpenGL3() const { + return (m_glMajorVersion * 100 + m_glMinorVersion) >= 302; + } + + bool supportsFenceSync() const { + return m_glMajorVersion >= 3; + } + +#ifdef Q_OS_WIN + // This is only for detecting whether ANGLE is being used. + // For detecting generic OpenGL ES please check isOpenGLES + bool isUsingAngle() const { + return m_rendererString.startsWith("ANGLE", Qt::CaseInsensitive); + } +#endif +}; + +} // namespace KisOpenGLPrivate + +#endif // KIS_OPENGL_P_H_