File indexing completed on 2024-05-19 16:34:34

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2006-2007 Rivo Laks <rivolaks@hot.ee>
0006     SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "kwinglutils.h"
0012 
0013 // need to call GLTexturePrivate::initStatic()
0014 #include "kwingltexture_p.h"
0015 
0016 #include "kwineffects.h"
0017 #include "kwinglplatform.h"
0018 #include "logging_p.h"
0019 
0020 #include <QFile>
0021 #include <QHash>
0022 #include <QImage>
0023 #include <QMatrix4x4>
0024 #include <QPixmap>
0025 #include <QVarLengthArray>
0026 #include <QVector2D>
0027 #include <QVector3D>
0028 #include <QVector4D>
0029 
0030 #include <array>
0031 #include <cmath>
0032 #include <deque>
0033 
0034 #define DEBUG_GLFRAMEBUFFER 0
0035 
0036 #ifdef __GNUC__
0037 #define likely(x) __builtin_expect(!!(x), 1)
0038 #define unlikely(x) __builtin_expect(!!(x), 0)
0039 #else
0040 #define likely(x) (x)
0041 #define unlikely(x) (x)
0042 #endif
0043 
0044 namespace KWin
0045 {
0046 // Variables
0047 // List of all supported GL extensions
0048 static QList<QByteArray> glExtensions;
0049 
0050 // Functions
0051 
0052 static void initDebugOutput()
0053 {
0054     static bool enabled = qEnvironmentVariableIntValue("KWIN_GL_DEBUG");
0055     if (!enabled) {
0056         return;
0057     }
0058 
0059     const bool have_KHR_debug = hasGLExtension(QByteArrayLiteral("GL_KHR_debug"));
0060     const bool have_ARB_debug = hasGLExtension(QByteArrayLiteral("GL_ARB_debug_output"));
0061     if (!have_KHR_debug && !have_ARB_debug) {
0062         return;
0063     }
0064 
0065     if (!have_ARB_debug) {
0066         // if we don't have ARB debug, but only KHR debug we need to verify whether the context is a debug context
0067         // it should work without as well, but empirical tests show: no it doesn't
0068         if (GLPlatform::instance()->isGLES()) {
0069             if (!hasGLVersion(3, 2)) {
0070                 // empirical data shows extension doesn't work
0071                 return;
0072             }
0073         } else if (!hasGLVersion(3, 0)) {
0074             return;
0075         }
0076         // can only be queried with either OpenGL >= 3.0 or OpenGL ES of at least 3.1
0077         GLint value = 0;
0078         glGetIntegerv(GL_CONTEXT_FLAGS, &value);
0079         if (!(value & GL_CONTEXT_FLAG_DEBUG_BIT)) {
0080             return;
0081         }
0082     }
0083 
0084     // Set the callback function
0085     auto callback = [](GLenum source, GLenum type, GLuint id,
0086                        GLenum severity, GLsizei length,
0087                        const GLchar *message,
0088                        const GLvoid *userParam) {
0089         while (length && std::isspace(message[length - 1])) {
0090             --length;
0091         }
0092 
0093         switch (type) {
0094         case GL_DEBUG_TYPE_ERROR:
0095         case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
0096             qCWarning(LIBKWINGLUTILS, "%#x: %.*s", id, length, message);
0097             break;
0098 
0099         case GL_DEBUG_TYPE_OTHER:
0100         case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
0101         case GL_DEBUG_TYPE_PORTABILITY:
0102         case GL_DEBUG_TYPE_PERFORMANCE:
0103         default:
0104             qCDebug(LIBKWINGLUTILS, "%#x: %.*s", id, length, message);
0105             break;
0106         }
0107     };
0108 
0109     glDebugMessageCallback(callback, nullptr);
0110 
0111     // This state exists only in GL_KHR_debug
0112     if (have_KHR_debug) {
0113         glEnable(GL_DEBUG_OUTPUT);
0114     }
0115 
0116 #if !defined(QT_NO_DEBUG)
0117     // Enable all debug messages
0118     glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
0119 #else
0120     // Enable error messages
0121     glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR, GL_DONT_CARE, 0, nullptr, GL_TRUE);
0122     glDebugMessageControl(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, GL_DONT_CARE, 0, nullptr, GL_TRUE);
0123 #endif
0124 
0125     // Insert a test message
0126     const QByteArray message = QByteArrayLiteral("OpenGL debug output initialized");
0127     glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0,
0128                          GL_DEBUG_SEVERITY_LOW, message.length(), message.constData());
0129 }
0130 
0131 void initGL(const std::function<resolveFuncPtr(const char *)> &resolveFunction)
0132 {
0133     // Get list of supported OpenGL extensions
0134     if (hasGLVersion(3, 0)) {
0135         int count;
0136         glGetIntegerv(GL_NUM_EXTENSIONS, &count);
0137 
0138         for (int i = 0; i < count; i++) {
0139             const QByteArray name = (const char *)glGetStringi(GL_EXTENSIONS, i);
0140             glExtensions << name;
0141         }
0142     } else {
0143         glExtensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
0144     }
0145 
0146     // handle OpenGL extensions functions
0147     glResolveFunctions(resolveFunction);
0148 
0149     initDebugOutput();
0150 
0151     GLTexturePrivate::initStatic();
0152     GLFramebuffer::initStatic();
0153     GLVertexBuffer::initStatic();
0154 }
0155 
0156 void cleanupGL()
0157 {
0158     ShaderManager::cleanup();
0159     GLTexturePrivate::cleanup();
0160     GLFramebuffer::cleanup();
0161     GLVertexBuffer::cleanup();
0162     GLPlatform::cleanup();
0163 
0164     glExtensions.clear();
0165 }
0166 
0167 bool hasGLVersion(int major, int minor, int release)
0168 {
0169     return GLPlatform::instance()->glVersion() >= kVersionNumber(major, minor, release);
0170 }
0171 
0172 bool hasGLExtension(const QByteArray &extension)
0173 {
0174     return glExtensions.contains(extension);
0175 }
0176 
0177 QList<QByteArray> openGLExtensions()
0178 {
0179     return glExtensions;
0180 }
0181 
0182 static QString formatGLError(GLenum err)
0183 {
0184     switch (err) {
0185     case GL_NO_ERROR:
0186         return QStringLiteral("GL_NO_ERROR");
0187     case GL_INVALID_ENUM:
0188         return QStringLiteral("GL_INVALID_ENUM");
0189     case GL_INVALID_VALUE:
0190         return QStringLiteral("GL_INVALID_VALUE");
0191     case GL_INVALID_OPERATION:
0192         return QStringLiteral("GL_INVALID_OPERATION");
0193     case GL_STACK_OVERFLOW:
0194         return QStringLiteral("GL_STACK_OVERFLOW");
0195     case GL_STACK_UNDERFLOW:
0196         return QStringLiteral("GL_STACK_UNDERFLOW");
0197     case GL_OUT_OF_MEMORY:
0198         return QStringLiteral("GL_OUT_OF_MEMORY");
0199     default:
0200         return QLatin1String("0x") + QString::number(err, 16);
0201     }
0202 }
0203 
0204 bool checkGLError(const char *txt)
0205 {
0206     GLenum err = glGetError();
0207     if (err == GL_CONTEXT_LOST) {
0208         qCWarning(LIBKWINGLUTILS) << "GL error: context lost";
0209         return true;
0210     }
0211     bool hasError = false;
0212     while (err != GL_NO_ERROR) {
0213         qCWarning(LIBKWINGLUTILS) << "GL error (" << txt << "): " << formatGLError(err);
0214         hasError = true;
0215         err = glGetError();
0216         if (err == GL_CONTEXT_LOST) {
0217             qCWarning(LIBKWINGLUTILS) << "GL error: context lost";
0218             break;
0219         }
0220     }
0221     return hasError;
0222 }
0223 
0224 //****************************************
0225 // GLShader
0226 //****************************************
0227 
0228 GLShader::GLShader(unsigned int flags)
0229     : mValid(false)
0230     , mLocationsResolved(false)
0231     , mExplicitLinking(flags & ExplicitLinking)
0232 {
0233     mProgram = glCreateProgram();
0234 }
0235 
0236 GLShader::GLShader(const QString &vertexfile, const QString &fragmentfile, unsigned int flags)
0237     : mValid(false)
0238     , mLocationsResolved(false)
0239     , mExplicitLinking(flags & ExplicitLinking)
0240 {
0241     mProgram = glCreateProgram();
0242     loadFromFiles(vertexfile, fragmentfile);
0243 }
0244 
0245 GLShader::~GLShader()
0246 {
0247     if (mProgram) {
0248         glDeleteProgram(mProgram);
0249     }
0250 }
0251 
0252 bool GLShader::loadFromFiles(const QString &vertexFile, const QString &fragmentFile)
0253 {
0254     QFile vf(vertexFile);
0255     if (!vf.open(QIODevice::ReadOnly)) {
0256         qCCritical(LIBKWINGLUTILS) << "Couldn't open" << vertexFile << "for reading!";
0257         return false;
0258     }
0259     const QByteArray vertexSource = vf.readAll();
0260 
0261     QFile ff(fragmentFile);
0262     if (!ff.open(QIODevice::ReadOnly)) {
0263         qCCritical(LIBKWINGLUTILS) << "Couldn't open" << fragmentFile << "for reading!";
0264         return false;
0265     }
0266     const QByteArray fragmentSource = ff.readAll();
0267 
0268     return load(vertexSource, fragmentSource);
0269 }
0270 
0271 bool GLShader::link()
0272 {
0273     // Be optimistic
0274     mValid = true;
0275 
0276     glLinkProgram(mProgram);
0277 
0278     // Get the program info log
0279     int maxLength, length;
0280     glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &maxLength);
0281 
0282     QByteArray log(maxLength, 0);
0283     glGetProgramInfoLog(mProgram, maxLength, &length, log.data());
0284 
0285     // Make sure the program linked successfully
0286     int status;
0287     glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
0288 
0289     if (status == 0) {
0290         qCCritical(LIBKWINGLUTILS) << "Failed to link shader:"
0291                                    << "\n"
0292                                    << log;
0293         mValid = false;
0294     } else if (length > 0) {
0295         qCDebug(LIBKWINGLUTILS) << "Shader link log:" << log;
0296     }
0297 
0298     return mValid;
0299 }
0300 
0301 const QByteArray GLShader::prepareSource(GLenum shaderType, const QByteArray &source) const
0302 {
0303     // Prepare the source code
0304     QByteArray ba;
0305     if (GLPlatform::instance()->isGLES() && GLPlatform::instance()->glslVersion() < kVersionNumber(3, 0)) {
0306         ba.append("precision highp float;\n");
0307     }
0308     ba.append(source);
0309     if (GLPlatform::instance()->isGLES() && GLPlatform::instance()->glslVersion() >= kVersionNumber(3, 0)) {
0310         ba.replace("#version 140", "#version 300 es\n\nprecision highp float;\n");
0311     }
0312 
0313     return ba;
0314 }
0315 
0316 bool GLShader::compile(GLuint program, GLenum shaderType, const QByteArray &source) const
0317 {
0318     GLuint shader = glCreateShader(shaderType);
0319 
0320     QByteArray preparedSource = prepareSource(shaderType, source);
0321     const char *src = preparedSource.constData();
0322     glShaderSource(shader, 1, &src, nullptr);
0323 
0324     // Compile the shader
0325     glCompileShader(shader);
0326 
0327     // Get the shader info log
0328     int maxLength, length;
0329     glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
0330 
0331     QByteArray log(maxLength, 0);
0332     glGetShaderInfoLog(shader, maxLength, &length, log.data());
0333 
0334     // Check the status
0335     int status;
0336     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
0337 
0338     if (status == 0) {
0339         const char *typeName = (shaderType == GL_VERTEX_SHADER ? "vertex" : "fragment");
0340         qCCritical(LIBKWINGLUTILS) << "Failed to compile" << typeName << "shader:"
0341                                    << "\n"
0342                                    << log;
0343     } else if (length > 0) {
0344         qCDebug(LIBKWINGLUTILS) << "Shader compile log:" << log;
0345     }
0346 
0347     if (status != 0) {
0348         glAttachShader(program, shader);
0349     }
0350 
0351     glDeleteShader(shader);
0352     return status != 0;
0353 }
0354 
0355 bool GLShader::load(const QByteArray &vertexSource, const QByteArray &fragmentSource)
0356 {
0357     // Make sure shaders are actually supported
0358     if (!(GLPlatform::instance()->supports(GLSL) &&
0359           // we lack shader branching for Texture2DRectangle everywhere - and it's probably not worth it
0360           GLPlatform::instance()->supports(TextureNPOT))) {
0361         qCCritical(LIBKWINGLUTILS) << "Shaders are not supported";
0362         return false;
0363     }
0364 
0365     mValid = false;
0366 
0367     // Compile the vertex shader
0368     if (!vertexSource.isEmpty()) {
0369         bool success = compile(mProgram, GL_VERTEX_SHADER, vertexSource);
0370 
0371         if (!success) {
0372             return false;
0373         }
0374     }
0375 
0376     // Compile the fragment shader
0377     if (!fragmentSource.isEmpty()) {
0378         bool success = compile(mProgram, GL_FRAGMENT_SHADER, fragmentSource);
0379 
0380         if (!success) {
0381             return false;
0382         }
0383     }
0384 
0385     if (mExplicitLinking) {
0386         return true;
0387     }
0388 
0389     // link() sets mValid
0390     return link();
0391 }
0392 
0393 void GLShader::bindAttributeLocation(const char *name, int index)
0394 {
0395     glBindAttribLocation(mProgram, index, name);
0396 }
0397 
0398 void GLShader::bindFragDataLocation(const char *name, int index)
0399 {
0400     if (!GLPlatform::instance()->isGLES() && (hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_EXT_gpu_shader4")))) {
0401         glBindFragDataLocation(mProgram, index, name);
0402     }
0403 }
0404 
0405 void GLShader::bind()
0406 {
0407     glUseProgram(mProgram);
0408 }
0409 
0410 void GLShader::unbind()
0411 {
0412     glUseProgram(0);
0413 }
0414 
0415 void GLShader::resolveLocations()
0416 {
0417     if (mLocationsResolved) {
0418         return;
0419     }
0420 
0421     mMatrixLocation[TextureMatrix] = uniformLocation("textureMatrix");
0422     mMatrixLocation[ProjectionMatrix] = uniformLocation("projection");
0423     mMatrixLocation[ModelViewMatrix] = uniformLocation("modelview");
0424     mMatrixLocation[ModelViewProjectionMatrix] = uniformLocation("modelViewProjectionMatrix");
0425     mMatrixLocation[WindowTransformation] = uniformLocation("windowTransformation");
0426     mMatrixLocation[ScreenTransformation] = uniformLocation("screenTransformation");
0427 
0428     mVec2Location[Offset] = uniformLocation("offset");
0429 
0430     mVec4Location[ModulationConstant] = uniformLocation("modulation");
0431 
0432     mFloatLocation[Saturation] = uniformLocation("saturation");
0433 
0434     mColorLocation[Color] = uniformLocation("geometryColor");
0435 
0436     mIntLocation[TextureWidth] = uniformLocation("textureWidth");
0437     mIntLocation[TextureHeight] = uniformLocation("textureHeight");
0438 
0439     mLocationsResolved = true;
0440 }
0441 
0442 int GLShader::uniformLocation(const char *name)
0443 {
0444     const int location = glGetUniformLocation(mProgram, name);
0445     return location;
0446 }
0447 
0448 bool GLShader::setUniform(GLShader::MatrixUniform uniform, const QMatrix4x4 &matrix)
0449 {
0450     resolveLocations();
0451     return setUniform(mMatrixLocation[uniform], matrix);
0452 }
0453 
0454 bool GLShader::setUniform(GLShader::Vec2Uniform uniform, const QVector2D &value)
0455 {
0456     resolveLocations();
0457     return setUniform(mVec2Location[uniform], value);
0458 }
0459 
0460 bool GLShader::setUniform(GLShader::Vec4Uniform uniform, const QVector4D &value)
0461 {
0462     resolveLocations();
0463     return setUniform(mVec4Location[uniform], value);
0464 }
0465 
0466 bool GLShader::setUniform(GLShader::FloatUniform uniform, float value)
0467 {
0468     resolveLocations();
0469     return setUniform(mFloatLocation[uniform], value);
0470 }
0471 
0472 bool GLShader::setUniform(GLShader::IntUniform uniform, int value)
0473 {
0474     resolveLocations();
0475     return setUniform(mIntLocation[uniform], value);
0476 }
0477 
0478 bool GLShader::setUniform(GLShader::ColorUniform uniform, const QVector4D &value)
0479 {
0480     resolveLocations();
0481     return setUniform(mColorLocation[uniform], value);
0482 }
0483 
0484 bool GLShader::setUniform(GLShader::ColorUniform uniform, const QColor &value)
0485 {
0486     resolveLocations();
0487     return setUniform(mColorLocation[uniform], value);
0488 }
0489 
0490 bool GLShader::setUniform(const char *name, float value)
0491 {
0492     const int location = uniformLocation(name);
0493     return setUniform(location, value);
0494 }
0495 
0496 bool GLShader::setUniform(const char *name, int value)
0497 {
0498     const int location = uniformLocation(name);
0499     return setUniform(location, value);
0500 }
0501 
0502 bool GLShader::setUniform(const char *name, const QVector2D &value)
0503 {
0504     const int location = uniformLocation(name);
0505     return setUniform(location, value);
0506 }
0507 
0508 bool GLShader::setUniform(const char *name, const QVector3D &value)
0509 {
0510     const int location = uniformLocation(name);
0511     return setUniform(location, value);
0512 }
0513 
0514 bool GLShader::setUniform(const char *name, const QVector4D &value)
0515 {
0516     const int location = uniformLocation(name);
0517     return setUniform(location, value);
0518 }
0519 
0520 bool GLShader::setUniform(const char *name, const QMatrix4x4 &value)
0521 {
0522     const int location = uniformLocation(name);
0523     return setUniform(location, value);
0524 }
0525 
0526 bool GLShader::setUniform(const char *name, const QColor &color)
0527 {
0528     const int location = uniformLocation(name);
0529     return setUniform(location, color);
0530 }
0531 
0532 bool GLShader::setUniform(int location, float value)
0533 {
0534     if (location >= 0) {
0535         glUniform1f(location, value);
0536     }
0537     return (location >= 0);
0538 }
0539 
0540 bool GLShader::setUniform(int location, int value)
0541 {
0542     if (location >= 0) {
0543         glUniform1i(location, value);
0544     }
0545     return (location >= 0);
0546 }
0547 
0548 bool GLShader::setUniform(int location, const QVector2D &value)
0549 {
0550     if (location >= 0) {
0551         glUniform2fv(location, 1, (const GLfloat *)&value);
0552     }
0553     return (location >= 0);
0554 }
0555 
0556 bool GLShader::setUniform(int location, const QVector3D &value)
0557 {
0558     if (location >= 0) {
0559         glUniform3fv(location, 1, (const GLfloat *)&value);
0560     }
0561     return (location >= 0);
0562 }
0563 
0564 bool GLShader::setUniform(int location, const QVector4D &value)
0565 {
0566     if (location >= 0) {
0567         glUniform4fv(location, 1, (const GLfloat *)&value);
0568     }
0569     return (location >= 0);
0570 }
0571 
0572 bool GLShader::setUniform(int location, const QMatrix4x4 &value)
0573 {
0574     if (location >= 0) {
0575         glUniformMatrix4fv(location, 1, GL_FALSE, value.constData());
0576     }
0577     return (location >= 0);
0578 }
0579 
0580 bool GLShader::setUniform(int location, const QColor &color)
0581 {
0582     if (location >= 0) {
0583         glUniform4f(location, color.redF(), color.greenF(), color.blueF(), color.alphaF());
0584     }
0585     return (location >= 0);
0586 }
0587 
0588 int GLShader::attributeLocation(const char *name)
0589 {
0590     int location = glGetAttribLocation(mProgram, name);
0591     return location;
0592 }
0593 
0594 bool GLShader::setAttribute(const char *name, float value)
0595 {
0596     int location = attributeLocation(name);
0597     if (location >= 0) {
0598         glVertexAttrib1f(location, value);
0599     }
0600     return (location >= 0);
0601 }
0602 
0603 QMatrix4x4 GLShader::getUniformMatrix4x4(const char *name)
0604 {
0605     int location = uniformLocation(name);
0606     if (location >= 0) {
0607         GLfloat m[16];
0608         glGetnUniformfv(mProgram, location, sizeof(m), m);
0609         QMatrix4x4 matrix(m[0], m[4], m[8], m[12],
0610                           m[1], m[5], m[9], m[13],
0611                           m[2], m[6], m[10], m[14],
0612                           m[3], m[7], m[11], m[15]);
0613         matrix.optimize();
0614         return matrix;
0615     } else {
0616         return QMatrix4x4();
0617     }
0618 }
0619 
0620 //****************************************
0621 // ShaderManager
0622 //****************************************
0623 std::unique_ptr<ShaderManager> ShaderManager::s_shaderManager;
0624 
0625 ShaderManager *ShaderManager::instance()
0626 {
0627     if (!s_shaderManager) {
0628         s_shaderManager.reset(new ShaderManager());
0629     }
0630     return s_shaderManager.get();
0631 }
0632 
0633 void ShaderManager::cleanup()
0634 {
0635     s_shaderManager.reset();
0636 }
0637 
0638 ShaderManager::ShaderManager()
0639 {
0640 }
0641 
0642 ShaderManager::~ShaderManager()
0643 {
0644     while (!m_boundShaders.isEmpty()) {
0645         popShader();
0646     }
0647 }
0648 
0649 QByteArray ShaderManager::generateVertexSource(ShaderTraits traits) const
0650 {
0651     QByteArray source;
0652     QTextStream stream(&source);
0653 
0654     GLPlatform *const gl = GLPlatform::instance();
0655     QByteArray attribute, varying;
0656 
0657     if (!gl->isGLES()) {
0658         const bool glsl_140 = gl->glslVersion() >= kVersionNumber(1, 40);
0659 
0660         attribute = glsl_140 ? QByteArrayLiteral("in") : QByteArrayLiteral("attribute");
0661         varying = glsl_140 ? QByteArrayLiteral("out") : QByteArrayLiteral("varying");
0662 
0663         if (glsl_140) {
0664             stream << "#version 140\n\n";
0665         }
0666     } else {
0667         const bool glsl_es_300 = gl->glslVersion() >= kVersionNumber(3, 0);
0668 
0669         attribute = glsl_es_300 ? QByteArrayLiteral("in") : QByteArrayLiteral("attribute");
0670         varying = glsl_es_300 ? QByteArrayLiteral("out") : QByteArrayLiteral("varying");
0671 
0672         if (glsl_es_300) {
0673             stream << "#version 300 es\n\n";
0674         }
0675     }
0676 
0677     stream << attribute << " vec4 position;\n";
0678     if (traits & ShaderTrait::MapTexture) {
0679         stream << attribute << " vec4 texcoord;\n\n";
0680         stream << varying << " vec2 texcoord0;\n\n";
0681     } else {
0682         stream << "\n";
0683     }
0684 
0685     stream << "uniform mat4 modelViewProjectionMatrix;\n\n";
0686 
0687     stream << "void main()\n{\n";
0688     if (traits & ShaderTrait::MapTexture) {
0689         stream << "    texcoord0 = texcoord.st;\n";
0690     }
0691 
0692     stream << "    gl_Position = modelViewProjectionMatrix * position;\n";
0693     stream << "}\n";
0694 
0695     stream.flush();
0696     return source;
0697 }
0698 
0699 QByteArray ShaderManager::generateFragmentSource(ShaderTraits traits) const
0700 {
0701     QByteArray source;
0702     QTextStream stream(&source);
0703 
0704     GLPlatform *const gl = GLPlatform::instance();
0705     QByteArray varying, output, textureLookup;
0706 
0707     if (!gl->isGLES()) {
0708         const bool glsl_140 = gl->glslVersion() >= kVersionNumber(1, 40);
0709 
0710         if (glsl_140) {
0711             stream << "#version 140\n\n";
0712         }
0713 
0714         varying = glsl_140 ? QByteArrayLiteral("in") : QByteArrayLiteral("varying");
0715         textureLookup = glsl_140 ? QByteArrayLiteral("texture") : QByteArrayLiteral("texture2D");
0716         output = glsl_140 ? QByteArrayLiteral("fragColor") : QByteArrayLiteral("gl_FragColor");
0717     } else {
0718         const bool glsl_es_300 = GLPlatform::instance()->glslVersion() >= kVersionNumber(3, 0);
0719 
0720         if (glsl_es_300) {
0721             stream << "#version 300 es\n\n";
0722         }
0723 
0724         // From the GLSL ES specification:
0725         //
0726         //     "The fragment language has no default precision qualifier for floating point types."
0727         stream << "precision highp float;\n\n";
0728 
0729         varying = glsl_es_300 ? QByteArrayLiteral("in") : QByteArrayLiteral("varying");
0730         textureLookup = glsl_es_300 ? QByteArrayLiteral("texture") : QByteArrayLiteral("texture2D");
0731         output = glsl_es_300 ? QByteArrayLiteral("fragColor") : QByteArrayLiteral("gl_FragColor");
0732     }
0733 
0734     if (traits & ShaderTrait::MapTexture) {
0735         stream << "uniform sampler2D sampler;\n";
0736 
0737         if (traits & ShaderTrait::Modulate) {
0738             stream << "uniform vec4 modulation;\n";
0739         }
0740         if (traits & ShaderTrait::AdjustSaturation) {
0741             stream << "uniform float saturation;\n";
0742         }
0743 
0744         stream << "\n"
0745                << varying << " vec2 texcoord0;\n";
0746 
0747     } else if (traits & ShaderTrait::UniformColor) {
0748         stream << "uniform vec4 geometryColor;\n";
0749     }
0750 
0751     if (output != QByteArrayLiteral("gl_FragColor")) {
0752         stream << "\nout vec4 " << output << ";\n";
0753     }
0754 
0755     stream << "\nvoid main(void)\n{\n";
0756     if (traits & ShaderTrait::MapTexture) {
0757         stream << "vec2 texcoordC = texcoord0;\n";
0758 
0759         if (traits & (ShaderTrait::Modulate | ShaderTrait::AdjustSaturation)) {
0760             stream << "    vec4 texel = " << textureLookup << "(sampler, texcoordC);\n";
0761             if (traits & ShaderTrait::Modulate) {
0762                 stream << "    texel *= modulation;\n";
0763             }
0764             if (traits & ShaderTrait::AdjustSaturation) {
0765                 stream << "    texel.rgb = mix(vec3(dot(texel.rgb, vec3(0.2126, 0.7152, 0.0722))), texel.rgb, saturation);\n";
0766             }
0767 
0768             stream << "    " << output << " = texel;\n";
0769         } else {
0770             stream << "    " << output << " = " << textureLookup << "(sampler, texcoordC);\n";
0771         }
0772     } else if (traits & ShaderTrait::UniformColor) {
0773         stream << "    " << output << " = geometryColor;\n";
0774     }
0775 
0776     stream << "}";
0777     stream.flush();
0778     return source;
0779 }
0780 
0781 std::unique_ptr<GLShader> ShaderManager::generateShader(ShaderTraits traits)
0782 {
0783     return generateCustomShader(traits);
0784 }
0785 
0786 std::unique_ptr<GLShader> ShaderManager::generateCustomShader(ShaderTraits traits, const QByteArray &vertexSource, const QByteArray &fragmentSource)
0787 {
0788     const QByteArray vertex = vertexSource.isEmpty() ? generateVertexSource(traits) : vertexSource;
0789     const QByteArray fragment = fragmentSource.isEmpty() ? generateFragmentSource(traits) : fragmentSource;
0790 
0791 #if 0
0792     qCDebug(LIBKWINGLUTILS) << "**************";
0793     qCDebug(LIBKWINGLUTILS) << vertex;
0794     qCDebug(LIBKWINGLUTILS) << "**************";
0795     qCDebug(LIBKWINGLUTILS) << fragment;
0796     qCDebug(LIBKWINGLUTILS) << "**************";
0797 #endif
0798 
0799     std::unique_ptr<GLShader> shader{new GLShader(GLShader::ExplicitLinking)};
0800     shader->load(vertex, fragment);
0801 
0802     shader->bindAttributeLocation("position", VA_Position);
0803     shader->bindAttributeLocation("texcoord", VA_TexCoord);
0804     shader->bindFragDataLocation("fragColor", 0);
0805 
0806     shader->link();
0807     return shader;
0808 }
0809 
0810 static QString resolveShaderFilePath(const QString &filePath)
0811 {
0812     QString suffix;
0813     QString extension;
0814 
0815     const qint64 coreVersionNumber = GLPlatform::instance()->isGLES() ? kVersionNumber(3, 0) : kVersionNumber(1, 40);
0816     if (GLPlatform::instance()->glslVersion() >= coreVersionNumber) {
0817         suffix = QStringLiteral("_core");
0818     }
0819 
0820     if (filePath.endsWith(QStringLiteral(".frag"))) {
0821         extension = QStringLiteral(".frag");
0822     } else if (filePath.endsWith(QStringLiteral(".vert"))) {
0823         extension = QStringLiteral(".vert");
0824     } else {
0825         qCWarning(LIBKWINGLUTILS) << filePath << "must end either with .vert or .frag";
0826         return QString();
0827     }
0828 
0829     const QString prefix = filePath.chopped(extension.size());
0830     return prefix + suffix + extension;
0831 }
0832 
0833 std::unique_ptr<GLShader> ShaderManager::generateShaderFromFile(ShaderTraits traits, const QString &vertexFile, const QString &fragmentFile)
0834 {
0835     auto loadShaderFile = [](const QString &filePath) {
0836         QFile file(filePath);
0837         if (file.open(QIODevice::ReadOnly)) {
0838             return file.readAll();
0839         }
0840         qCCritical(LIBKWINGLUTILS) << "Failed to read shader " << filePath;
0841         return QByteArray();
0842     };
0843     QByteArray vertexSource;
0844     QByteArray fragmentSource;
0845     if (!vertexFile.isEmpty()) {
0846         vertexSource = loadShaderFile(resolveShaderFilePath(vertexFile));
0847         if (vertexSource.isEmpty()) {
0848             return std::unique_ptr<GLShader>(new GLShader());
0849         }
0850     }
0851     if (!fragmentFile.isEmpty()) {
0852         fragmentSource = loadShaderFile(resolveShaderFilePath(fragmentFile));
0853         if (fragmentSource.isEmpty()) {
0854             return std::unique_ptr<GLShader>(new GLShader());
0855         }
0856     }
0857     return generateCustomShader(traits, vertexSource, fragmentSource);
0858 }
0859 
0860 GLShader *ShaderManager::shader(ShaderTraits traits)
0861 {
0862     std::unique_ptr<GLShader> &shader = m_shaderHash[traits];
0863     if (!shader) {
0864         shader = generateShader(traits);
0865     }
0866     return shader.get();
0867 }
0868 
0869 GLShader *ShaderManager::getBoundShader() const
0870 {
0871     if (m_boundShaders.isEmpty()) {
0872         return nullptr;
0873     } else {
0874         return m_boundShaders.top();
0875     }
0876 }
0877 
0878 bool ShaderManager::isShaderBound() const
0879 {
0880     return !m_boundShaders.isEmpty();
0881 }
0882 
0883 GLShader *ShaderManager::pushShader(ShaderTraits traits)
0884 {
0885     GLShader *shader = this->shader(traits);
0886     pushShader(shader);
0887     return shader;
0888 }
0889 
0890 void ShaderManager::pushShader(GLShader *shader)
0891 {
0892     // only bind shader if it is not already bound
0893     if (shader != getBoundShader()) {
0894         shader->bind();
0895     }
0896     m_boundShaders.push(shader);
0897 }
0898 
0899 void ShaderManager::popShader()
0900 {
0901     if (m_boundShaders.isEmpty()) {
0902         return;
0903     }
0904     GLShader *shader = m_boundShaders.pop();
0905     if (m_boundShaders.isEmpty()) {
0906         // no more shader bound - unbind
0907         shader->unbind();
0908     } else if (shader != m_boundShaders.top()) {
0909         // only rebind if a different shader is on top of stack
0910         m_boundShaders.top()->bind();
0911     }
0912 }
0913 
0914 void ShaderManager::bindFragDataLocations(GLShader *shader)
0915 {
0916     shader->bindFragDataLocation("fragColor", 0);
0917 }
0918 
0919 void ShaderManager::bindAttributeLocations(GLShader *shader) const
0920 {
0921     shader->bindAttributeLocation("vertex", VA_Position);
0922     shader->bindAttributeLocation("texCoord", VA_TexCoord);
0923 }
0924 
0925 std::unique_ptr<GLShader> ShaderManager::loadShaderFromCode(const QByteArray &vertexSource, const QByteArray &fragmentSource)
0926 {
0927     std::unique_ptr<GLShader> shader{new GLShader(GLShader::ExplicitLinking)};
0928     shader->load(vertexSource, fragmentSource);
0929     bindAttributeLocations(shader.get());
0930     bindFragDataLocations(shader.get());
0931     shader->link();
0932     return shader;
0933 }
0934 
0935 /***  GLFramebuffer  ***/
0936 bool GLFramebuffer::sSupported = false;
0937 bool GLFramebuffer::s_blitSupported = false;
0938 QStack<GLFramebuffer *> GLFramebuffer::s_fbos = QStack<GLFramebuffer *>();
0939 
0940 void GLFramebuffer::initStatic()
0941 {
0942     if (GLPlatform::instance()->isGLES()) {
0943         sSupported = true;
0944         s_blitSupported = hasGLVersion(3, 0);
0945     } else {
0946         sSupported = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_ARB_framebuffer_object")) || hasGLExtension(QByteArrayLiteral("GL_EXT_framebuffer_object"));
0947 
0948         s_blitSupported = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_ARB_framebuffer_object")) || hasGLExtension(QByteArrayLiteral("GL_EXT_framebuffer_blit"));
0949     }
0950 }
0951 
0952 void GLFramebuffer::cleanup()
0953 {
0954     Q_ASSERT(s_fbos.isEmpty());
0955     sSupported = false;
0956     s_blitSupported = false;
0957 }
0958 
0959 bool GLFramebuffer::blitSupported()
0960 {
0961     return s_blitSupported;
0962 }
0963 
0964 GLFramebuffer *GLFramebuffer::currentFramebuffer()
0965 {
0966     return s_fbos.isEmpty() ? nullptr : s_fbos.top();
0967 }
0968 
0969 void GLFramebuffer::pushFramebuffer(GLFramebuffer *fbo)
0970 {
0971     fbo->bind();
0972     s_fbos.push(fbo);
0973 }
0974 
0975 void GLFramebuffer::pushFramebuffers(QStack<GLFramebuffer *> fbos)
0976 {
0977     fbos.top()->bind();
0978     s_fbos.append(fbos);
0979 }
0980 
0981 GLFramebuffer *GLFramebuffer::popFramebuffer()
0982 {
0983     GLFramebuffer *ret = s_fbos.pop();
0984     if (!s_fbos.isEmpty()) {
0985         s_fbos.top()->bind();
0986     } else {
0987         glBindFramebuffer(GL_FRAMEBUFFER, 0);
0988     }
0989 
0990     return ret;
0991 }
0992 
0993 GLFramebuffer::GLFramebuffer()
0994 {
0995 }
0996 
0997 GLFramebuffer::GLFramebuffer(GLTexture *colorAttachment)
0998     : mSize(colorAttachment->size())
0999 {
1000     // Make sure FBO is supported
1001     if (sSupported && !colorAttachment->isNull()) {
1002         initFBO(colorAttachment);
1003     } else {
1004         qCCritical(LIBKWINGLUTILS) << "Framebuffer objects aren't supported!";
1005     }
1006 }
1007 
1008 GLFramebuffer::GLFramebuffer(GLuint handle, const QSize &size)
1009     : mFramebuffer(handle)
1010     , mSize(size)
1011     , mValid(true)
1012     , mForeign(true)
1013 {
1014 }
1015 
1016 GLFramebuffer::~GLFramebuffer()
1017 {
1018     if (!mForeign && mValid) {
1019         glDeleteFramebuffers(1, &mFramebuffer);
1020     }
1021 }
1022 
1023 bool GLFramebuffer::bind()
1024 {
1025     if (!valid()) {
1026         qCCritical(LIBKWINGLUTILS) << "Can't enable invalid framebuffer object!";
1027         return false;
1028     }
1029 
1030     glBindFramebuffer(GL_FRAMEBUFFER, handle());
1031     glViewport(0, 0, mSize.width(), mSize.height());
1032 
1033     return true;
1034 }
1035 
1036 static QString formatFramebufferStatus(GLenum status)
1037 {
1038     switch (status) {
1039     case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1040         // An attachment is the wrong type / is invalid / has 0 width or height
1041         return QStringLiteral("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
1042     case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1043         // There are no images attached to the framebuffer
1044         return QStringLiteral("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
1045     case GL_FRAMEBUFFER_UNSUPPORTED:
1046         // A format or the combination of formats of the attachments is unsupported
1047         return QStringLiteral("GL_FRAMEBUFFER_UNSUPPORTED");
1048     case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
1049         // Not all attached images have the same width and height
1050         return QStringLiteral("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");
1051     case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
1052         // The color attachments don't have the same format
1053         return QStringLiteral("GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");
1054     case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
1055         // The attachments don't have the same number of samples
1056         return QStringLiteral("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE");
1057     case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
1058         // The draw buffer is missing
1059         return QStringLiteral("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER");
1060     case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
1061         // The read buffer is missing
1062         return QStringLiteral("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER");
1063     default:
1064         return QStringLiteral("Unknown (0x") + QString::number(status, 16) + QStringLiteral(")");
1065     }
1066 }
1067 
1068 void GLFramebuffer::initFBO(GLTexture *colorAttachment)
1069 {
1070 #if DEBUG_GLFRAMEBUFFER
1071     GLenum err = glGetError();
1072     if (err != GL_NO_ERROR)
1073         qCCritical(LIBKWINGLUTILS) << "Error status when entering GLFramebuffer::initFBO: " << formatGLError(err);
1074 #endif
1075 
1076     GLuint prevFbo = 0;
1077     if (const GLFramebuffer *current = currentFramebuffer()) {
1078         prevFbo = current->handle();
1079     }
1080 
1081     glGenFramebuffers(1, &mFramebuffer);
1082 
1083 #if DEBUG_GLFRAMEBUFFER
1084     if ((err = glGetError()) != GL_NO_ERROR) {
1085         qCCritical(LIBKWINGLUTILS) << "glGenFramebuffers failed: " << formatGLError(err);
1086         return;
1087     }
1088 #endif
1089 
1090     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
1091 
1092 #if DEBUG_GLFRAMEBUFFER
1093     if ((err = glGetError()) != GL_NO_ERROR) {
1094         qCCritical(LIBKWINGLUTILS) << "glBindFramebuffer failed: " << formatGLError(err);
1095         glDeleteFramebuffers(1, &mFramebuffer);
1096         return;
1097     }
1098 #endif
1099 
1100     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1101                            colorAttachment->target(), colorAttachment->texture(), 0);
1102 
1103 #if DEBUG_GLFRAMEBUFFER
1104     if ((err = glGetError()) != GL_NO_ERROR) {
1105         qCCritical(LIBKWINGLUTILS) << "glFramebufferTexture2D failed: " << formatGLError(err);
1106         glBindFramebuffer(GL_FRAMEBUFFER, prevFbo);
1107         glDeleteFramebuffers(1, &mFramebuffer);
1108         return;
1109     }
1110 #endif
1111 
1112     const GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1113 
1114     glBindFramebuffer(GL_FRAMEBUFFER, prevFbo);
1115 
1116     if (status != GL_FRAMEBUFFER_COMPLETE) {
1117         // We have an incomplete framebuffer, consider it invalid
1118         if (status == 0) {
1119             qCCritical(LIBKWINGLUTILS) << "glCheckFramebufferStatus failed: " << formatGLError(glGetError());
1120         } else {
1121             qCCritical(LIBKWINGLUTILS) << "Invalid framebuffer status: " << formatFramebufferStatus(status);
1122         }
1123         glDeleteFramebuffers(1, &mFramebuffer);
1124         return;
1125     }
1126 
1127     mValid = true;
1128 }
1129 
1130 void GLFramebuffer::blitFromFramebuffer(const QRect &source, const QRect &destination, GLenum filter)
1131 {
1132     if (!valid()) {
1133         return;
1134     }
1135 
1136     const GLFramebuffer *top = currentFramebuffer();
1137     GLFramebuffer::pushFramebuffer(this);
1138 
1139     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, handle());
1140     glBindFramebuffer(GL_READ_FRAMEBUFFER, top->handle());
1141 
1142     const QRect s = source.isNull() ? QRect(QPoint(0, 0), top->size()) : source;
1143     const QRect d = destination.isNull() ? QRect(QPoint(0, 0), size()) : destination;
1144 
1145     const GLuint srcX0 = s.x();
1146     const GLuint srcY0 = top->size().height() - (s.y() + s.height());
1147     const GLuint srcX1 = s.x() + s.width();
1148     const GLuint srcY1 = top->size().height() - s.y();
1149 
1150     const GLuint dstX0 = d.x();
1151     const GLuint dstY0 = mSize.height() - (d.y() + d.height());
1152     const GLuint dstX1 = d.x() + d.width();
1153     const GLuint dstY1 = mSize.height() - d.y();
1154 
1155     glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_COLOR_BUFFER_BIT, filter);
1156 
1157     GLFramebuffer::popFramebuffer();
1158 }
1159 
1160 // ------------------------------------------------------------------
1161 
1162 static const uint16_t indices[] = {
1163     1, 0, 3, 3, 2, 1, 5, 4, 7, 7, 6, 5, 9, 8, 11, 11, 10, 9,
1164     13, 12, 15, 15, 14, 13, 17, 16, 19, 19, 18, 17, 21, 20, 23, 23, 22, 21,
1165     25, 24, 27, 27, 26, 25, 29, 28, 31, 31, 30, 29, 33, 32, 35, 35, 34, 33,
1166     37, 36, 39, 39, 38, 37, 41, 40, 43, 43, 42, 41, 45, 44, 47, 47, 46, 45,
1167     49, 48, 51, 51, 50, 49, 53, 52, 55, 55, 54, 53, 57, 56, 59, 59, 58, 57,
1168     61, 60, 63, 63, 62, 61, 65, 64, 67, 67, 66, 65, 69, 68, 71, 71, 70, 69,
1169     73, 72, 75, 75, 74, 73, 77, 76, 79, 79, 78, 77, 81, 80, 83, 83, 82, 81,
1170     85, 84, 87, 87, 86, 85, 89, 88, 91, 91, 90, 89, 93, 92, 95, 95, 94, 93,
1171     97, 96, 99, 99, 98, 97, 101, 100, 103, 103, 102, 101, 105, 104, 107, 107, 106, 105,
1172     109, 108, 111, 111, 110, 109, 113, 112, 115, 115, 114, 113, 117, 116, 119, 119, 118, 117,
1173     121, 120, 123, 123, 122, 121, 125, 124, 127, 127, 126, 125, 129, 128, 131, 131, 130, 129,
1174     133, 132, 135, 135, 134, 133, 137, 136, 139, 139, 138, 137, 141, 140, 143, 143, 142, 141,
1175     145, 144, 147, 147, 146, 145, 149, 148, 151, 151, 150, 149, 153, 152, 155, 155, 154, 153,
1176     157, 156, 159, 159, 158, 157, 161, 160, 163, 163, 162, 161, 165, 164, 167, 167, 166, 165,
1177     169, 168, 171, 171, 170, 169, 173, 172, 175, 175, 174, 173, 177, 176, 179, 179, 178, 177,
1178     181, 180, 183, 183, 182, 181, 185, 184, 187, 187, 186, 185, 189, 188, 191, 191, 190, 189,
1179     193, 192, 195, 195, 194, 193, 197, 196, 199, 199, 198, 197, 201, 200, 203, 203, 202, 201,
1180     205, 204, 207, 207, 206, 205, 209, 208, 211, 211, 210, 209, 213, 212, 215, 215, 214, 213,
1181     217, 216, 219, 219, 218, 217, 221, 220, 223, 223, 222, 221, 225, 224, 227, 227, 226, 225,
1182     229, 228, 231, 231, 230, 229, 233, 232, 235, 235, 234, 233, 237, 236, 239, 239, 238, 237,
1183     241, 240, 243, 243, 242, 241, 245, 244, 247, 247, 246, 245, 249, 248, 251, 251, 250, 249,
1184     253, 252, 255, 255, 254, 253, 257, 256, 259, 259, 258, 257, 261, 260, 263, 263, 262, 261,
1185     265, 264, 267, 267, 266, 265, 269, 268, 271, 271, 270, 269, 273, 272, 275, 275, 274, 273,
1186     277, 276, 279, 279, 278, 277, 281, 280, 283, 283, 282, 281, 285, 284, 287, 287, 286, 285,
1187     289, 288, 291, 291, 290, 289, 293, 292, 295, 295, 294, 293, 297, 296, 299, 299, 298, 297,
1188     301, 300, 303, 303, 302, 301, 305, 304, 307, 307, 306, 305, 309, 308, 311, 311, 310, 309,
1189     313, 312, 315, 315, 314, 313, 317, 316, 319, 319, 318, 317, 321, 320, 323, 323, 322, 321,
1190     325, 324, 327, 327, 326, 325, 329, 328, 331, 331, 330, 329, 333, 332, 335, 335, 334, 333,
1191     337, 336, 339, 339, 338, 337, 341, 340, 343, 343, 342, 341, 345, 344, 347, 347, 346, 345,
1192     349, 348, 351, 351, 350, 349, 353, 352, 355, 355, 354, 353, 357, 356, 359, 359, 358, 357,
1193     361, 360, 363, 363, 362, 361, 365, 364, 367, 367, 366, 365, 369, 368, 371, 371, 370, 369,
1194     373, 372, 375, 375, 374, 373, 377, 376, 379, 379, 378, 377, 381, 380, 383, 383, 382, 381,
1195     385, 384, 387, 387, 386, 385, 389, 388, 391, 391, 390, 389, 393, 392, 395, 395, 394, 393,
1196     397, 396, 399, 399, 398, 397, 401, 400, 403, 403, 402, 401, 405, 404, 407, 407, 406, 405,
1197     409, 408, 411, 411, 410, 409, 413, 412, 415, 415, 414, 413, 417, 416, 419, 419, 418, 417,
1198     421, 420, 423, 423, 422, 421, 425, 424, 427, 427, 426, 425, 429, 428, 431, 431, 430, 429,
1199     433, 432, 435, 435, 434, 433, 437, 436, 439, 439, 438, 437, 441, 440, 443, 443, 442, 441,
1200     445, 444, 447, 447, 446, 445, 449, 448, 451, 451, 450, 449, 453, 452, 455, 455, 454, 453,
1201     457, 456, 459, 459, 458, 457, 461, 460, 463, 463, 462, 461, 465, 464, 467, 467, 466, 465,
1202     469, 468, 471, 471, 470, 469, 473, 472, 475, 475, 474, 473, 477, 476, 479, 479, 478, 477,
1203     481, 480, 483, 483, 482, 481, 485, 484, 487, 487, 486, 485, 489, 488, 491, 491, 490, 489,
1204     493, 492, 495, 495, 494, 493, 497, 496, 499, 499, 498, 497, 501, 500, 503, 503, 502, 501,
1205     505, 504, 507, 507, 506, 505, 509, 508, 511, 511, 510, 509, 513, 512, 515, 515, 514, 513,
1206     517, 516, 519, 519, 518, 517, 521, 520, 523, 523, 522, 521, 525, 524, 527, 527, 526, 525,
1207     529, 528, 531, 531, 530, 529, 533, 532, 535, 535, 534, 533, 537, 536, 539, 539, 538, 537,
1208     541, 540, 543, 543, 542, 541, 545, 544, 547, 547, 546, 545, 549, 548, 551, 551, 550, 549,
1209     553, 552, 555, 555, 554, 553, 557, 556, 559, 559, 558, 557, 561, 560, 563, 563, 562, 561,
1210     565, 564, 567, 567, 566, 565, 569, 568, 571, 571, 570, 569, 573, 572, 575, 575, 574, 573,
1211     577, 576, 579, 579, 578, 577, 581, 580, 583, 583, 582, 581, 585, 584, 587, 587, 586, 585,
1212     589, 588, 591, 591, 590, 589, 593, 592, 595, 595, 594, 593, 597, 596, 599, 599, 598, 597,
1213     601, 600, 603, 603, 602, 601, 605, 604, 607, 607, 606, 605, 609, 608, 611, 611, 610, 609,
1214     613, 612, 615, 615, 614, 613, 617, 616, 619, 619, 618, 617, 621, 620, 623, 623, 622, 621,
1215     625, 624, 627, 627, 626, 625, 629, 628, 631, 631, 630, 629, 633, 632, 635, 635, 634, 633,
1216     637, 636, 639, 639, 638, 637, 641, 640, 643, 643, 642, 641, 645, 644, 647, 647, 646, 645,
1217     649, 648, 651, 651, 650, 649, 653, 652, 655, 655, 654, 653, 657, 656, 659, 659, 658, 657,
1218     661, 660, 663, 663, 662, 661, 665, 664, 667, 667, 666, 665, 669, 668, 671, 671, 670, 669,
1219     673, 672, 675, 675, 674, 673, 677, 676, 679, 679, 678, 677, 681, 680, 683, 683, 682, 681,
1220     685, 684, 687, 687, 686, 685, 689, 688, 691, 691, 690, 689, 693, 692, 695, 695, 694, 693,
1221     697, 696, 699, 699, 698, 697, 701, 700, 703, 703, 702, 701, 705, 704, 707, 707, 706, 705,
1222     709, 708, 711, 711, 710, 709, 713, 712, 715, 715, 714, 713, 717, 716, 719, 719, 718, 717,
1223     721, 720, 723, 723, 722, 721, 725, 724, 727, 727, 726, 725, 729, 728, 731, 731, 730, 729,
1224     733, 732, 735, 735, 734, 733, 737, 736, 739, 739, 738, 737, 741, 740, 743, 743, 742, 741,
1225     745, 744, 747, 747, 746, 745, 749, 748, 751, 751, 750, 749, 753, 752, 755, 755, 754, 753,
1226     757, 756, 759, 759, 758, 757, 761, 760, 763, 763, 762, 761, 765, 764, 767, 767, 766, 765,
1227     769, 768, 771, 771, 770, 769, 773, 772, 775, 775, 774, 773, 777, 776, 779, 779, 778, 777,
1228     781, 780, 783, 783, 782, 781, 785, 784, 787, 787, 786, 785, 789, 788, 791, 791, 790, 789,
1229     793, 792, 795, 795, 794, 793, 797, 796, 799, 799, 798, 797, 801, 800, 803, 803, 802, 801,
1230     805, 804, 807, 807, 806, 805, 809, 808, 811, 811, 810, 809, 813, 812, 815, 815, 814, 813,
1231     817, 816, 819, 819, 818, 817, 821, 820, 823, 823, 822, 821, 825, 824, 827, 827, 826, 825,
1232     829, 828, 831, 831, 830, 829, 833, 832, 835, 835, 834, 833, 837, 836, 839, 839, 838, 837,
1233     841, 840, 843, 843, 842, 841, 845, 844, 847, 847, 846, 845, 849, 848, 851, 851, 850, 849,
1234     853, 852, 855, 855, 854, 853, 857, 856, 859, 859, 858, 857, 861, 860, 863, 863, 862, 861,
1235     865, 864, 867, 867, 866, 865, 869, 868, 871, 871, 870, 869, 873, 872, 875, 875, 874, 873,
1236     877, 876, 879, 879, 878, 877, 881, 880, 883, 883, 882, 881, 885, 884, 887, 887, 886, 885,
1237     889, 888, 891, 891, 890, 889, 893, 892, 895, 895, 894, 893, 897, 896, 899, 899, 898, 897,
1238     901, 900, 903, 903, 902, 901, 905, 904, 907, 907, 906, 905, 909, 908, 911, 911, 910, 909,
1239     913, 912, 915, 915, 914, 913, 917, 916, 919, 919, 918, 917, 921, 920, 923, 923, 922, 921,
1240     925, 924, 927, 927, 926, 925, 929, 928, 931, 931, 930, 929, 933, 932, 935, 935, 934, 933,
1241     937, 936, 939, 939, 938, 937, 941, 940, 943, 943, 942, 941, 945, 944, 947, 947, 946, 945,
1242     949, 948, 951, 951, 950, 949, 953, 952, 955, 955, 954, 953, 957, 956, 959, 959, 958, 957,
1243     961, 960, 963, 963, 962, 961, 965, 964, 967, 967, 966, 965, 969, 968, 971, 971, 970, 969,
1244     973, 972, 975, 975, 974, 973, 977, 976, 979, 979, 978, 977, 981, 980, 983, 983, 982, 981,
1245     985, 984, 987, 987, 986, 985, 989, 988, 991, 991, 990, 989, 993, 992, 995, 995, 994, 993,
1246     997, 996, 999, 999, 998, 997, 1001, 1000, 1003, 1003, 1002, 1001, 1005, 1004, 1007, 1007, 1006, 1005,
1247     1009, 1008, 1011, 1011, 1010, 1009, 1013, 1012, 1015, 1015, 1014, 1013, 1017, 1016, 1019, 1019, 1018, 1017,
1248     1021, 1020, 1023, 1023, 1022, 1021, 1025, 1024, 1027, 1027, 1026, 1025, 1029, 1028, 1031, 1031, 1030, 1029,
1249     1033, 1032, 1035, 1035, 1034, 1033, 1037, 1036, 1039, 1039, 1038, 1037, 1041, 1040, 1043, 1043, 1042, 1041,
1250     1045, 1044, 1047, 1047, 1046, 1045, 1049, 1048, 1051, 1051, 1050, 1049, 1053, 1052, 1055, 1055, 1054, 1053,
1251     1057, 1056, 1059, 1059, 1058, 1057, 1061, 1060, 1063, 1063, 1062, 1061, 1065, 1064, 1067, 1067, 1066, 1065,
1252     1069, 1068, 1071, 1071, 1070, 1069, 1073, 1072, 1075, 1075, 1074, 1073, 1077, 1076, 1079, 1079, 1078, 1077,
1253     1081, 1080, 1083, 1083, 1082, 1081, 1085, 1084, 1087, 1087, 1086, 1085, 1089, 1088, 1091, 1091, 1090, 1089,
1254     1093, 1092, 1095, 1095, 1094, 1093, 1097, 1096, 1099, 1099, 1098, 1097, 1101, 1100, 1103, 1103, 1102, 1101,
1255     1105, 1104, 1107, 1107, 1106, 1105, 1109, 1108, 1111, 1111, 1110, 1109, 1113, 1112, 1115, 1115, 1114, 1113,
1256     1117, 1116, 1119, 1119, 1118, 1117, 1121, 1120, 1123, 1123, 1122, 1121, 1125, 1124, 1127, 1127, 1126, 1125,
1257     1129, 1128, 1131, 1131, 1130, 1129, 1133, 1132, 1135, 1135, 1134, 1133, 1137, 1136, 1139, 1139, 1138, 1137,
1258     1141, 1140, 1143, 1143, 1142, 1141, 1145, 1144, 1147, 1147, 1146, 1145, 1149, 1148, 1151, 1151, 1150, 1149,
1259     1153, 1152, 1155, 1155, 1154, 1153, 1157, 1156, 1159, 1159, 1158, 1157, 1161, 1160, 1163, 1163, 1162, 1161,
1260     1165, 1164, 1167, 1167, 1166, 1165, 1169, 1168, 1171, 1171, 1170, 1169, 1173, 1172, 1175, 1175, 1174, 1173,
1261     1177, 1176, 1179, 1179, 1178, 1177, 1181, 1180, 1183, 1183, 1182, 1181, 1185, 1184, 1187, 1187, 1186, 1185,
1262     1189, 1188, 1191, 1191, 1190, 1189, 1193, 1192, 1195, 1195, 1194, 1193, 1197, 1196, 1199, 1199, 1198, 1197,
1263     1201, 1200, 1203, 1203, 1202, 1201, 1205, 1204, 1207, 1207, 1206, 1205, 1209, 1208, 1211, 1211, 1210, 1209,
1264     1213, 1212, 1215, 1215, 1214, 1213, 1217, 1216, 1219, 1219, 1218, 1217, 1221, 1220, 1223, 1223, 1222, 1221,
1265     1225, 1224, 1227, 1227, 1226, 1225, 1229, 1228, 1231, 1231, 1230, 1229, 1233, 1232, 1235, 1235, 1234, 1233,
1266     1237, 1236, 1239, 1239, 1238, 1237, 1241, 1240, 1243, 1243, 1242, 1241, 1245, 1244, 1247, 1247, 1246, 1245,
1267     1249, 1248, 1251, 1251, 1250, 1249, 1253, 1252, 1255, 1255, 1254, 1253, 1257, 1256, 1259, 1259, 1258, 1257,
1268     1261, 1260, 1263, 1263, 1262, 1261, 1265, 1264, 1267, 1267, 1266, 1265, 1269, 1268, 1271, 1271, 1270, 1269,
1269     1273, 1272, 1275, 1275, 1274, 1273, 1277, 1276, 1279, 1279, 1278, 1277, 1281, 1280, 1283, 1283, 1282, 1281,
1270     1285, 1284, 1287, 1287, 1286, 1285, 1289, 1288, 1291, 1291, 1290, 1289, 1293, 1292, 1295, 1295, 1294, 1293,
1271     1297, 1296, 1299, 1299, 1298, 1297, 1301, 1300, 1303, 1303, 1302, 1301, 1305, 1304, 1307, 1307, 1306, 1305,
1272     1309, 1308, 1311, 1311, 1310, 1309, 1313, 1312, 1315, 1315, 1314, 1313, 1317, 1316, 1319, 1319, 1318, 1317,
1273     1321, 1320, 1323, 1323, 1322, 1321, 1325, 1324, 1327, 1327, 1326, 1325, 1329, 1328, 1331, 1331, 1330, 1329,
1274     1333, 1332, 1335, 1335, 1334, 1333, 1337, 1336, 1339, 1339, 1338, 1337, 1341, 1340, 1343, 1343, 1342, 1341,
1275     1345, 1344, 1347, 1347, 1346, 1345, 1349, 1348, 1351, 1351, 1350, 1349, 1353, 1352, 1355, 1355, 1354, 1353,
1276     1357, 1356, 1359, 1359, 1358, 1357, 1361, 1360, 1363, 1363, 1362, 1361, 1365, 1364, 1367, 1367, 1366, 1365,
1277     1369, 1368, 1371, 1371, 1370, 1369, 1373, 1372, 1375, 1375, 1374, 1373, 1377, 1376, 1379, 1379, 1378, 1377,
1278     1381, 1380, 1383, 1383, 1382, 1381, 1385, 1384, 1387, 1387, 1386, 1385, 1389, 1388, 1391, 1391, 1390, 1389,
1279     1393, 1392, 1395, 1395, 1394, 1393, 1397, 1396, 1399, 1399, 1398, 1397, 1401, 1400, 1403, 1403, 1402, 1401,
1280     1405, 1404, 1407, 1407, 1406, 1405, 1409, 1408, 1411, 1411, 1410, 1409, 1413, 1412, 1415, 1415, 1414, 1413,
1281     1417, 1416, 1419, 1419, 1418, 1417, 1421, 1420, 1423, 1423, 1422, 1421, 1425, 1424, 1427, 1427, 1426, 1425,
1282     1429, 1428, 1431, 1431, 1430, 1429, 1433, 1432, 1435, 1435, 1434, 1433, 1437, 1436, 1439, 1439, 1438, 1437,
1283     1441, 1440, 1443, 1443, 1442, 1441, 1445, 1444, 1447, 1447, 1446, 1445, 1449, 1448, 1451, 1451, 1450, 1449,
1284     1453, 1452, 1455, 1455, 1454, 1453, 1457, 1456, 1459, 1459, 1458, 1457, 1461, 1460, 1463, 1463, 1462, 1461,
1285     1465, 1464, 1467, 1467, 1466, 1465, 1469, 1468, 1471, 1471, 1470, 1469, 1473, 1472, 1475, 1475, 1474, 1473,
1286     1477, 1476, 1479, 1479, 1478, 1477, 1481, 1480, 1483, 1483, 1482, 1481, 1485, 1484, 1487, 1487, 1486, 1485,
1287     1489, 1488, 1491, 1491, 1490, 1489, 1493, 1492, 1495, 1495, 1494, 1493, 1497, 1496, 1499, 1499, 1498, 1497,
1288     1501, 1500, 1503, 1503, 1502, 1501, 1505, 1504, 1507, 1507, 1506, 1505, 1509, 1508, 1511, 1511, 1510, 1509,
1289     1513, 1512, 1515, 1515, 1514, 1513, 1517, 1516, 1519, 1519, 1518, 1517, 1521, 1520, 1523, 1523, 1522, 1521,
1290     1525, 1524, 1527, 1527, 1526, 1525, 1529, 1528, 1531, 1531, 1530, 1529, 1533, 1532, 1535, 1535, 1534, 1533,
1291     1537, 1536, 1539, 1539, 1538, 1537, 1541, 1540, 1543, 1543, 1542, 1541, 1545, 1544, 1547, 1547, 1546, 1545,
1292     1549, 1548, 1551, 1551, 1550, 1549, 1553, 1552, 1555, 1555, 1554, 1553, 1557, 1556, 1559, 1559, 1558, 1557,
1293     1561, 1560, 1563, 1563, 1562, 1561, 1565, 1564, 1567, 1567, 1566, 1565, 1569, 1568, 1571, 1571, 1570, 1569,
1294     1573, 1572, 1575, 1575, 1574, 1573, 1577, 1576, 1579, 1579, 1578, 1577, 1581, 1580, 1583, 1583, 1582, 1581,
1295     1585, 1584, 1587, 1587, 1586, 1585, 1589, 1588, 1591, 1591, 1590, 1589, 1593, 1592, 1595, 1595, 1594, 1593,
1296     1597, 1596, 1599, 1599, 1598, 1597, 1601, 1600, 1603, 1603, 1602, 1601, 1605, 1604, 1607, 1607, 1606, 1605,
1297     1609, 1608, 1611, 1611, 1610, 1609, 1613, 1612, 1615, 1615, 1614, 1613, 1617, 1616, 1619, 1619, 1618, 1617,
1298     1621, 1620, 1623, 1623, 1622, 1621, 1625, 1624, 1627, 1627, 1626, 1625, 1629, 1628, 1631, 1631, 1630, 1629,
1299     1633, 1632, 1635, 1635, 1634, 1633, 1637, 1636, 1639, 1639, 1638, 1637, 1641, 1640, 1643, 1643, 1642, 1641,
1300     1645, 1644, 1647, 1647, 1646, 1645, 1649, 1648, 1651, 1651, 1650, 1649, 1653, 1652, 1655, 1655, 1654, 1653,
1301     1657, 1656, 1659, 1659, 1658, 1657, 1661, 1660, 1663, 1663, 1662, 1661, 1665, 1664, 1667, 1667, 1666, 1665,
1302     1669, 1668, 1671, 1671, 1670, 1669, 1673, 1672, 1675, 1675, 1674, 1673, 1677, 1676, 1679, 1679, 1678, 1677,
1303     1681, 1680, 1683, 1683, 1682, 1681, 1685, 1684, 1687, 1687, 1686, 1685, 1689, 1688, 1691, 1691, 1690, 1689,
1304     1693, 1692, 1695, 1695, 1694, 1693, 1697, 1696, 1699, 1699, 1698, 1697, 1701, 1700, 1703, 1703, 1702, 1701,
1305     1705, 1704, 1707, 1707, 1706, 1705, 1709, 1708, 1711, 1711, 1710, 1709, 1713, 1712, 1715, 1715, 1714, 1713,
1306     1717, 1716, 1719, 1719, 1718, 1717, 1721, 1720, 1723, 1723, 1722, 1721, 1725, 1724, 1727, 1727, 1726, 1725,
1307     1729, 1728, 1731, 1731, 1730, 1729, 1733, 1732, 1735, 1735, 1734, 1733, 1737, 1736, 1739, 1739, 1738, 1737,
1308     1741, 1740, 1743, 1743, 1742, 1741, 1745, 1744, 1747, 1747, 1746, 1745, 1749, 1748, 1751, 1751, 1750, 1749,
1309     1753, 1752, 1755, 1755, 1754, 1753, 1757, 1756, 1759, 1759, 1758, 1757, 1761, 1760, 1763, 1763, 1762, 1761,
1310     1765, 1764, 1767, 1767, 1766, 1765, 1769, 1768, 1771, 1771, 1770, 1769, 1773, 1772, 1775, 1775, 1774, 1773,
1311     1777, 1776, 1779, 1779, 1778, 1777, 1781, 1780, 1783, 1783, 1782, 1781, 1785, 1784, 1787, 1787, 1786, 1785,
1312     1789, 1788, 1791, 1791, 1790, 1789, 1793, 1792, 1795, 1795, 1794, 1793, 1797, 1796, 1799, 1799, 1798, 1797,
1313     1801, 1800, 1803, 1803, 1802, 1801, 1805, 1804, 1807, 1807, 1806, 1805, 1809, 1808, 1811, 1811, 1810, 1809,
1314     1813, 1812, 1815, 1815, 1814, 1813, 1817, 1816, 1819, 1819, 1818, 1817, 1821, 1820, 1823, 1823, 1822, 1821,
1315     1825, 1824, 1827, 1827, 1826, 1825, 1829, 1828, 1831, 1831, 1830, 1829, 1833, 1832, 1835, 1835, 1834, 1833,
1316     1837, 1836, 1839, 1839, 1838, 1837, 1841, 1840, 1843, 1843, 1842, 1841, 1845, 1844, 1847, 1847, 1846, 1845,
1317     1849, 1848, 1851, 1851, 1850, 1849, 1853, 1852, 1855, 1855, 1854, 1853, 1857, 1856, 1859, 1859, 1858, 1857,
1318     1861, 1860, 1863, 1863, 1862, 1861, 1865, 1864, 1867, 1867, 1866, 1865, 1869, 1868, 1871, 1871, 1870, 1869,
1319     1873, 1872, 1875, 1875, 1874, 1873, 1877, 1876, 1879, 1879, 1878, 1877, 1881, 1880, 1883, 1883, 1882, 1881,
1320     1885, 1884, 1887, 1887, 1886, 1885, 1889, 1888, 1891, 1891, 1890, 1889, 1893, 1892, 1895, 1895, 1894, 1893,
1321     1897, 1896, 1899, 1899, 1898, 1897, 1901, 1900, 1903, 1903, 1902, 1901, 1905, 1904, 1907, 1907, 1906, 1905,
1322     1909, 1908, 1911, 1911, 1910, 1909, 1913, 1912, 1915, 1915, 1914, 1913, 1917, 1916, 1919, 1919, 1918, 1917,
1323     1921, 1920, 1923, 1923, 1922, 1921, 1925, 1924, 1927, 1927, 1926, 1925, 1929, 1928, 1931, 1931, 1930, 1929,
1324     1933, 1932, 1935, 1935, 1934, 1933, 1937, 1936, 1939, 1939, 1938, 1937, 1941, 1940, 1943, 1943, 1942, 1941,
1325     1945, 1944, 1947, 1947, 1946, 1945, 1949, 1948, 1951, 1951, 1950, 1949, 1953, 1952, 1955, 1955, 1954, 1953,
1326     1957, 1956, 1959, 1959, 1958, 1957, 1961, 1960, 1963, 1963, 1962, 1961, 1965, 1964, 1967, 1967, 1966, 1965,
1327     1969, 1968, 1971, 1971, 1970, 1969, 1973, 1972, 1975, 1975, 1974, 1973, 1977, 1976, 1979, 1979, 1978, 1977,
1328     1981, 1980, 1983, 1983, 1982, 1981, 1985, 1984, 1987, 1987, 1986, 1985, 1989, 1988, 1991, 1991, 1990, 1989,
1329     1993, 1992, 1995, 1995, 1994, 1993, 1997, 1996, 1999, 1999, 1998, 1997, 2001, 2000, 2003, 2003, 2002, 2001,
1330     2005, 2004, 2007, 2007, 2006, 2005, 2009, 2008, 2011, 2011, 2010, 2009, 2013, 2012, 2015, 2015, 2014, 2013,
1331     2017, 2016, 2019, 2019, 2018, 2017, 2021, 2020, 2023, 2023, 2022, 2021, 2025, 2024, 2027, 2027, 2026, 2025,
1332     2029, 2028, 2031, 2031, 2030, 2029, 2033, 2032, 2035, 2035, 2034, 2033, 2037, 2036, 2039, 2039, 2038, 2037,
1333     2041, 2040, 2043, 2043, 2042, 2041, 2045, 2044, 2047, 2047, 2046, 2045};
1334 
1335 // Certain GPUs, especially mobile, require the data copied to the GPU to be aligned to a
1336 // certain amount of bytes. For example, the Mali GPU requires data to be aligned to 8 bytes.
1337 // This function helps ensure that the data is aligned.
1338 template<typename T>
1339 T align(T value, int bytes)
1340 {
1341     return (value + bytes - 1) & ~T(bytes - 1);
1342 }
1343 
1344 class IndexBuffer
1345 {
1346 public:
1347     IndexBuffer();
1348     ~IndexBuffer();
1349 
1350     void accommodate(int count);
1351     void bind();
1352 
1353 private:
1354     GLuint m_buffer;
1355     size_t m_size;
1356     int m_count;
1357 };
1358 
1359 IndexBuffer::IndexBuffer()
1360 {
1361     // The maximum number of quads we can render with 16 bit indices is 16,384.
1362     // But we start with 512 and grow the buffer as needed.
1363     m_size = sizeof(indices);
1364     m_count = m_size / (6 * sizeof(uint16_t));
1365 
1366     glGenBuffers(1, &m_buffer);
1367     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
1368     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
1369 }
1370 
1371 IndexBuffer::~IndexBuffer()
1372 {
1373     glDeleteBuffers(1, &m_buffer);
1374 }
1375 
1376 void IndexBuffer::accommodate(int count)
1377 {
1378     // Check if we need to grow the buffer.
1379     if (count <= m_count) {
1380         return;
1381     }
1382 
1383     size_t size = 6 * sizeof(uint16_t) * count;
1384 
1385     // Create a new buffer object
1386     GLuint buffer;
1387     glGenBuffers(1, &buffer);
1388     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
1389     glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
1390 
1391     // Use the GPU to copy the data from the old object to the new object,
1392     glBindBuffer(GL_COPY_READ_BUFFER, m_buffer);
1393     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_ELEMENT_ARRAY_BUFFER, 0, 0, m_size);
1394     glDeleteBuffers(1, &m_buffer);
1395     glFlush(); // Needed to work around what appears to be a CP DMA issue in r600g
1396 
1397     // Map the new object and fill in the uninitialized section
1398     const GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
1399     uint16_t *map = (uint16_t *)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, m_size, size - m_size, access);
1400 
1401     const uint16_t index[] = {1, 0, 3, 3, 2, 1};
1402     for (int i = m_count; i < count; i++) {
1403         for (int j = 0; j < 6; j++) {
1404             *(map++) = i * 4 + index[j];
1405         }
1406     }
1407 
1408     glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
1409     m_buffer = buffer;
1410     m_count = count;
1411     m_size = size;
1412 }
1413 
1414 void IndexBuffer::bind()
1415 {
1416     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
1417 }
1418 
1419 // ------------------------------------------------------------------
1420 
1421 class BitRef
1422 {
1423 public:
1424     BitRef(uint32_t &bitfield, int bit)
1425         : m_bitfield(bitfield)
1426         , m_mask(1 << bit)
1427     {
1428     }
1429 
1430     void operator=(bool val)
1431     {
1432         if (val) {
1433             m_bitfield |= m_mask;
1434         } else {
1435             m_bitfield &= ~m_mask;
1436         }
1437     }
1438 
1439     operator bool() const
1440     {
1441         return m_bitfield & m_mask;
1442     }
1443 
1444 private:
1445     uint32_t &m_bitfield;
1446     int const m_mask;
1447 };
1448 
1449 // ------------------------------------------------------------------
1450 
1451 class Bitfield
1452 {
1453 public:
1454     Bitfield()
1455         : m_bitfield(0)
1456     {
1457     }
1458     Bitfield(uint32_t bits)
1459         : m_bitfield(bits)
1460     {
1461     }
1462 
1463     void set(int i)
1464     {
1465         m_bitfield |= (1 << i);
1466     }
1467     void clear(int i)
1468     {
1469         m_bitfield &= ~(1 << i);
1470     }
1471 
1472     BitRef operator[](int i)
1473     {
1474         return BitRef(m_bitfield, i);
1475     }
1476     operator uint32_t() const
1477     {
1478         return m_bitfield;
1479     }
1480 
1481 private:
1482     uint32_t m_bitfield;
1483 };
1484 
1485 // ------------------------------------------------------------------
1486 
1487 class BitfieldIterator
1488 {
1489 public:
1490     BitfieldIterator(uint32_t bitfield)
1491         : m_bitfield(bitfield)
1492     {
1493     }
1494 
1495     bool hasNext() const
1496     {
1497         return m_bitfield != 0;
1498     }
1499 
1500     int next()
1501     {
1502         const int bit = ffs(m_bitfield) - 1;
1503         m_bitfield ^= (1 << bit);
1504         return bit;
1505     }
1506 
1507 private:
1508     uint32_t m_bitfield;
1509 };
1510 
1511 // ------------------------------------------------------------------
1512 
1513 struct VertexAttrib
1514 {
1515     int size;
1516     GLenum type;
1517     int offset;
1518 };
1519 
1520 // ------------------------------------------------------------------
1521 
1522 struct BufferFence
1523 {
1524     GLsync sync;
1525     intptr_t nextEnd;
1526 
1527     bool signaled() const
1528     {
1529         GLint value;
1530         glGetSynciv(sync, GL_SYNC_STATUS, 1, nullptr, &value);
1531         return value == GL_SIGNALED;
1532     }
1533 };
1534 
1535 static void deleteAll(std::deque<BufferFence> &fences)
1536 {
1537     for (const BufferFence &fence : fences) {
1538         glDeleteSync(fence.sync);
1539     }
1540 
1541     fences.clear();
1542 }
1543 
1544 // ------------------------------------------------------------------
1545 
1546 template<size_t Count>
1547 struct FrameSizesArray
1548 {
1549 public:
1550     FrameSizesArray()
1551     {
1552         m_array.fill(0);
1553     }
1554 
1555     void push(size_t size)
1556     {
1557         m_array[m_index] = size;
1558         m_index = (m_index + 1) % Count;
1559     }
1560 
1561     size_t average() const
1562     {
1563         size_t sum = 0;
1564         for (size_t size : m_array) {
1565             sum += size;
1566         }
1567         return sum / Count;
1568     }
1569 
1570 private:
1571     std::array<size_t, Count> m_array;
1572     int m_index = 0;
1573 };
1574 
1575 //*********************************
1576 // GLVertexBufferPrivate
1577 //*********************************
1578 class GLVertexBufferPrivate
1579 {
1580 public:
1581     GLVertexBufferPrivate(GLVertexBuffer::UsageHint usageHint)
1582         : vertexCount(0)
1583         , persistent(false)
1584         , useColor(false)
1585         , color(0, 0, 0, 255)
1586         , bufferSize(0)
1587         , bufferEnd(0)
1588         , mappedSize(0)
1589         , frameSize(0)
1590         , nextOffset(0)
1591         , baseAddress(0)
1592         , map(nullptr)
1593     {
1594         glGenBuffers(1, &buffer);
1595 
1596         switch (usageHint) {
1597         case GLVertexBuffer::Dynamic:
1598             usage = GL_DYNAMIC_DRAW;
1599             break;
1600         case GLVertexBuffer::Static:
1601             usage = GL_STATIC_DRAW;
1602             break;
1603         default:
1604             usage = GL_STREAM_DRAW;
1605             break;
1606         }
1607     }
1608 
1609     ~GLVertexBufferPrivate()
1610     {
1611         deleteAll(fences);
1612 
1613         if (buffer != 0) {
1614             glDeleteBuffers(1, &buffer);
1615             map = nullptr;
1616         }
1617     }
1618 
1619     void interleaveArrays(float *array, int dim, const float *vertices, const float *texcoords, int count);
1620     void bindArrays();
1621     void unbindArrays();
1622     void reallocateBuffer(size_t size);
1623     GLvoid *mapNextFreeRange(size_t size);
1624     void reallocatePersistentBuffer(size_t size);
1625     bool awaitFence(intptr_t offset);
1626     GLvoid *getIdleRange(size_t size);
1627 
1628     GLuint buffer;
1629     GLenum usage;
1630     int stride;
1631     int vertexCount;
1632     static std::unique_ptr<GLVertexBuffer> streamingBuffer;
1633     static bool haveBufferStorage;
1634     static bool haveSyncFences;
1635     static bool hasMapBufferRange;
1636     static bool supportsIndexedQuads;
1637     QByteArray dataStore;
1638     bool persistent;
1639     bool useColor;
1640     QVector4D color;
1641     size_t bufferSize;
1642     intptr_t bufferEnd;
1643     size_t mappedSize;
1644     size_t frameSize;
1645     intptr_t nextOffset;
1646     intptr_t baseAddress;
1647     uint8_t *map;
1648     std::deque<BufferFence> fences;
1649     FrameSizesArray<4> frameSizes;
1650     VertexAttrib attrib[VertexAttributeCount];
1651     Bitfield enabledArrays;
1652     static std::unique_ptr<IndexBuffer> s_indexBuffer;
1653 };
1654 
1655 bool GLVertexBufferPrivate::hasMapBufferRange = false;
1656 bool GLVertexBufferPrivate::supportsIndexedQuads = false;
1657 std::unique_ptr<GLVertexBuffer> GLVertexBufferPrivate::streamingBuffer;
1658 bool GLVertexBufferPrivate::haveBufferStorage = false;
1659 bool GLVertexBufferPrivate::haveSyncFences = false;
1660 std::unique_ptr<IndexBuffer> GLVertexBufferPrivate::s_indexBuffer;
1661 
1662 void GLVertexBufferPrivate::interleaveArrays(float *dst, int dim,
1663                                              const float *vertices, const float *texcoords,
1664                                              int count)
1665 {
1666     if (!texcoords) {
1667         memcpy((void *)dst, vertices, dim * sizeof(float) * count);
1668         return;
1669     }
1670 
1671     switch (dim) {
1672     case 2:
1673         for (int i = 0; i < count; i++) {
1674             *(dst++) = *(vertices++);
1675             *(dst++) = *(vertices++);
1676             *(dst++) = *(texcoords++);
1677             *(dst++) = *(texcoords++);
1678         }
1679         break;
1680 
1681     case 3:
1682         for (int i = 0; i < count; i++) {
1683             *(dst++) = *(vertices++);
1684             *(dst++) = *(vertices++);
1685             *(dst++) = *(vertices++);
1686             *(dst++) = *(texcoords++);
1687             *(dst++) = *(texcoords++);
1688         }
1689         break;
1690 
1691     default:
1692         for (int i = 0; i < count; i++) {
1693             for (int j = 0; j < dim; j++) {
1694                 *(dst++) = *(vertices++);
1695             }
1696 
1697             *(dst++) = *(texcoords++);
1698             *(dst++) = *(texcoords++);
1699         }
1700     }
1701 }
1702 
1703 void GLVertexBufferPrivate::bindArrays()
1704 {
1705     if (useColor) {
1706         GLShader *shader = ShaderManager::instance()->getBoundShader();
1707         shader->setUniform(GLShader::Color, color);
1708     }
1709 
1710     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1711 
1712     BitfieldIterator it(enabledArrays);
1713     while (it.hasNext()) {
1714         const int index = it.next();
1715         glVertexAttribPointer(index, attrib[index].size, attrib[index].type, GL_FALSE, stride,
1716                               (const GLvoid *)(baseAddress + attrib[index].offset));
1717         glEnableVertexAttribArray(index);
1718     }
1719 }
1720 
1721 void GLVertexBufferPrivate::unbindArrays()
1722 {
1723     BitfieldIterator it(enabledArrays);
1724     while (it.hasNext()) {
1725         glDisableVertexAttribArray(it.next());
1726     }
1727 }
1728 
1729 void GLVertexBufferPrivate::reallocatePersistentBuffer(size_t size)
1730 {
1731     if (buffer != 0) {
1732         // This also unmaps and unbinds the buffer
1733         glDeleteBuffers(1, &buffer);
1734         buffer = 0;
1735 
1736         deleteAll(fences);
1737     }
1738 
1739     if (buffer == 0) {
1740         glGenBuffers(1, &buffer);
1741     }
1742 
1743     // Round the size up to 64 kb
1744     size_t minSize = std::max<size_t>(frameSizes.average() * 3, 128 * 1024);
1745     bufferSize = std::max(size, minSize);
1746 
1747     const GLbitfield storage = GL_DYNAMIC_STORAGE_BIT;
1748     const GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
1749 
1750     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1751     glBufferStorage(GL_ARRAY_BUFFER, bufferSize, nullptr, storage | access);
1752 
1753     map = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, bufferSize, access);
1754 
1755     nextOffset = 0;
1756     bufferEnd = bufferSize;
1757 }
1758 
1759 bool GLVertexBufferPrivate::awaitFence(intptr_t end)
1760 {
1761     // Skip fences until we reach the end offset
1762     while (!fences.empty() && fences.front().nextEnd < end) {
1763         glDeleteSync(fences.front().sync);
1764         fences.pop_front();
1765     }
1766 
1767     Q_ASSERT(!fences.empty());
1768 
1769     // Wait on the next fence
1770     const BufferFence &fence = fences.front();
1771 
1772     if (!fence.signaled()) {
1773         qCDebug(LIBKWINGLUTILS) << "Stalling on VBO fence";
1774         const GLenum ret = glClientWaitSync(fence.sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000000);
1775 
1776         if (ret == GL_TIMEOUT_EXPIRED || ret == GL_WAIT_FAILED) {
1777             qCCritical(LIBKWINGLUTILS) << "Wait failed";
1778             return false;
1779         }
1780     }
1781 
1782     glDeleteSync(fence.sync);
1783 
1784     // Update the end pointer
1785     bufferEnd = fence.nextEnd;
1786     fences.pop_front();
1787 
1788     return true;
1789 }
1790 
1791 GLvoid *GLVertexBufferPrivate::getIdleRange(size_t size)
1792 {
1793     if (unlikely(size > bufferSize)) {
1794         reallocatePersistentBuffer(size * 2);
1795     }
1796 
1797     // Handle wrap-around
1798     if (unlikely(nextOffset + size > bufferSize)) {
1799         nextOffset = 0;
1800         bufferEnd -= bufferSize;
1801 
1802         for (BufferFence &fence : fences) {
1803             fence.nextEnd -= bufferSize;
1804         }
1805 
1806         // Emit a fence now
1807         if (auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)) {
1808             fences.push_back(BufferFence{
1809                 .sync = sync,
1810                 .nextEnd = intptr_t(bufferSize)});
1811         }
1812     }
1813 
1814     if (unlikely(nextOffset + intptr_t(size) > bufferEnd)) {
1815         if (!awaitFence(nextOffset + size)) {
1816             return nullptr;
1817         }
1818     }
1819 
1820     return map + nextOffset;
1821 }
1822 
1823 void GLVertexBufferPrivate::reallocateBuffer(size_t size)
1824 {
1825     // Round the size up to 4 Kb for streaming/dynamic buffers.
1826     const size_t minSize = 32768; // Minimum size for streaming buffers
1827     const size_t alloc = usage != GL_STATIC_DRAW ? std::max(size, minSize) : size;
1828 
1829     glBufferData(GL_ARRAY_BUFFER, alloc, nullptr, usage);
1830 
1831     bufferSize = alloc;
1832 }
1833 
1834 GLvoid *GLVertexBufferPrivate::mapNextFreeRange(size_t size)
1835 {
1836     GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
1837 
1838     if ((nextOffset + size) > bufferSize) {
1839         // Reallocate the data store if it's too small.
1840         if (size > bufferSize) {
1841             reallocateBuffer(size);
1842         } else {
1843             access |= GL_MAP_INVALIDATE_BUFFER_BIT;
1844             access ^= GL_MAP_UNSYNCHRONIZED_BIT;
1845         }
1846 
1847         nextOffset = 0;
1848     }
1849 
1850     return glMapBufferRange(GL_ARRAY_BUFFER, nextOffset, size, access);
1851 }
1852 
1853 //*********************************
1854 // GLVertexBuffer
1855 //*********************************
1856 
1857 const GLVertexAttrib GLVertexBuffer::GLVertex2DLayout[2] = {
1858     {VA_Position, 2, GL_FLOAT, offsetof(GLVertex2D, position)},
1859     {VA_TexCoord, 2, GL_FLOAT, offsetof(GLVertex2D, texcoord)},
1860 };
1861 
1862 const GLVertexAttrib GLVertexBuffer::GLVertex3DLayout[2] = {
1863     {VA_Position, 3, GL_FLOAT, offsetof(GLVertex3D, position)},
1864     {VA_TexCoord, 2, GL_FLOAT, offsetof(GLVertex3D, texcoord)},
1865 };
1866 
1867 GLVertexBuffer::GLVertexBuffer(UsageHint hint)
1868     : d(std::make_unique<GLVertexBufferPrivate>(hint))
1869 {
1870 }
1871 
1872 GLVertexBuffer::~GLVertexBuffer() = default;
1873 
1874 void GLVertexBuffer::setData(const void *data, size_t size)
1875 {
1876     GLvoid *ptr = map(size);
1877     memcpy(ptr, data, size);
1878     unmap();
1879 }
1880 
1881 void GLVertexBuffer::setData(int vertexCount, int dim, const float *vertices, const float *texcoords)
1882 {
1883     const GLVertexAttrib layout[] = {
1884         {VA_Position, dim, GL_FLOAT, 0},
1885         {VA_TexCoord, 2, GL_FLOAT, int(dim * sizeof(float))}};
1886 
1887     int stride = (texcoords ? dim + 2 : dim) * sizeof(float);
1888     int attribCount = texcoords ? 2 : 1;
1889 
1890     setAttribLayout(layout, attribCount, stride);
1891     setVertexCount(vertexCount);
1892 
1893     GLvoid *ptr = map(vertexCount * stride);
1894     d->interleaveArrays((float *)ptr, dim, vertices, texcoords, vertexCount);
1895     unmap();
1896 }
1897 
1898 GLvoid *GLVertexBuffer::map(size_t size)
1899 {
1900     d->mappedSize = size;
1901     d->frameSize += size;
1902 
1903     if (d->persistent) {
1904         return d->getIdleRange(size);
1905     }
1906 
1907     glBindBuffer(GL_ARRAY_BUFFER, d->buffer);
1908 
1909     bool preferBufferSubData = GLPlatform::instance()->preferBufferSubData();
1910 
1911     if (GLVertexBufferPrivate::hasMapBufferRange && !preferBufferSubData) {
1912         return (GLvoid *)d->mapNextFreeRange(size);
1913     }
1914 
1915     // If we can't map the buffer we allocate local memory to hold the
1916     // buffer data and return a pointer to it.  The data will be submitted
1917     // to the actual buffer object when the user calls unmap().
1918     if (size_t(d->dataStore.size()) < size) {
1919         d->dataStore.resize(size);
1920     }
1921 
1922     return (GLvoid *)d->dataStore.data();
1923 }
1924 
1925 void GLVertexBuffer::unmap()
1926 {
1927     if (d->persistent) {
1928         d->baseAddress = d->nextOffset;
1929         d->nextOffset += align(d->mappedSize, 8);
1930         d->mappedSize = 0;
1931         return;
1932     }
1933 
1934     bool preferBufferSubData = GLPlatform::instance()->preferBufferSubData();
1935 
1936     if (GLVertexBufferPrivate::hasMapBufferRange && !preferBufferSubData) {
1937         glUnmapBuffer(GL_ARRAY_BUFFER);
1938 
1939         d->baseAddress = d->nextOffset;
1940         d->nextOffset += align(d->mappedSize, 8);
1941     } else {
1942         // Upload the data from local memory to the buffer object
1943         if (preferBufferSubData) {
1944             if ((d->nextOffset + d->mappedSize) > d->bufferSize) {
1945                 d->reallocateBuffer(d->mappedSize);
1946                 d->nextOffset = 0;
1947             }
1948 
1949             glBufferSubData(GL_ARRAY_BUFFER, d->nextOffset, d->mappedSize, d->dataStore.constData());
1950 
1951             d->baseAddress = d->nextOffset;
1952             d->nextOffset += align(d->mappedSize, 8);
1953         } else {
1954             glBufferData(GL_ARRAY_BUFFER, d->mappedSize, d->dataStore.data(), d->usage);
1955             d->baseAddress = 0;
1956         }
1957 
1958         // Free the local memory buffer if it's unlikely to be used again
1959         if (d->usage == GL_STATIC_DRAW) {
1960             d->dataStore = QByteArray();
1961         }
1962     }
1963 
1964     d->mappedSize = 0;
1965 }
1966 
1967 void GLVertexBuffer::setVertexCount(int count)
1968 {
1969     d->vertexCount = count;
1970 }
1971 
1972 void GLVertexBuffer::setAttribLayout(const GLVertexAttrib *attribs, int count, int stride)
1973 {
1974     // Start by disabling all arrays
1975     d->enabledArrays = 0;
1976 
1977     for (int i = 0; i < count; i++) {
1978         const int index = attribs[i].index;
1979 
1980         Q_ASSERT(index >= 0 && index < VertexAttributeCount);
1981         Q_ASSERT(!d->enabledArrays[index]);
1982 
1983         d->attrib[index].size = attribs[i].size;
1984         d->attrib[index].type = attribs[i].type;
1985         d->attrib[index].offset = attribs[i].relativeOffset;
1986 
1987         d->enabledArrays[index] = true;
1988     }
1989 
1990     d->stride = stride;
1991 }
1992 
1993 void GLVertexBuffer::render(GLenum primitiveMode)
1994 {
1995     render(infiniteRegion(), primitiveMode, false);
1996 }
1997 
1998 void GLVertexBuffer::render(const QRegion &region, GLenum primitiveMode, bool hardwareClipping)
1999 {
2000     d->bindArrays();
2001     draw(region, primitiveMode, 0, d->vertexCount, hardwareClipping);
2002     d->unbindArrays();
2003 }
2004 
2005 void GLVertexBuffer::bindArrays()
2006 {
2007     d->bindArrays();
2008 }
2009 
2010 void GLVertexBuffer::unbindArrays()
2011 {
2012     d->unbindArrays();
2013 }
2014 
2015 void GLVertexBuffer::draw(GLenum primitiveMode, int first, int count)
2016 {
2017     draw(infiniteRegion(), primitiveMode, first, count, false);
2018 }
2019 
2020 void GLVertexBuffer::draw(const QRegion &region, GLenum primitiveMode, int first, int count, bool hardwareClipping)
2021 {
2022     if (primitiveMode == GL_QUADS) {
2023         if (!GLVertexBufferPrivate::s_indexBuffer) {
2024             GLVertexBufferPrivate::s_indexBuffer = std::make_unique<IndexBuffer>();
2025         }
2026 
2027         GLVertexBufferPrivate::s_indexBuffer->bind();
2028         GLVertexBufferPrivate::s_indexBuffer->accommodate(count / 4);
2029 
2030         count = count * 6 / 4;
2031 
2032         if (!hardwareClipping) {
2033             glDrawElementsBaseVertex(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, nullptr, first);
2034         } else {
2035             // Clip using scissoring
2036             const GLFramebuffer *current = GLFramebuffer::currentFramebuffer();
2037             for (const QRect &r : region) {
2038                 glScissor(r.x(), current->size().height() - (r.y() + r.height()), r.width(), r.height());
2039                 glDrawElementsBaseVertex(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, nullptr, first);
2040             }
2041         }
2042         return;
2043     }
2044 
2045     if (!hardwareClipping) {
2046         glDrawArrays(primitiveMode, first, count);
2047     } else {
2048         // Clip using scissoring
2049         const GLFramebuffer *current = GLFramebuffer::currentFramebuffer();
2050         for (const QRect &r : region) {
2051             glScissor(r.x(), current->size().height() - (r.y() + r.height()), r.width(), r.height());
2052             glDrawArrays(primitiveMode, first, count);
2053         }
2054     }
2055 }
2056 
2057 bool GLVertexBuffer::supportsIndexedQuads()
2058 {
2059     return GLVertexBufferPrivate::supportsIndexedQuads;
2060 }
2061 
2062 bool GLVertexBuffer::isUseColor() const
2063 {
2064     return d->useColor;
2065 }
2066 
2067 void GLVertexBuffer::setUseColor(bool enable)
2068 {
2069     d->useColor = enable;
2070 }
2071 
2072 void GLVertexBuffer::setColor(const QColor &color, bool enable)
2073 {
2074     d->useColor = enable;
2075     d->color = QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF());
2076 }
2077 
2078 void GLVertexBuffer::reset()
2079 {
2080     d->useColor = false;
2081     d->color = QVector4D(0, 0, 0, 1);
2082     d->vertexCount = 0;
2083 }
2084 
2085 void GLVertexBuffer::endOfFrame()
2086 {
2087     if (!d->persistent) {
2088         return;
2089     }
2090 
2091     // Emit a fence if we have uploaded data
2092     if (d->frameSize > 0) {
2093         d->frameSizes.push(d->frameSize);
2094         d->frameSize = 0;
2095 
2096         // Force the buffer to be reallocated at the beginning of the next frame
2097         // if the average frame size is greater than half the size of the buffer
2098         if (unlikely(d->frameSizes.average() > d->bufferSize / 2)) {
2099             deleteAll(d->fences);
2100             glDeleteBuffers(1, &d->buffer);
2101 
2102             d->buffer = 0;
2103             d->bufferSize = 0;
2104             d->nextOffset = 0;
2105             d->map = nullptr;
2106         } else {
2107             if (auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)) {
2108                 d->fences.push_back(BufferFence{
2109                     .sync = sync,
2110                     .nextEnd = intptr_t(d->nextOffset + d->bufferSize)});
2111             }
2112         }
2113     }
2114 }
2115 
2116 void GLVertexBuffer::beginFrame()
2117 {
2118     if (!d->persistent) {
2119         return;
2120     }
2121 
2122     // Remove finished fences from the list and update the bufferEnd offset
2123     while (d->fences.size() > 1 && d->fences.front().signaled()) {
2124         const BufferFence &fence = d->fences.front();
2125         glDeleteSync(fence.sync);
2126 
2127         d->bufferEnd = fence.nextEnd;
2128         d->fences.pop_front();
2129     }
2130 }
2131 
2132 void GLVertexBuffer::initStatic()
2133 {
2134     if (GLPlatform::instance()->isGLES()) {
2135         bool haveBaseVertex = hasGLExtension(QByteArrayLiteral("GL_OES_draw_elements_base_vertex"));
2136         bool haveCopyBuffer = hasGLVersion(3, 0);
2137         bool haveMapBufferRange = hasGLExtension(QByteArrayLiteral("GL_EXT_map_buffer_range"));
2138 
2139         GLVertexBufferPrivate::hasMapBufferRange = haveMapBufferRange;
2140         GLVertexBufferPrivate::supportsIndexedQuads = haveBaseVertex && haveCopyBuffer && haveMapBufferRange;
2141         GLVertexBufferPrivate::haveBufferStorage = hasGLExtension("GL_EXT_buffer_storage");
2142         GLVertexBufferPrivate::haveSyncFences = hasGLVersion(3, 0);
2143     } else {
2144         bool haveBaseVertex = hasGLVersion(3, 2) || hasGLExtension(QByteArrayLiteral("GL_ARB_draw_elements_base_vertex"));
2145         bool haveCopyBuffer = hasGLVersion(3, 1) || hasGLExtension(QByteArrayLiteral("GL_ARB_copy_buffer"));
2146         bool haveMapBufferRange = hasGLVersion(3, 0) || hasGLExtension(QByteArrayLiteral("GL_ARB_map_buffer_range"));
2147 
2148         GLVertexBufferPrivate::hasMapBufferRange = haveMapBufferRange;
2149         GLVertexBufferPrivate::supportsIndexedQuads = haveBaseVertex && haveCopyBuffer && haveMapBufferRange;
2150         GLVertexBufferPrivate::haveBufferStorage = hasGLVersion(4, 4) || hasGLExtension("GL_ARB_buffer_storage");
2151         GLVertexBufferPrivate::haveSyncFences = hasGLVersion(3, 2) || hasGLExtension("GL_ARB_sync");
2152     }
2153     GLVertexBufferPrivate::s_indexBuffer.reset();
2154     GLVertexBufferPrivate::streamingBuffer = std::make_unique<GLVertexBuffer>(GLVertexBuffer::Stream);
2155 
2156     if (GLVertexBufferPrivate::haveBufferStorage && GLVertexBufferPrivate::haveSyncFences) {
2157         if (qgetenv("KWIN_PERSISTENT_VBO") != QByteArrayLiteral("0")) {
2158             GLVertexBufferPrivate::streamingBuffer->d->persistent = true;
2159         }
2160     }
2161 }
2162 
2163 void GLVertexBuffer::cleanup()
2164 {
2165     GLVertexBufferPrivate::s_indexBuffer.reset();
2166     GLVertexBufferPrivate::hasMapBufferRange = false;
2167     GLVertexBufferPrivate::supportsIndexedQuads = false;
2168     GLVertexBufferPrivate::streamingBuffer.reset();
2169 }
2170 
2171 GLVertexBuffer *GLVertexBuffer::streamingBuffer()
2172 {
2173     return GLVertexBufferPrivate::streamingBuffer.get();
2174 }
2175 
2176 } // namespace