File indexing completed on 2024-11-10 04:56:56

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2023 Xaver Hugl <xaver.hugl@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "openglcontext.h"
0010 
0011 #include <QByteArray>
0012 #include <QList>
0013 
0014 #include <epoxy/gl.h>
0015 
0016 namespace KWin
0017 {
0018 
0019 static QSet<QByteArray> getExtensions(OpenGlContext *context)
0020 {
0021     QSet<QByteArray> ret;
0022     if (!context->isOpenglES() && context->hasVersion(Version(3, 0))) {
0023         int count;
0024         glGetIntegerv(GL_NUM_EXTENSIONS, &count);
0025 
0026         for (int i = 0; i < count; i++) {
0027             const char *name = (const char *)glGetStringi(GL_EXTENSIONS, i);
0028             ret.insert(name);
0029         }
0030     } else {
0031         const QByteArray extensions = (const char *)glGetString(GL_EXTENSIONS);
0032         QList<QByteArray> extensionsList = extensions.split(' ');
0033         ret = {extensionsList.constBegin(), extensionsList.constEnd()};
0034     }
0035     return ret;
0036 }
0037 
0038 OpenGlContext::OpenGlContext()
0039     : m_versionString((const char *)glGetString(GL_VERSION))
0040     , m_version(Version::parseString(m_versionString))
0041     , m_vendor((const char *)glGetString(GL_VENDOR))
0042     , m_renderer((const char *)glGetString(GL_RENDERER))
0043     , m_isOpenglES(m_versionString.startsWith("OpenGL ES"))
0044     , m_extensions(getExtensions(this))
0045     , m_supportsTimerQueries(checkTimerQuerySupport())
0046 {
0047 }
0048 
0049 bool OpenGlContext::checkTimerQuerySupport() const
0050 {
0051     if (qEnvironmentVariableIsSet("KWIN_NO_TIMER_QUERY")) {
0052         return false;
0053     }
0054     if (m_isOpenglES) {
0055         // 3.0 is required so query functions can be used without "EXT" suffix.
0056         // Timer queries are still not part of the core OpenGL ES specification.
0057         return openglVersion() >= Version(3, 0) && hasOpenglExtension("GL_EXT_disjoint_timer_query");
0058     } else {
0059         return openglVersion() >= Version(3, 3) || hasOpenglExtension("GL_ARB_timer_query");
0060     }
0061 }
0062 
0063 bool OpenGlContext::hasVersion(const Version &version) const
0064 {
0065     return m_version >= version;
0066 }
0067 
0068 QByteArrayView OpenGlContext::openglVersionString() const
0069 {
0070     return m_versionString;
0071 }
0072 
0073 Version OpenGlContext::openglVersion() const
0074 {
0075     return m_version;
0076 }
0077 
0078 QByteArrayView OpenGlContext::vendor() const
0079 {
0080     return m_vendor;
0081 }
0082 
0083 QByteArrayView OpenGlContext::renderer() const
0084 {
0085     return m_renderer;
0086 }
0087 
0088 bool OpenGlContext::isOpenglES() const
0089 {
0090     return m_isOpenglES;
0091 }
0092 
0093 bool OpenGlContext::hasOpenglExtension(QByteArrayView name) const
0094 {
0095     return std::any_of(m_extensions.cbegin(), m_extensions.cend(), [name](const auto &string) {
0096         return string == name;
0097     });
0098 }
0099 
0100 bool OpenGlContext::isSoftwareRenderer() const
0101 {
0102     return m_renderer.contains("softpipe") || m_renderer.contains("Software Rasterizer") || m_renderer.contains("llvmpipe");
0103 }
0104 
0105 bool OpenGlContext::supportsTimerQueries() const
0106 {
0107     return m_supportsTimerQueries;
0108 }
0109 
0110 bool OpenGlContext::checkSupported() const
0111 {
0112     const bool supportsGLSL = m_isOpenglES || (hasOpenglExtension("GL_ARB_shader_objects") && hasOpenglExtension("GL_ARB_fragment_shader") && hasOpenglExtension("GL_ARB_vertex_shader"));
0113     const bool supportsNonPowerOfTwoTextures = m_isOpenglES || hasOpenglExtension("GL_ARB_texture_non_power_of_two");
0114     const bool supports3DTextures = !m_isOpenglES || hasVersion(Version(3, 0)) || hasOpenglExtension("GL_OES_texture_3D");
0115     return supportsGLSL && supportsNonPowerOfTwoTextures && supports3DTextures;
0116 }
0117 }