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 }