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

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2010 Fredrik Höglund <fredrik@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "kwinglplatform.h"
0011 // include kwinglutils_funcs.h to avoid the redeclaration issues
0012 // between qopengl.h and epoxy/gl.h
0013 #include "kwinglutils_funcs.h"
0014 #include <epoxy/gl.h>
0015 
0016 #include <QDebug>
0017 #include <QOpenGLContext>
0018 #include <QRegularExpression>
0019 #include <QStringList>
0020 
0021 #include <sys/utsname.h>
0022 
0023 #include <iomanip>
0024 #include <ios>
0025 #include <iostream>
0026 
0027 namespace KWin
0028 {
0029 
0030 std::unique_ptr<GLPlatform> GLPlatform::s_platform;
0031 
0032 static qint64 parseVersionString(const QByteArray &version)
0033 {
0034     // Skip any leading non digit
0035     int start = 0;
0036     while (start < version.length() && !QChar::fromLatin1(version[start]).isDigit()) {
0037         start++;
0038     }
0039 
0040     // Strip any non digit, non '.' characters from the end
0041     int end = start;
0042     while (end < version.length() && (version[end] == '.' || QChar::fromLatin1(version[end]).isDigit())) {
0043         end++;
0044     }
0045 
0046     const QByteArray result = version.mid(start, end - start);
0047     const QList<QByteArray> tokens = result.split('.');
0048     const qint64 major = tokens.at(0).toInt();
0049     const qint64 minor = tokens.count() > 1 ? tokens.at(1).toInt() : 0;
0050     const qint64 patch = tokens.count() > 2 ? tokens.at(2).toInt() : 0;
0051 
0052     return kVersionNumber(major, minor, patch);
0053 }
0054 
0055 static qint64 getXServerVersion()
0056 {
0057     qint64 major, minor, patch;
0058     major = 0;
0059     minor = 0;
0060     patch = 0;
0061 
0062     if (xcb_connection_t *c = connection()) {
0063         auto setup = xcb_get_setup(c);
0064         const QByteArray vendorName(xcb_setup_vendor(setup), xcb_setup_vendor_length(setup));
0065         if (vendorName.contains("X.Org")) {
0066             const int release = setup->release_number;
0067             major = (release / 10000000);
0068             minor = (release / 100000) % 100;
0069             patch = (release / 1000) % 100;
0070         }
0071     }
0072 
0073     return kVersionNumber(major, minor, patch);
0074 }
0075 
0076 static qint64 getKernelVersion()
0077 {
0078     struct utsname name;
0079     uname(&name);
0080 
0081     if (qstrcmp(name.sysname, "Linux") == 0) {
0082         return parseVersionString(name.release);
0083     }
0084 
0085     return 0;
0086 }
0087 
0088 // Extracts the portion of a string that matches a regular expression
0089 static QString extract(const QString &text, const QString &pattern)
0090 {
0091     const QRegularExpression regexp(pattern);
0092     const QRegularExpressionMatch match = regexp.match(text);
0093     if (!match.hasMatch()) {
0094         return QString();
0095     }
0096     return match.captured();
0097 }
0098 
0099 static ChipClass detectRadeonClass(const QByteArray &chipset)
0100 {
0101     if (chipset.isEmpty()) {
0102         return UnknownRadeon;
0103     }
0104 
0105     if (chipset.contains("R100")
0106         || chipset.contains("RV100")
0107         || chipset.contains("RS100")) {
0108         return R100;
0109     }
0110 
0111     if (chipset.contains("RV200")
0112         || chipset.contains("RS200")
0113         || chipset.contains("R200")
0114         || chipset.contains("RV250")
0115         || chipset.contains("RS300")
0116         || chipset.contains("RV280")) {
0117         return R200;
0118     }
0119 
0120     if (chipset.contains("R300")
0121         || chipset.contains("R350")
0122         || chipset.contains("R360")
0123         || chipset.contains("RV350")
0124         || chipset.contains("RV370")
0125         || chipset.contains("RV380")) {
0126         return R300;
0127     }
0128 
0129     if (chipset.contains("R420")
0130         || chipset.contains("R423")
0131         || chipset.contains("R430")
0132         || chipset.contains("R480")
0133         || chipset.contains("R481")
0134         || chipset.contains("RV410")
0135         || chipset.contains("RS400")
0136         || chipset.contains("RC410")
0137         || chipset.contains("RS480")
0138         || chipset.contains("RS482")
0139         || chipset.contains("RS600")
0140         || chipset.contains("RS690")
0141         || chipset.contains("RS740")) {
0142         return R400;
0143     }
0144 
0145     if (chipset.contains("RV515")
0146         || chipset.contains("R520")
0147         || chipset.contains("RV530")
0148         || chipset.contains("R580")
0149         || chipset.contains("RV560")
0150         || chipset.contains("RV570")) {
0151         return R500;
0152     }
0153 
0154     if (chipset.contains("R600")
0155         || chipset.contains("RV610")
0156         || chipset.contains("RV630")
0157         || chipset.contains("RV670")
0158         || chipset.contains("RV620")
0159         || chipset.contains("RV635")
0160         || chipset.contains("RS780")
0161         || chipset.contains("RS880")) {
0162         return R600;
0163     }
0164 
0165     if (chipset.contains("R700")
0166         || chipset.contains("RV770")
0167         || chipset.contains("RV730")
0168         || chipset.contains("RV710")
0169         || chipset.contains("RV740")) {
0170         return R700;
0171     }
0172 
0173     if (chipset.contains("EVERGREEN") // Not an actual chipset, but returned by R600G in 7.9
0174         || chipset.contains("CEDAR")
0175         || chipset.contains("REDWOOD")
0176         || chipset.contains("JUNIPER")
0177         || chipset.contains("CYPRESS")
0178         || chipset.contains("HEMLOCK")
0179         || chipset.contains("PALM")) {
0180         return Evergreen;
0181     }
0182 
0183     if (chipset.contains("SUMO")
0184         || chipset.contains("SUMO2")
0185         || chipset.contains("BARTS")
0186         || chipset.contains("TURKS")
0187         || chipset.contains("CAICOS")
0188         || chipset.contains("CAYMAN")) {
0189         return NorthernIslands;
0190     }
0191 
0192     if (chipset.contains("TAHITI")
0193         || chipset.contains("PITCAIRN")
0194         || chipset.contains("VERDE")
0195         || chipset.contains("OLAND")
0196         || chipset.contains("HAINAN")) {
0197         return SouthernIslands;
0198     }
0199 
0200     if (chipset.contains("BONAIRE")
0201         || chipset.contains("KAVERI")
0202         || chipset.contains("KABINI")
0203         || chipset.contains("HAWAII")
0204         || chipset.contains("MULLINS")) {
0205         return SeaIslands;
0206     }
0207 
0208     if (chipset.contains("TONGA")
0209         || chipset.contains("TOPAZ")
0210         || chipset.contains("FIJI")
0211         || chipset.contains("CARRIZO")
0212         || chipset.contains("STONEY")) {
0213         return VolcanicIslands;
0214     }
0215 
0216     if (chipset.contains("POLARIS10")
0217         || chipset.contains("POLARIS11")
0218         || chipset.contains("POLARIS12")
0219         || chipset.contains("VEGAM")) {
0220         return ArcticIslands;
0221     }
0222 
0223     if (chipset.contains("VEGA10")
0224         || chipset.contains("VEGA12")
0225         || chipset.contains("VEGA20")
0226         || chipset.contains("RAVEN")
0227         || chipset.contains("RAVEN2")
0228         || chipset.contains("RENOIR")
0229         || chipset.contains("ARCTURUS")) {
0230         return Vega;
0231     }
0232 
0233     if (chipset.contains("NAVI10")
0234         || chipset.contains("NAVI12")
0235         || chipset.contains("NAVI14")) {
0236         return Navi;
0237     }
0238 
0239     const QString chipset16 = QString::fromLatin1(chipset);
0240     QString name = extract(chipset16, QStringLiteral("HD [0-9]{4}")); // HD followed by a space and 4 digits
0241     if (!name.isEmpty()) {
0242         const int id = QStringView(name).right(4).toInt();
0243         if (id == 6250 || id == 6310) { // Palm
0244             return Evergreen;
0245         }
0246 
0247         if (id >= 6000 && id < 7000) {
0248             return NorthernIslands; // HD 6xxx
0249         }
0250 
0251         if (id >= 5000 && id < 6000) {
0252             return Evergreen; // HD 5xxx
0253         }
0254 
0255         if (id >= 4000 && id < 5000) {
0256             return R700; // HD 4xxx
0257         }
0258 
0259         if (id >= 2000 && id < 4000) { // HD 2xxx/3xxx
0260             return R600;
0261         }
0262 
0263         return UnknownRadeon;
0264     }
0265 
0266     name = extract(chipset16, QStringLiteral("X[0-9]{3,4}")); // X followed by 3-4 digits
0267     if (!name.isEmpty()) {
0268         const int id = QStringView(name).mid(1, -1).toInt();
0269 
0270         // X1xxx
0271         if (id >= 1300) {
0272             return R500;
0273         }
0274 
0275         // X7xx, X8xx, X12xx, 2100
0276         if ((id >= 700 && id < 1000) || id >= 1200) {
0277             return R400;
0278         }
0279 
0280         // X200, X3xx, X5xx, X6xx, X10xx, X11xx
0281         if ((id >= 300 && id < 700) || (id >= 1000 && id < 1200)) {
0282             return R300;
0283         }
0284 
0285         return UnknownRadeon;
0286     }
0287 
0288     name = extract(chipset16, QStringLiteral("\\b[0-9]{4}\\b")); // A group of 4 digits
0289     if (!name.isEmpty()) {
0290         const int id = name.toInt();
0291 
0292         // 7xxx
0293         if (id >= 7000 && id < 8000) {
0294             return R100;
0295         }
0296 
0297         // 8xxx, 9xxx
0298         if (id >= 8000 && id < 9500) {
0299             return R200;
0300         }
0301 
0302         // 9xxx
0303         if (id >= 9500) {
0304             return R300;
0305         }
0306 
0307         if (id == 2100) {
0308             return R400;
0309         }
0310     }
0311 
0312     return UnknownRadeon;
0313 }
0314 
0315 static ChipClass detectNVidiaClass(const QString &chipset)
0316 {
0317     QString name = extract(chipset, QStringLiteral("\\bNV[0-9,A-F]{2}\\b")); // NV followed by two hexadecimal digits
0318     if (!name.isEmpty()) {
0319         const int id = QStringView(chipset).mid(2, -1).toInt(nullptr, 16); // Strip the 'NV' from the id
0320 
0321         switch (id & 0xf0) {
0322         case 0x00:
0323         case 0x10:
0324             return NV10;
0325 
0326         case 0x20:
0327             return NV20;
0328 
0329         case 0x30:
0330             return NV30;
0331 
0332         case 0x40:
0333         case 0x60:
0334             return NV40;
0335 
0336         case 0x50:
0337         case 0x80:
0338         case 0x90:
0339         case 0xA0:
0340             return G80;
0341 
0342         default:
0343             return UnknownNVidia;
0344         }
0345     }
0346 
0347     if (chipset.contains(QLatin1String("GeForce2")) || chipset.contains(QLatin1String("GeForce 256"))) {
0348         return NV10;
0349     }
0350 
0351     if (chipset.contains(QLatin1String("GeForce3"))) {
0352         return NV20;
0353     }
0354 
0355     if (chipset.contains(QLatin1String("GeForce4"))) {
0356         if (chipset.contains(QLatin1String("MX 420"))
0357             || chipset.contains(QLatin1String("MX 440")) // including MX 440SE
0358             || chipset.contains(QLatin1String("MX 460"))
0359             || chipset.contains(QLatin1String("MX 4000"))
0360             || chipset.contains(QLatin1String("PCX 4300"))) {
0361             return NV10;
0362         }
0363 
0364         return NV20;
0365     }
0366 
0367     // GeForce 5,6,7,8,9
0368     name = extract(chipset, QStringLiteral("GeForce (FX |PCX |Go )?\\d{4}(M|\\b)")).trimmed();
0369     if (!name.isEmpty()) {
0370         if (!name[name.length() - 1].isDigit()) {
0371             name.chop(1);
0372         }
0373 
0374         const int id = QStringView(name).right(4).toInt();
0375         if (id < 6000) {
0376             return NV30;
0377         }
0378 
0379         if (id >= 6000 && id < 8000) {
0380             return NV40;
0381         }
0382 
0383         if (id >= 8000) {
0384             return G80;
0385         }
0386 
0387         return UnknownNVidia;
0388     }
0389 
0390     // GeForce 100/200/300/400/500
0391     name = extract(chipset, QStringLiteral("GeForce (G |GT |GTX |GTS )?\\d{3}(M|\\b)")).trimmed();
0392     if (!name.isEmpty()) {
0393         if (!name[name.length() - 1].isDigit()) {
0394             name.chop(1);
0395         }
0396 
0397         const int id = QStringView(name).right(3).toInt();
0398         if (id >= 100 && id < 600) {
0399             if (id >= 400) {
0400                 return GF100;
0401             }
0402 
0403             return G80;
0404         }
0405         return UnknownNVidia;
0406     }
0407 
0408     return UnknownNVidia;
0409 }
0410 static inline ChipClass detectNVidiaClass(const QByteArray &chipset)
0411 {
0412     return detectNVidiaClass(QString::fromLatin1(chipset));
0413 }
0414 
0415 static ChipClass detectIntelClass(const QByteArray &chipset)
0416 {
0417     // see mesa repository: src/mesa/drivers/dri/intel/intel_context.c
0418     // GL 1.3, DX8? SM ?
0419     if (chipset.contains("845G")
0420         || chipset.contains("830M")
0421         || chipset.contains("852GM/855GM")
0422         || chipset.contains("865G")) {
0423         return I8XX;
0424     }
0425 
0426     // GL 1.4, DX 9.0, SM 2.0
0427     if (chipset.contains("915G")
0428         || chipset.contains("E7221G")
0429         || chipset.contains("915GM")
0430         || chipset.contains("945G") // DX 9.0c
0431         || chipset.contains("945GM")
0432         || chipset.contains("945GME")
0433         || chipset.contains("Q33") // GL1.5
0434         || chipset.contains("Q35")
0435         || chipset.contains("G33")
0436         || chipset.contains("965Q") // GMA 3000, but apparently considered gen 4 by the driver
0437         || chipset.contains("946GZ") // GMA 3000, but apparently considered gen 4 by the driver
0438         || chipset.contains("IGD")) {
0439         return I915;
0440     }
0441 
0442     // GL 2.0, DX 9.0c, SM 3.0
0443     if (chipset.contains("965G")
0444         || chipset.contains("G45/G43") // SM 4.0
0445         || chipset.contains("965GM") // GL 2.1
0446         || chipset.contains("965GME/GLE")
0447         || chipset.contains("GM45")
0448         || chipset.contains("Q45/Q43")
0449         || chipset.contains("G41")
0450         || chipset.contains("B43")
0451         || chipset.contains("Ironlake")) {
0452         return I965;
0453     }
0454 
0455     // GL 3.1, CL 1.1, DX 10.1
0456     if (chipset.contains("Sandybridge") || chipset.contains("SNB GT")) {
0457         return SandyBridge;
0458     }
0459 
0460     // GL4.0, CL1.1, DX11, SM 5.0
0461     if (chipset.contains("Ivybridge") || chipset.contains("IVB GT")) {
0462         return IvyBridge;
0463     }
0464 
0465     // GL4.0, CL1.2, DX11.1, SM 5.0
0466     if (chipset.contains("Haswell") || chipset.contains("HSW GT")) {
0467         return Haswell;
0468     }
0469     if (chipset.contains("BYT")) {
0470         return BayTrail;
0471     }
0472     if (chipset.contains("CHV") || chipset.contains("BSW")) {
0473         return Cherryview;
0474     }
0475     if (chipset.contains("BDW GT")) {
0476         return Broadwell;
0477     }
0478     if (chipset.contains("SKL GT")) {
0479         return Skylake;
0480     }
0481     if (chipset.contains("APL")) {
0482         return ApolloLake;
0483     }
0484     if (chipset.contains("KBL GT")) {
0485         return KabyLake;
0486     }
0487     if (chipset.contains("WHL GT")) {
0488         return WhiskeyLake;
0489     }
0490     if (chipset.contains("CML GT")) {
0491         return CometLake;
0492     }
0493     if (chipset.contains("CNL GT")) {
0494         return CannonLake;
0495     }
0496     if (chipset.contains("CFL GT")) {
0497         return CoffeeLake;
0498     }
0499     if (chipset.contains("ICL GT")) {
0500         return IceLake;
0501     }
0502     if (chipset.contains("TGL GT")) {
0503         return TigerLake;
0504     }
0505 
0506     return UnknownIntel;
0507 }
0508 
0509 static ChipClass detectQualcommClass(const QByteArray &chipClass)
0510 {
0511     if (!chipClass.contains("Adreno")) {
0512         return UnknownChipClass;
0513     }
0514     const auto parts = chipClass.split(' ');
0515     if (parts.count() < 3) {
0516         return UnknownAdreno;
0517     }
0518     bool ok = false;
0519     const int value = parts.at(2).toInt(&ok);
0520     if (ok) {
0521         if (value >= 100 && value < 200) {
0522             return Adreno1XX;
0523         } else if (value >= 200 && value < 300) {
0524             return Adreno2XX;
0525         } else if (value >= 300 && value < 400) {
0526             return Adreno3XX;
0527         } else if (value >= 400 && value < 500) {
0528             return Adreno4XX;
0529         } else if (value >= 500 && value < 600) {
0530             return Adreno5XX;
0531         }
0532     }
0533     return UnknownAdreno;
0534 }
0535 
0536 static ChipClass detectPanfrostClass(const QByteArray &chipClass)
0537 {
0538 // Keep the list of supported Mali chipset up to date with https://docs.mesa3d.org/drivers/panfrost.html
0539     if (chipClass.contains("T720") || chipClass.contains("T760")) {
0540         return MaliT7XX;
0541     }
0542 
0543     if (chipClass.contains("T820") || chipClass.contains("T830") || chipClass.contains("T860") || chipClass.contains("T880")) {
0544         return MaliT8XX;
0545     }
0546 
0547     if (chipClass.contains("G31") || chipClass.contains("G51") || chipClass.contains("G52") || chipClass.contains("G57") || chipClass.contains("G72") || chipClass.contains("G76")) {
0548         return MaliGXX;
0549     }
0550 
0551     return UnknownPanfrost;
0552 }
0553 
0554 static ChipClass detectLimaClass(const QByteArray &chipClass)
0555 {
0556     if (chipClass.contains("400")) {
0557         return Mali400;
0558     } else if (chipClass.contains("450")) {
0559         return Mali450;
0560     } else if (chipClass.contains("470")) {
0561         return Mali470;
0562     }
0563 
0564     return UnknownLima;
0565 }
0566 
0567 static ChipClass detectVC4Class(const QByteArray &chipClass)
0568 {
0569     if (chipClass.contains("2.1")) {
0570         return VC4_2_1;
0571     }
0572 
0573     return UnknownVideoCore4;
0574 }
0575 
0576 static ChipClass detectV3DClass(const QByteArray &chipClass)
0577 {
0578     if (chipClass.contains("4.2")) {
0579         return V3D_4_2;
0580     }
0581 
0582     return UnknownVideoCore3D;
0583 }
0584 
0585 QString GLPlatform::versionToString(qint64 version)
0586 {
0587     return QString::fromLatin1(versionToString8(version));
0588 }
0589 QByteArray GLPlatform::versionToString8(qint64 version)
0590 {
0591     int major = (version >> 32);
0592     int minor = (version >> 16) & 0xffff;
0593     int patch = version & 0xffff;
0594 
0595     QByteArray string = QByteArray::number(major) + '.' + QByteArray::number(minor);
0596     if (patch != 0) {
0597         string += '.' + QByteArray::number(patch);
0598     }
0599 
0600     return string;
0601 }
0602 
0603 QString GLPlatform::driverToString(Driver driver)
0604 {
0605     return QString::fromLatin1(driverToString8(driver));
0606 }
0607 QByteArray GLPlatform::driverToString8(Driver driver)
0608 {
0609     switch (driver) {
0610     case Driver_R100:
0611         return QByteArrayLiteral("Radeon");
0612     case Driver_R200:
0613         return QByteArrayLiteral("R200");
0614     case Driver_R300C:
0615         return QByteArrayLiteral("R300C");
0616     case Driver_R300G:
0617         return QByteArrayLiteral("R300G");
0618     case Driver_R600C:
0619         return QByteArrayLiteral("R600C");
0620     case Driver_R600G:
0621         return QByteArrayLiteral("R600G");
0622     case Driver_RadeonSI:
0623         return QByteArrayLiteral("RadeonSI");
0624     case Driver_Nouveau:
0625         return QByteArrayLiteral("Nouveau");
0626     case Driver_Intel:
0627         return QByteArrayLiteral("Intel");
0628     case Driver_NVidia:
0629         return QByteArrayLiteral("NVIDIA");
0630     case Driver_Catalyst:
0631         return QByteArrayLiteral("Catalyst");
0632     case Driver_Swrast:
0633         return QByteArrayLiteral("Software rasterizer");
0634     case Driver_Softpipe:
0635         return QByteArrayLiteral("softpipe");
0636     case Driver_Llvmpipe:
0637         return QByteArrayLiteral("LLVMpipe");
0638     case Driver_VirtualBox:
0639         return QByteArrayLiteral("VirtualBox (Chromium)");
0640     case Driver_VMware:
0641         return QByteArrayLiteral("VMware (SVGA3D)");
0642     case Driver_Qualcomm:
0643         return QByteArrayLiteral("Qualcomm");
0644     case Driver_Virgl:
0645         return QByteArrayLiteral("Virgl (virtio-gpu, Qemu/KVM guest)");
0646     case Driver_Panfrost:
0647         return QByteArrayLiteral("Panfrost");
0648     case Driver_Lima:
0649         return QByteArrayLiteral("Mali (Lima)");
0650     case Driver_VC4:
0651         return QByteArrayLiteral("VideoCore IV");
0652     case Driver_V3D:
0653         return QByteArrayLiteral("VideoCore 3D");
0654 
0655     default:
0656         return QByteArrayLiteral("Unknown");
0657     }
0658 }
0659 
0660 QString GLPlatform::chipClassToString(ChipClass chipClass)
0661 {
0662     return QString::fromLatin1(chipClassToString8(chipClass));
0663 }
0664 QByteArray GLPlatform::chipClassToString8(ChipClass chipClass)
0665 {
0666     switch (chipClass) {
0667     case R100:
0668         return QByteArrayLiteral("R100");
0669     case R200:
0670         return QByteArrayLiteral("R200");
0671     case R300:
0672         return QByteArrayLiteral("R300");
0673     case R400:
0674         return QByteArrayLiteral("R400");
0675     case R500:
0676         return QByteArrayLiteral("R500");
0677     case R600:
0678         return QByteArrayLiteral("R600");
0679     case R700:
0680         return QByteArrayLiteral("R700");
0681     case Evergreen:
0682         return QByteArrayLiteral("EVERGREEN");
0683     case NorthernIslands:
0684         return QByteArrayLiteral("Northern Islands");
0685     case SouthernIslands:
0686         return QByteArrayLiteral("Southern Islands");
0687     case SeaIslands:
0688         return QByteArrayLiteral("Sea Islands");
0689     case VolcanicIslands:
0690         return QByteArrayLiteral("Volcanic Islands");
0691     case ArcticIslands:
0692         return QByteArrayLiteral("Arctic Islands");
0693     case Vega:
0694         return QByteArrayLiteral("Vega");
0695     case Navi:
0696         return QByteArrayLiteral("Navi");
0697 
0698     case NV10:
0699         return QByteArrayLiteral("NV10");
0700     case NV20:
0701         return QByteArrayLiteral("NV20");
0702     case NV30:
0703         return QByteArrayLiteral("NV30");
0704     case NV40:
0705         return QByteArrayLiteral("NV40/G70");
0706     case G80:
0707         return QByteArrayLiteral("G80/G90");
0708     case GF100:
0709         return QByteArrayLiteral("GF100");
0710 
0711     case I8XX:
0712         return QByteArrayLiteral("i830/i835");
0713     case I915:
0714         return QByteArrayLiteral("i915/i945");
0715     case I965:
0716         return QByteArrayLiteral("i965");
0717     case SandyBridge:
0718         return QByteArrayLiteral("SandyBridge");
0719     case IvyBridge:
0720         return QByteArrayLiteral("IvyBridge");
0721     case Haswell:
0722         return QByteArrayLiteral("Haswell");
0723     case BayTrail:
0724         return QByteArrayLiteral("Bay Trail");
0725     case Cherryview:
0726         return QByteArrayLiteral("Cherryview");
0727     case Broadwell:
0728         return QByteArrayLiteral("Broadwell");
0729     case ApolloLake:
0730         return QByteArrayLiteral("Apollo Lake");
0731     case Skylake:
0732         return QByteArrayLiteral("Skylake");
0733     case GeminiLake:
0734         return QByteArrayLiteral("Gemini Lake");
0735     case KabyLake:
0736         return QByteArrayLiteral("Kaby Lake");
0737     case CoffeeLake:
0738         return QByteArrayLiteral("Coffee Lake");
0739     case WhiskeyLake:
0740         return QByteArrayLiteral("Whiskey Lake");
0741     case CometLake:
0742         return QByteArrayLiteral("Comet Lake");
0743     case CannonLake:
0744         return QByteArrayLiteral("Cannon Lake");
0745     case IceLake:
0746         return QByteArrayLiteral("Ice Lake");
0747     case TigerLake:
0748         return QByteArrayLiteral("Tiger Lake");
0749 
0750     case Adreno1XX:
0751         return QByteArrayLiteral("Adreno 1xx series");
0752     case Adreno2XX:
0753         return QByteArrayLiteral("Adreno 2xx series");
0754     case Adreno3XX:
0755         return QByteArrayLiteral("Adreno 3xx series");
0756     case Adreno4XX:
0757         return QByteArrayLiteral("Adreno 4xx series");
0758     case Adreno5XX:
0759         return QByteArrayLiteral("Adreno 5xx series");
0760 
0761     case Mali400:
0762         return QByteArrayLiteral("Mali 400 series");
0763     case Mali450:
0764         return QByteArrayLiteral("Mali 450 series");
0765     case Mali470:
0766         return QByteArrayLiteral("Mali 470 series");
0767 
0768     case MaliT7XX:
0769         return QByteArrayLiteral("Mali T7xx series");
0770     case MaliT8XX:
0771         return QByteArrayLiteral("Mali T8xx series");
0772     case MaliGXX:
0773         return QByteArrayLiteral("Mali Gxx series");
0774 
0775     case VC4_2_1:
0776         return QByteArrayLiteral("VideoCore IV");
0777     case V3D_4_2:
0778         return QByteArrayLiteral("VideoCore 3D");
0779 
0780     default:
0781         return QByteArrayLiteral("Unknown");
0782     }
0783 }
0784 
0785 // -------
0786 
0787 GLPlatform::GLPlatform()
0788     : m_driver(Driver_Unknown)
0789     , m_chipClass(UnknownChipClass)
0790     , m_recommendedCompositor(QPainterCompositing)
0791     , m_glVersion(0)
0792     , m_glslVersion(0)
0793     , m_mesaVersion(0)
0794     , m_driverVersion(0)
0795     , m_galliumVersion(0)
0796     , m_serverVersion(0)
0797     , m_kernelVersion(0)
0798     , m_looseBinding(false)
0799     , m_supportsGLSL(false)
0800     , m_limitedGLSL(false)
0801     , m_textureNPOT(false)
0802     , m_limitedNPOT(false)
0803     , m_packInvert(false)
0804     , m_virtualMachine(false)
0805     , m_preferBufferSubData(false)
0806     , m_platformInterface(NoOpenGLPlatformInterface)
0807     , m_gles(false)
0808 {
0809 }
0810 
0811 GLPlatform::~GLPlatform()
0812 {
0813 }
0814 
0815 void GLPlatform::detect(OpenGLPlatformInterface platformInterface)
0816 {
0817     m_platformInterface = platformInterface;
0818 
0819     m_vendor = (const char *)glGetString(GL_VENDOR);
0820     m_renderer = (const char *)glGetString(GL_RENDERER);
0821     m_version = (const char *)glGetString(GL_VERSION);
0822 
0823     // Parse the OpenGL version
0824     const QList<QByteArray> versionTokens = m_version.split(' ');
0825     if (versionTokens.count() > 0) {
0826         const QByteArray version = QByteArray(m_version);
0827         m_glVersion = parseVersionString(version);
0828         if (platformInterface == EglPlatformInterface) {
0829             // only EGL can have OpenGLES, GLX is OpenGL only
0830             if (version.startsWith("OpenGL ES")) {
0831                 // from GLES 2: "Returns a version or release number of the form OpenGL<space>ES<space><version number><space><vendor-specific information>."
0832                 // from GLES 3: "Returns a version or release number." and "The version number uses one of these forms: major_number.minor_number major_number.minor_number.release_number"
0833                 m_gles = true;
0834             }
0835         }
0836     }
0837 
0838     if (!isGLES() && m_glVersion >= kVersionNumber(3, 0)) {
0839         int count;
0840         glGetIntegerv(GL_NUM_EXTENSIONS, &count);
0841 
0842         for (int i = 0; i < count; i++) {
0843             const char *name = (const char *)glGetStringi(GL_EXTENSIONS, i);
0844             m_extensions.insert(name);
0845         }
0846     } else {
0847         const QByteArray extensions = (const char *)glGetString(GL_EXTENSIONS);
0848         QList<QByteArray> extensionsList = extensions.split(' ');
0849         m_extensions = {extensionsList.constBegin(), extensionsList.constEnd()};
0850     }
0851 
0852     // Parse the Mesa version
0853     const int mesaIndex = versionTokens.indexOf("Mesa");
0854     if (mesaIndex != -1) {
0855         const QByteArray &version = versionTokens.at(mesaIndex + 1);
0856         m_mesaVersion = parseVersionString(version);
0857     }
0858 
0859     if (isGLES()) {
0860         m_supportsGLSL = true;
0861         m_textureNPOT = true;
0862     } else {
0863         m_supportsGLSL = (m_extensions.contains("GL_ARB_shader_objects")
0864                           && m_extensions.contains("GL_ARB_fragment_shader")
0865                           && m_extensions.contains("GL_ARB_vertex_shader"));
0866 
0867         m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two");
0868     }
0869 
0870     m_serverVersion = getXServerVersion();
0871     m_kernelVersion = getKernelVersion();
0872 
0873     m_glslVersion = 0;
0874     m_glsl_version.clear();
0875 
0876     if (m_supportsGLSL) {
0877         // Parse the GLSL version
0878         m_glsl_version = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
0879         m_glslVersion = parseVersionString(m_glsl_version);
0880     }
0881 
0882     m_chipset = QByteArrayLiteral("Unknown");
0883     m_preferBufferSubData = false;
0884     m_packInvert = m_extensions.contains("GL_MESA_pack_invert");
0885 
0886     // Mesa classic drivers
0887     // ====================================================
0888 
0889     // Radeon
0890     if (m_renderer.startsWith("Mesa DRI R")) {
0891         // Sample renderer string: Mesa DRI R600 (RV740 94B3) 20090101 x86/MMX/SSE2 TCL DRI2
0892         const QList<QByteArray> tokens = m_renderer.split(' ');
0893         const QByteArray &chipClass = tokens.at(2);
0894         m_chipset = tokens.at(3).mid(1, -1); // Strip the leading '('
0895 
0896         if (chipClass == "R100") {
0897             // Vendor: Tungsten Graphics, Inc.
0898             m_driver = Driver_R100;
0899 
0900         } else if (chipClass == "R200") {
0901             // Vendor: Tungsten Graphics, Inc.
0902             m_driver = Driver_R200;
0903 
0904         } else if (chipClass == "R300") {
0905             // Vendor: DRI R300 Project
0906             m_driver = Driver_R300C;
0907 
0908         } else if (chipClass == "R600") {
0909             // Vendor: Advanced Micro Devices, Inc.
0910             m_driver = Driver_R600C;
0911         }
0912 
0913         m_chipClass = detectRadeonClass(m_chipset);
0914     }
0915 
0916     // Intel
0917     else if (m_renderer.contains("Intel")) {
0918         // Vendor: Tungsten Graphics, Inc.
0919         // Sample renderer string: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100328 2010Q1
0920 
0921         QByteArray chipset;
0922         if (m_renderer.startsWith("Intel(R) Integrated Graphics Device")) {
0923             chipset = "IGD";
0924         } else {
0925             chipset = m_renderer;
0926         }
0927 
0928         m_driver = Driver_Intel;
0929         m_chipClass = detectIntelClass(chipset);
0930     }
0931 
0932     // Properietary drivers
0933     // ====================================================
0934     else if (m_vendor == "ATI Technologies Inc.") {
0935         m_chipClass = detectRadeonClass(m_renderer);
0936         m_driver = Driver_Catalyst;
0937 
0938         if (versionTokens.count() > 1 && versionTokens.at(2)[0] == '(') {
0939             m_driverVersion = parseVersionString(versionTokens.at(1));
0940         } else if (versionTokens.count() > 0) {
0941             m_driverVersion = parseVersionString(versionTokens.at(0));
0942         } else {
0943             m_driverVersion = 0;
0944         }
0945     }
0946 
0947     else if (m_vendor == "NVIDIA Corporation") {
0948         m_chipClass = detectNVidiaClass(m_renderer);
0949         m_driver = Driver_NVidia;
0950 
0951         int index = versionTokens.indexOf("NVIDIA");
0952         if (versionTokens.count() > index) {
0953             m_driverVersion = parseVersionString(versionTokens.at(index + 1));
0954         } else {
0955             m_driverVersion = 0;
0956         }
0957     }
0958 
0959     else if (m_vendor == "Qualcomm") {
0960         m_driver = Driver_Qualcomm;
0961         m_chipClass = detectQualcommClass(m_renderer);
0962     }
0963 
0964     else if (m_renderer.contains("Panfrost")) {
0965         m_driver = Driver_Panfrost;
0966         m_chipClass = detectPanfrostClass(m_renderer);
0967     }
0968 
0969     else if (m_renderer.contains("Mali")) {
0970         m_driver = Driver_Lima;
0971         m_chipClass = detectLimaClass(m_renderer);
0972     }
0973 
0974     else if (m_renderer.startsWith("VC4 ")) {
0975         m_driver = Driver_VC4;
0976         m_chipClass = detectVC4Class(m_renderer);
0977     }
0978 
0979     else if(m_renderer.startsWith("V3D ")) {
0980         m_driver = Driver_V3D;
0981         m_chipClass = detectV3DClass(m_renderer);
0982     }
0983 
0984     else if (m_renderer == "Software Rasterizer") {
0985         m_driver = Driver_Swrast;
0986     }
0987 
0988     // Virtual Hardware
0989     // ====================================================
0990     else if (m_vendor == "Humper" && m_renderer == "Chromium") {
0991         // Virtual Box
0992         m_driver = Driver_VirtualBox;
0993 
0994         const int index = versionTokens.indexOf("Chromium");
0995         if (versionTokens.count() > index) {
0996             m_driverVersion = parseVersionString(versionTokens.at(index + 1));
0997         } else {
0998             m_driverVersion = 0;
0999         }
1000     }
1001 
1002     // Gallium drivers
1003     // ====================================================
1004     else {
1005         const QList<QByteArray> tokens = m_renderer.split(' ');
1006         if (m_renderer.contains("Gallium")) {
1007             // Sample renderer string: Gallium 0.4 on AMD RV740
1008             m_galliumVersion = parseVersionString(tokens.at(1));
1009             m_chipset = (tokens.at(3) == "AMD" || tokens.at(3) == "ATI") ? tokens.at(4) : tokens.at(3);
1010         } else {
1011             // The renderer string does not contain "Gallium" anymore.
1012             m_chipset = tokens.at(0);
1013             // We don't know the actual version anymore, but it's at least 0.4.
1014             m_galliumVersion = kVersionNumber(0, 4, 0);
1015         }
1016 
1017         // R300G
1018         if (m_vendor == QByteArrayLiteral("X.Org R300 Project")) {
1019             m_chipClass = detectRadeonClass(m_chipset);
1020             m_driver = Driver_R300G;
1021         }
1022 
1023         // R600G
1024         else if (m_vendor == "X.Org" && (m_renderer.contains("R6") || m_renderer.contains("R7") || m_renderer.contains("RV6") || m_renderer.contains("RV7") || m_renderer.contains("RS780") || m_renderer.contains("RS880") || m_renderer.contains("CEDAR") || m_renderer.contains("REDWOOD") || m_renderer.contains("JUNIPER") || m_renderer.contains("CYPRESS") || m_renderer.contains("HEMLOCK") || m_renderer.contains("PALM") || m_renderer.contains("EVERGREEN") || m_renderer.contains("SUMO") || m_renderer.contains("SUMO2") || m_renderer.contains("BARTS") || m_renderer.contains("TURKS") || m_renderer.contains("CAICOS") || m_renderer.contains("CAYMAN"))) {
1025             m_chipClass = detectRadeonClass(m_chipset);
1026             m_driver = Driver_R600G;
1027         }
1028 
1029         // RadeonSI
1030         else if ((m_vendor == "X.Org" || m_vendor == "AMD") && (m_renderer.contains("TAHITI") || m_renderer.contains("PITCAIRN") || m_renderer.contains("VERDE") || m_renderer.contains("OLAND") || m_renderer.contains("HAINAN") || m_renderer.contains("BONAIRE") || m_renderer.contains("KAVERI") || m_renderer.contains("KABINI") || m_renderer.contains("HAWAII") || m_renderer.contains("MULLINS") || m_renderer.contains("TOPAZ") || m_renderer.contains("TONGA") || m_renderer.contains("FIJI") || m_renderer.contains("CARRIZO") || m_renderer.contains("STONEY") || m_renderer.contains("POLARIS10") || m_renderer.contains("POLARIS11") || m_renderer.contains("POLARIS12") || m_renderer.contains("VEGAM") || m_renderer.contains("VEGA10") || m_renderer.contains("VEGA12") || m_renderer.contains("VEGA20") || m_renderer.contains("RAVEN") || m_renderer.contains("RAVEN2") || m_renderer.contains("RENOIR") || m_renderer.contains("ARCTURUS") || m_renderer.contains("NAVI10") || m_renderer.contains("NAVI12") || m_renderer.contains("NAVI14"))) {
1031             m_chipClass = detectRadeonClass(m_renderer);
1032             m_driver = Driver_RadeonSI;
1033         }
1034 
1035         // Nouveau
1036         else if (m_vendor == "nouveau") {
1037             m_chipClass = detectNVidiaClass(m_chipset);
1038             m_driver = Driver_Nouveau;
1039         }
1040 
1041         // softpipe
1042         else if (m_chipset == "softpipe") {
1043             m_driver = Driver_Softpipe;
1044         }
1045 
1046         // llvmpipe
1047         else if (m_chipset == "llvmpipe") {
1048             m_driver = Driver_Llvmpipe;
1049         }
1050 
1051         // SVGA3D
1052         else if (m_vendor == "VMware, Inc." && m_chipset.contains("SVGA3D")) {
1053             m_driver = Driver_VMware;
1054         }
1055 
1056         // virgl
1057         else if (m_renderer == "virgl") {
1058             m_driver = Driver_Virgl;
1059         }
1060     }
1061 
1062     // Driver/GPU specific features
1063     // ====================================================
1064     if (isRadeon()) {
1065         // R200 technically has a programmable pipeline, but since it's SM 1.4,
1066         // it's too limited to to be of any practical value to us.
1067         if (m_chipClass < R300) {
1068             m_supportsGLSL = false;
1069         }
1070 
1071         m_limitedGLSL = false;
1072         m_limitedNPOT = false;
1073 
1074         if (m_chipClass < R600) {
1075             if (driver() == Driver_Catalyst) {
1076                 m_textureNPOT = m_limitedNPOT = false; // Software fallback
1077             } else if (driver() == Driver_R300G) {
1078                 m_limitedNPOT = m_textureNPOT;
1079             }
1080 
1081             m_limitedGLSL = m_supportsGLSL;
1082         }
1083 
1084         if (m_chipClass < R300) {
1085             // fallback to NoCompositing for R100 and R200
1086             m_recommendedCompositor = NoCompositing;
1087         } else if (m_chipClass < R600) {
1088             // NoCompositing due to NPOT limitations not supported by KWin's shaders
1089             m_recommendedCompositor = NoCompositing;
1090         } else {
1091             m_recommendedCompositor = OpenGLCompositing;
1092         }
1093 
1094         if (driver() == Driver_R600G || (driver() == Driver_R600C && m_renderer.contains("DRI2"))) {
1095             m_looseBinding = true;
1096         }
1097     }
1098 
1099     if (isNvidia()) {
1100         if (m_driver == Driver_NVidia && m_chipClass < NV40) {
1101             m_supportsGLSL = false; // High likelihood of software emulation
1102         }
1103 
1104         if (m_driver == Driver_NVidia) {
1105             m_looseBinding = true;
1106             m_preferBufferSubData = true;
1107         }
1108 
1109         if (m_chipClass < NV40) {
1110             m_recommendedCompositor = NoCompositing;
1111         } else {
1112             m_recommendedCompositor = OpenGLCompositing;
1113         }
1114 
1115         m_limitedNPOT = m_textureNPOT && m_chipClass < NV40;
1116         m_limitedGLSL = m_supportsGLSL && m_chipClass < G80;
1117     }
1118 
1119     if (isIntel()) {
1120         if (m_chipClass < I915) {
1121             m_supportsGLSL = false;
1122         }
1123 
1124         m_limitedGLSL = m_supportsGLSL && m_chipClass < I965;
1125         // see https://bugs.freedesktop.org/show_bug.cgi?id=80349#c1
1126         m_looseBinding = false;
1127 
1128         if (m_chipClass < I915) {
1129             m_recommendedCompositor = NoCompositing;
1130         } else {
1131             m_recommendedCompositor = OpenGLCompositing;
1132         }
1133     }
1134 
1135     if (isPanfrost()) {
1136         m_recommendedCompositor = OpenGLCompositing;
1137     }
1138 
1139     if (isLima()) {
1140         m_recommendedCompositor = OpenGLCompositing;
1141         m_supportsGLSL = true;
1142     }
1143 
1144     if (isVideoCore4()) {
1145         // OpenGL works, but is much slower than QPainter
1146         m_recommendedCompositor = QPainterCompositing;
1147     }
1148 
1149     if (isVideoCore3D()) {
1150         // OpenGL works, but is much slower than QPainter
1151         m_recommendedCompositor = QPainterCompositing;
1152     }
1153 
1154     if (isMesaDriver() && platformInterface == EglPlatformInterface) {
1155         // According to the reference implementation in
1156         // mesa/demos/src/egl/opengles1/texture_from_pixmap
1157         // the mesa egl implementation does not require a strict binding (so far).
1158         m_looseBinding = true;
1159     }
1160 
1161     if (isSoftwareEmulation()) {
1162         if (m_driver < Driver_Llvmpipe) {
1163             // we recommend QPainter
1164             m_recommendedCompositor = QPainterCompositing;
1165             // Software emulation does not provide GLSL
1166             m_limitedGLSL = m_supportsGLSL = false;
1167         } else {
1168             // llvmpipe does support GLSL
1169             m_recommendedCompositor = OpenGLCompositing;
1170             m_limitedGLSL = false;
1171             m_supportsGLSL = true;
1172         }
1173     }
1174 
1175     if (m_driver == Driver_Qualcomm) {
1176         if (m_chipClass == Adreno1XX) {
1177             m_recommendedCompositor = NoCompositing;
1178         } else {
1179             // all other drivers support at least GLES 2
1180             m_recommendedCompositor = OpenGLCompositing;
1181         }
1182     }
1183 
1184     if (m_chipClass == UnknownChipClass && m_driver == Driver_Unknown) {
1185         // we don't know the hardware. Let's be optimistic and assume OpenGL compatible hardware
1186         m_recommendedCompositor = OpenGLCompositing;
1187         m_supportsGLSL = true;
1188     }
1189 
1190     if (isVirtualBox()) {
1191         m_virtualMachine = true;
1192         m_recommendedCompositor = OpenGLCompositing;
1193     }
1194 
1195     if (isVMware()) {
1196         m_virtualMachine = true;
1197         m_recommendedCompositor = OpenGLCompositing;
1198     }
1199 
1200     if (m_driver == Driver_Virgl) {
1201         m_virtualMachine = true;
1202         m_recommendedCompositor = OpenGLCompositing;
1203     }
1204 
1205     // and force back to shader supported on gles, we wouldn't have got a context if not supported
1206     if (isGLES()) {
1207         m_supportsGLSL = true;
1208         m_limitedGLSL = false;
1209     }
1210 }
1211 
1212 static void print(const QByteArray &label, const QByteArray &setting)
1213 {
1214     qInfo("%-40s%s", label.data(), setting.data());
1215 }
1216 
1217 void GLPlatform::printResults() const
1218 {
1219     print(QByteArrayLiteral("OpenGL vendor string:"), m_vendor);
1220     print(QByteArrayLiteral("OpenGL renderer string:"), m_renderer);
1221     print(QByteArrayLiteral("OpenGL version string:"), m_version);
1222 
1223     if (m_supportsGLSL) {
1224         print(QByteArrayLiteral("OpenGL shading language version string:"), m_glsl_version);
1225     }
1226 
1227     print(QByteArrayLiteral("Driver:"), driverToString8(m_driver));
1228     if (!isMesaDriver()) {
1229         print(QByteArrayLiteral("Driver version:"), versionToString8(m_driverVersion));
1230     }
1231 
1232     print(QByteArrayLiteral("GPU class:"), chipClassToString8(m_chipClass));
1233 
1234     print(QByteArrayLiteral("OpenGL version:"), versionToString8(m_glVersion));
1235 
1236     if (m_supportsGLSL) {
1237         print(QByteArrayLiteral("GLSL version:"), versionToString8(m_glslVersion));
1238     }
1239 
1240     if (isMesaDriver()) {
1241         print(QByteArrayLiteral("Mesa version:"), versionToString8(mesaVersion()));
1242     }
1243     // if (galliumVersion() > 0)
1244     //     print("Gallium version:", versionToString(m_galliumVersion));
1245     if (serverVersion() > 0) {
1246         print(QByteArrayLiteral("X server version:"), versionToString8(m_serverVersion));
1247     }
1248     if (kernelVersion() > 0) {
1249         print(QByteArrayLiteral("Linux kernel version:"), versionToString8(m_kernelVersion));
1250     }
1251 
1252     print(QByteArrayLiteral("Requires strict binding:"), !m_looseBinding ? QByteArrayLiteral("yes") : QByteArrayLiteral("no"));
1253     print(QByteArrayLiteral("GLSL shaders:"), m_supportsGLSL ? (m_limitedGLSL ? QByteArrayLiteral("limited") : QByteArrayLiteral("yes")) : QByteArrayLiteral("no"));
1254     print(QByteArrayLiteral("Texture NPOT support:"), m_textureNPOT ? (m_limitedNPOT ? QByteArrayLiteral("limited") : QByteArrayLiteral("yes")) : QByteArrayLiteral("no"));
1255     print(QByteArrayLiteral("Virtual Machine:"), m_virtualMachine ? QByteArrayLiteral("yes") : QByteArrayLiteral("no"));
1256 }
1257 
1258 bool GLPlatform::supports(GLFeature feature) const
1259 {
1260     switch (feature) {
1261     case LooseBinding:
1262         return m_looseBinding;
1263 
1264     case GLSL:
1265         return m_supportsGLSL;
1266 
1267     case LimitedGLSL:
1268         return m_limitedGLSL;
1269 
1270     case TextureNPOT:
1271         return m_textureNPOT;
1272 
1273     case LimitedNPOT:
1274         return m_limitedNPOT;
1275 
1276     case PackInvert:
1277         return m_packInvert;
1278 
1279     default:
1280         return false;
1281     }
1282 }
1283 
1284 qint64 GLPlatform::glVersion() const
1285 {
1286     return m_glVersion;
1287 }
1288 
1289 qint64 GLPlatform::glslVersion() const
1290 {
1291     return m_glslVersion;
1292 }
1293 
1294 qint64 GLPlatform::mesaVersion() const
1295 {
1296     return m_mesaVersion;
1297 }
1298 
1299 qint64 GLPlatform::galliumVersion() const
1300 {
1301     return m_galliumVersion;
1302 }
1303 
1304 qint64 GLPlatform::serverVersion() const
1305 {
1306     return m_serverVersion;
1307 }
1308 
1309 qint64 GLPlatform::kernelVersion() const
1310 {
1311     return m_kernelVersion;
1312 }
1313 
1314 qint64 GLPlatform::driverVersion() const
1315 {
1316     if (isMesaDriver()) {
1317         return mesaVersion();
1318     }
1319 
1320     return m_driverVersion;
1321 }
1322 
1323 Driver GLPlatform::driver() const
1324 {
1325     return m_driver;
1326 }
1327 
1328 ChipClass GLPlatform::chipClass() const
1329 {
1330     return m_chipClass;
1331 }
1332 
1333 bool GLPlatform::isMesaDriver() const
1334 {
1335     return mesaVersion() > 0;
1336 }
1337 
1338 bool GLPlatform::isGalliumDriver() const
1339 {
1340     return galliumVersion() > 0;
1341 }
1342 
1343 bool GLPlatform::isRadeon() const
1344 {
1345     return m_chipClass >= R100 && m_chipClass <= UnknownRadeon;
1346 }
1347 
1348 bool GLPlatform::isNvidia() const
1349 {
1350     return m_chipClass >= NV10 && m_chipClass <= UnknownNVidia;
1351 }
1352 
1353 bool GLPlatform::isIntel() const
1354 {
1355     return m_chipClass >= I8XX && m_chipClass <= UnknownIntel;
1356 }
1357 
1358 bool GLPlatform::isVirtualBox() const
1359 {
1360     return m_driver == Driver_VirtualBox;
1361 }
1362 
1363 bool GLPlatform::isVMware() const
1364 {
1365     return m_driver == Driver_VMware;
1366 }
1367 
1368 bool GLPlatform::isVirgl() const
1369 {
1370     return m_driver == Driver_Virgl;
1371 }
1372 
1373 bool GLPlatform::isSoftwareEmulation() const
1374 {
1375     return m_driver == Driver_Softpipe || m_driver == Driver_Swrast || m_driver == Driver_Llvmpipe;
1376 }
1377 
1378 bool GLPlatform::isAdreno() const
1379 {
1380     return m_chipClass >= Adreno1XX && m_chipClass <= UnknownAdreno;
1381 }
1382 
1383 bool GLPlatform::isPanfrost() const
1384 {
1385     return m_chipClass >= MaliT7XX && m_chipClass <= UnknownPanfrost;
1386 }
1387 
1388 bool GLPlatform::isLima() const
1389 {
1390     return m_chipClass >= Mali400 && m_chipClass <= UnknownLima;
1391 }
1392 
1393 bool GLPlatform::isVideoCore4() const
1394 {
1395     return m_chipClass >= VC4_2_1 && m_chipClass <= UnknownVideoCore4;
1396 }
1397 
1398 bool GLPlatform::isVideoCore3D() const
1399 {
1400     return m_chipClass >= V3D_4_2 && m_chipClass <= UnknownVideoCore3D;
1401 }
1402 
1403 const QByteArray &GLPlatform::glRendererString() const
1404 {
1405     return m_renderer;
1406 }
1407 
1408 const QByteArray &GLPlatform::glVendorString() const
1409 {
1410     return m_vendor;
1411 }
1412 
1413 const QByteArray &GLPlatform::glVersionString() const
1414 {
1415     return m_version;
1416 }
1417 
1418 const QByteArray &GLPlatform::glShadingLanguageVersionString() const
1419 {
1420     return m_glsl_version;
1421 }
1422 
1423 bool GLPlatform::isLooseBinding() const
1424 {
1425     return m_looseBinding;
1426 }
1427 
1428 bool GLPlatform::isVirtualMachine() const
1429 {
1430     return m_virtualMachine;
1431 }
1432 
1433 CompositingType GLPlatform::recommendedCompositor() const
1434 {
1435     return m_recommendedCompositor;
1436 }
1437 
1438 bool GLPlatform::preferBufferSubData() const
1439 {
1440     return m_preferBufferSubData;
1441 }
1442 
1443 OpenGLPlatformInterface GLPlatform::platformInterface() const
1444 {
1445     return m_platformInterface;
1446 }
1447 
1448 bool GLPlatform::isGLES() const
1449 {
1450     return m_gles;
1451 }
1452 
1453 void GLPlatform::cleanup()
1454 {
1455     s_platform.reset();
1456 }
1457 
1458 } // namespace KWin