KWin
Loading...
Searching...
No Matches
glplatform.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2010 Fredrik Höglund <fredrik@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9
10#include "opengl/glplatform.h"
11// include kwinglutils_funcs.h to avoid the redeclaration issues
12// between qopengl.h and epoxy/gl.h
13#include "effect/xcb.h"
15#include <epoxy/gl.h>
16
17#include <QDebug>
18#include <QOpenGLContext>
19#include <QRegularExpression>
20#include <QStringList>
21
22#include <sys/utsname.h>
23
24#include <iomanip>
25#include <ios>
26#include <iostream>
27
28namespace KWin
29{
30
31std::unique_ptr<GLPlatform> GLPlatform::s_platform;
32
33// Extracts the portion of a string that matches a regular expression
34static QString extract(const QString &text, const QString &pattern)
35{
36 const QRegularExpression regexp(pattern);
37 const QRegularExpressionMatch match = regexp.match(text);
38 if (!match.hasMatch()) {
39 return QString();
40 }
41 return match.captured();
42}
43
44static ChipClass detectRadeonClass(QByteArrayView chipset)
45{
46 if (chipset.isEmpty()) {
47 return UnknownRadeon;
48 }
49
50 if (chipset.contains("R100")
51 || chipset.contains("RV100")
52 || chipset.contains("RS100")) {
53 return R100;
54 }
55
56 if (chipset.contains("RV200")
57 || chipset.contains("RS200")
58 || chipset.contains("R200")
59 || chipset.contains("RV250")
60 || chipset.contains("RS300")
61 || chipset.contains("RV280")) {
62 return R200;
63 }
64
65 if (chipset.contains("R300")
66 || chipset.contains("R350")
67 || chipset.contains("R360")
68 || chipset.contains("RV350")
69 || chipset.contains("RV370")
70 || chipset.contains("RV380")) {
71 return R300;
72 }
73
74 if (chipset.contains("R420")
75 || chipset.contains("R423")
76 || chipset.contains("R430")
77 || chipset.contains("R480")
78 || chipset.contains("R481")
79 || chipset.contains("RV410")
80 || chipset.contains("RS400")
81 || chipset.contains("RC410")
82 || chipset.contains("RS480")
83 || chipset.contains("RS482")
84 || chipset.contains("RS600")
85 || chipset.contains("RS690")
86 || chipset.contains("RS740")) {
87 return R400;
88 }
89
90 if (chipset.contains("RV515")
91 || chipset.contains("R520")
92 || chipset.contains("RV530")
93 || chipset.contains("R580")
94 || chipset.contains("RV560")
95 || chipset.contains("RV570")) {
96 return R500;
97 }
98
99 if (chipset.contains("R600")
100 || chipset.contains("RV610")
101 || chipset.contains("RV630")
102 || chipset.contains("RV670")
103 || chipset.contains("RV620")
104 || chipset.contains("RV635")
105 || chipset.contains("RS780")
106 || chipset.contains("RS880")) {
107 return R600;
108 }
109
110 if (chipset.contains("R700")
111 || chipset.contains("RV770")
112 || chipset.contains("RV730")
113 || chipset.contains("RV710")
114 || chipset.contains("RV740")) {
115 return R700;
116 }
117
118 if (chipset.contains("EVERGREEN") // Not an actual chipset, but returned by R600G in 7.9
119 || chipset.contains("CEDAR")
120 || chipset.contains("REDWOOD")
121 || chipset.contains("JUNIPER")
122 || chipset.contains("CYPRESS")
123 || chipset.contains("HEMLOCK")
124 || chipset.contains("PALM")) {
125 return Evergreen;
126 }
127
128 if (chipset.contains("SUMO")
129 || chipset.contains("SUMO2")
130 || chipset.contains("BARTS")
131 || chipset.contains("TURKS")
132 || chipset.contains("CAICOS")
133 || chipset.contains("CAYMAN")) {
134 return NorthernIslands;
135 }
136
137 if (chipset.contains("TAHITI")
138 || chipset.contains("PITCAIRN")
139 || chipset.contains("VERDE")
140 || chipset.contains("OLAND")
141 || chipset.contains("HAINAN")) {
142 return SouthernIslands;
143 }
144
145 if (chipset.contains("BONAIRE")
146 || chipset.contains("KAVERI")
147 || chipset.contains("KABINI")
148 || chipset.contains("HAWAII")
149 || chipset.contains("MULLINS")) {
150 return SeaIslands;
151 }
152
153 if (chipset.contains("TONGA")
154 || chipset.contains("TOPAZ")
155 || chipset.contains("FIJI")
156 || chipset.contains("CARRIZO")
157 || chipset.contains("STONEY")) {
158 return VolcanicIslands;
159 }
160
161 if (chipset.contains("POLARIS10")
162 || chipset.contains("POLARIS11")
163 || chipset.contains("POLARIS12")
164 || chipset.contains("VEGAM")) {
165 return ArcticIslands;
166 }
167
168 if (chipset.contains("VEGA10")
169 || chipset.contains("VEGA12")
170 || chipset.contains("VEGA20")
171 || chipset.contains("RAVEN")
172 || chipset.contains("RAVEN2")
173 || chipset.contains("RENOIR")
174 || chipset.contains("ARCTURUS")) {
175 return Vega;
176 }
177
178 if (chipset.contains("NAVI10")
179 || chipset.contains("NAVI12")
180 || chipset.contains("NAVI14")) {
181 return Navi;
182 }
183
184 const QString chipset16 = QString::fromLatin1(chipset);
185 QString name = extract(chipset16, QStringLiteral("HD [0-9]{4}")); // HD followed by a space and 4 digits
186 if (!name.isEmpty()) {
187 const int id = QStringView(name).right(4).toInt();
188 if (id == 6250 || id == 6310) { // Palm
189 return Evergreen;
190 }
191
192 if (id >= 6000 && id < 7000) {
193 return NorthernIslands; // HD 6xxx
194 }
195
196 if (id >= 5000 && id < 6000) {
197 return Evergreen; // HD 5xxx
198 }
199
200 if (id >= 4000 && id < 5000) {
201 return R700; // HD 4xxx
202 }
203
204 if (id >= 2000 && id < 4000) { // HD 2xxx/3xxx
205 return R600;
206 }
207
208 return UnknownRadeon;
209 }
210
211 name = extract(chipset16, QStringLiteral("X[0-9]{3,4}")); // X followed by 3-4 digits
212 if (!name.isEmpty()) {
213 const int id = QStringView(name).mid(1, -1).toInt();
214
215 // X1xxx
216 if (id >= 1300) {
217 return R500;
218 }
219
220 // X7xx, X8xx, X12xx, 2100
221 if ((id >= 700 && id < 1000) || id >= 1200) {
222 return R400;
223 }
224
225 // X200, X3xx, X5xx, X6xx, X10xx, X11xx
226 if ((id >= 300 && id < 700) || (id >= 1000 && id < 1200)) {
227 return R300;
228 }
229
230 return UnknownRadeon;
231 }
232
233 name = extract(chipset16, QStringLiteral("\\b[0-9]{4}\\b")); // A group of 4 digits
234 if (!name.isEmpty()) {
235 const int id = name.toInt();
236
237 // 7xxx
238 if (id >= 7000 && id < 8000) {
239 return R100;
240 }
241
242 // 8xxx, 9xxx
243 if (id >= 8000 && id < 9500) {
244 return R200;
245 }
246
247 // 9xxx
248 if (id >= 9500) {
249 return R300;
250 }
251
252 if (id == 2100) {
253 return R400;
254 }
255 }
256
257 return UnknownRadeon;
258}
259
260static ChipClass detectNVidiaClass(const QString &chipset)
261{
262 QString name = extract(chipset, QStringLiteral("\\bNV[0-9,A-F]{2}\\b")); // NV followed by two hexadecimal digits
263 if (!name.isEmpty()) {
264 const int id = QStringView(chipset).mid(2, -1).toInt(nullptr, 16); // Strip the 'NV' from the id
265
266 switch (id & 0xf0) {
267 case 0x00:
268 case 0x10:
269 return NV10;
270
271 case 0x20:
272 return NV20;
273
274 case 0x30:
275 return NV30;
276
277 case 0x40:
278 case 0x60:
279 return NV40;
280
281 case 0x50:
282 case 0x80:
283 case 0x90:
284 case 0xA0:
285 return G80;
286
287 default:
288 return UnknownNVidia;
289 }
290 }
291
292 if (chipset.contains(QLatin1String("GeForce2")) || chipset.contains(QLatin1String("GeForce 256"))) {
293 return NV10;
294 }
295
296 if (chipset.contains(QLatin1String("GeForce3"))) {
297 return NV20;
298 }
299
300 if (chipset.contains(QLatin1String("GeForce4"))) {
301 if (chipset.contains(QLatin1String("MX 420"))
302 || chipset.contains(QLatin1String("MX 440")) // including MX 440SE
303 || chipset.contains(QLatin1String("MX 460"))
304 || chipset.contains(QLatin1String("MX 4000"))
305 || chipset.contains(QLatin1String("PCX 4300"))) {
306 return NV10;
307 }
308
309 return NV20;
310 }
311
312 // GeForce 5,6,7,8,9
313 name = extract(chipset, QStringLiteral("GeForce (FX |PCX |Go )?\\d{4}(M|\\b)")).trimmed();
314 if (!name.isEmpty()) {
315 if (!name[name.length() - 1].isDigit()) {
316 name.chop(1);
317 }
318
319 const int id = QStringView(name).right(4).toInt();
320 if (id < 6000) {
321 return NV30;
322 }
323
324 if (id >= 6000 && id < 8000) {
325 return NV40;
326 }
327
328 if (id >= 8000) {
329 return G80;
330 }
331
332 return UnknownNVidia;
333 }
334
335 // GeForce 100/200/300/400/500
336 name = extract(chipset, QStringLiteral("GeForce (G |GT |GTX |GTS )?\\d{3}(M|\\b)")).trimmed();
337 if (!name.isEmpty()) {
338 if (!name[name.length() - 1].isDigit()) {
339 name.chop(1);
340 }
341
342 const int id = QStringView(name).right(3).toInt();
343 if (id >= 100 && id < 600) {
344 if (id >= 400) {
345 return GF100;
346 }
347
348 return G80;
349 }
350 return UnknownNVidia;
351 }
352
353 return UnknownNVidia;
354}
355static inline ChipClass detectNVidiaClass(QByteArrayView chipset)
356{
357 return detectNVidiaClass(QString::fromLatin1(chipset));
358}
359
360static ChipClass detectIntelClass(QByteArrayView chipset)
361{
362 // see mesa repository: src/mesa/drivers/dri/intel/intel_context.c
363 // GL 1.3, DX8? SM ?
364 if (chipset.contains("845G")
365 || chipset.contains("830M")
366 || chipset.contains("852GM/855GM")
367 || chipset.contains("865G")) {
368 return I8XX;
369 }
370
371 // GL 1.4, DX 9.0, SM 2.0
372 if (chipset.contains("915G")
373 || chipset.contains("E7221G")
374 || chipset.contains("915GM")
375 || chipset.contains("945G") // DX 9.0c
376 || chipset.contains("945GM")
377 || chipset.contains("945GME")
378 || chipset.contains("Q33") // GL1.5
379 || chipset.contains("Q35")
380 || chipset.contains("G33")
381 || chipset.contains("965Q") // GMA 3000, but apparently considered gen 4 by the driver
382 || chipset.contains("946GZ") // GMA 3000, but apparently considered gen 4 by the driver
383 || chipset.contains("IGD")) {
384 return I915;
385 }
386
387 // GL 2.0, DX 9.0c, SM 3.0
388 if (chipset.contains("965G")
389 || chipset.contains("G45/G43") // SM 4.0
390 || chipset.contains("965GM") // GL 2.1
391 || chipset.contains("965GME/GLE")
392 || chipset.contains("GM45")
393 || chipset.contains("Q45/Q43")
394 || chipset.contains("G41")
395 || chipset.contains("B43")
396 || chipset.contains("Ironlake")) {
397 return I965;
398 }
399
400 // GL 3.1, CL 1.1, DX 10.1
401 if (chipset.contains("Sandybridge") || chipset.contains("SNB GT")) {
402 return SandyBridge;
403 }
404
405 // GL4.0, CL1.1, DX11, SM 5.0
406 if (chipset.contains("Ivybridge") || chipset.contains("IVB GT")) {
407 return IvyBridge;
408 }
409
410 // GL4.0, CL1.2, DX11.1, SM 5.0
411 if (chipset.contains("Haswell") || chipset.contains("HSW GT")) {
412 return Haswell;
413 }
414 if (chipset.contains("BYT")) {
415 return BayTrail;
416 }
417 if (chipset.contains("CHV") || chipset.contains("BSW")) {
418 return Cherryview;
419 }
420 if (chipset.contains("BDW GT")) {
421 return Broadwell;
422 }
423 if (chipset.contains("SKL GT")) {
424 return Skylake;
425 }
426 if (chipset.contains("APL")) {
427 return ApolloLake;
428 }
429 if (chipset.contains("KBL GT")) {
430 return KabyLake;
431 }
432 if (chipset.contains("WHL GT")) {
433 return WhiskeyLake;
434 }
435 if (chipset.contains("CML GT")) {
436 return CometLake;
437 }
438 if (chipset.contains("CNL GT")) {
439 return CannonLake;
440 }
441 if (chipset.contains("CFL GT")) {
442 return CoffeeLake;
443 }
444 if (chipset.contains("ICL GT")) {
445 return IceLake;
446 }
447 if (chipset.contains("TGL GT")) {
448 return TigerLake;
449 }
450
451 return UnknownIntel;
452}
453
454static ChipClass detectQualcommClass(QByteArrayView chipClass)
455{
456 if (!chipClass.contains("Adreno")) {
457 return UnknownChipClass;
458 }
459 const auto parts = chipClass.toByteArray().split(' ');
460 if (parts.count() < 3) {
461 return UnknownAdreno;
462 }
463 bool ok = false;
464 const int value = parts.at(2).toInt(&ok);
465 if (ok) {
466 if (value >= 100 && value < 200) {
467 return Adreno1XX;
468 } else if (value >= 200 && value < 300) {
469 return Adreno2XX;
470 } else if (value >= 300 && value < 400) {
471 return Adreno3XX;
472 } else if (value >= 400 && value < 500) {
473 return Adreno4XX;
474 } else if (value >= 500 && value < 600) {
475 return Adreno5XX;
476 }
477 }
478 return UnknownAdreno;
479}
480
481static ChipClass detectPanfrostClass(QByteArrayView chipClass)
482{
483 // Keep the list of supported Mali chipset up to date with https://docs.mesa3d.org/drivers/panfrost.html
484 if (chipClass.contains("T720") || chipClass.contains("T760")) {
485 return MaliT7XX;
486 }
487
488 if (chipClass.contains("T820") || chipClass.contains("T830") || chipClass.contains("T860") || chipClass.contains("T880")) {
489 return MaliT8XX;
490 }
491
492 if (chipClass.contains("G31") || chipClass.contains("G51") || chipClass.contains("G52") || chipClass.contains("G57") || chipClass.contains("G72") || chipClass.contains("G76")) {
493 return MaliGXX;
494 }
495
496 return UnknownPanfrost;
497}
498
499static ChipClass detectLimaClass(QByteArrayView chipClass)
500{
501 if (chipClass.contains("400")) {
502 return Mali400;
503 } else if (chipClass.contains("450")) {
504 return Mali450;
505 } else if (chipClass.contains("470")) {
506 return Mali470;
507 }
508
509 return UnknownLima;
510}
511
512static ChipClass detectVC4Class(QByteArrayView chipClass)
513{
514 if (chipClass.contains("2.1")) {
515 return VC4_2_1;
516 }
517
518 return UnknownVideoCore4;
519}
520
521static ChipClass detectV3DClass(QByteArrayView chipClass)
522{
523 if (chipClass.contains("4.2")) {
524 return V3D_4_2;
525 }
526
527 return UnknownVideoCore3D;
528}
529
531{
532 return QString::fromLatin1(driverToString8(driver));
533}
535{
536 switch (driver) {
537 case Driver_R100:
538 return QByteArrayLiteral("Radeon");
539 case Driver_R200:
540 return QByteArrayLiteral("R200");
541 case Driver_R300C:
542 return QByteArrayLiteral("R300C");
543 case Driver_R300G:
544 return QByteArrayLiteral("R300G");
545 case Driver_R600C:
546 return QByteArrayLiteral("R600C");
547 case Driver_R600G:
548 return QByteArrayLiteral("R600G");
549 case Driver_RadeonSI:
550 return QByteArrayLiteral("RadeonSI");
551 case Driver_Nouveau:
552 return QByteArrayLiteral("Nouveau");
553 case Driver_Intel:
554 return QByteArrayLiteral("Intel");
555 case Driver_NVidia:
556 return QByteArrayLiteral("NVIDIA");
557 case Driver_Catalyst:
558 return QByteArrayLiteral("Catalyst");
559 case Driver_Swrast:
560 return QByteArrayLiteral("Software rasterizer");
561 case Driver_Softpipe:
562 return QByteArrayLiteral("softpipe");
563 case Driver_Llvmpipe:
564 return QByteArrayLiteral("LLVMpipe");
566 return QByteArrayLiteral("VirtualBox (Chromium)");
567 case Driver_VMware:
568 return QByteArrayLiteral("VMware (SVGA3D)");
569 case Driver_Qualcomm:
570 return QByteArrayLiteral("Qualcomm");
571 case Driver_Virgl:
572 return QByteArrayLiteral("Virgl (virtio-gpu, Qemu/KVM guest)");
573 case Driver_Panfrost:
574 return QByteArrayLiteral("Panfrost");
575 case Driver_Lima:
576 return QByteArrayLiteral("Mali (Lima)");
577 case Driver_VC4:
578 return QByteArrayLiteral("VideoCore IV");
579 case Driver_V3D:
580 return QByteArrayLiteral("VideoCore 3D");
581
582 default:
583 return QByteArrayLiteral("Unknown");
584 }
585}
586
588{
589 return QString::fromLatin1(chipClassToString8(chipClass));
590}
592{
593 switch (chipClass) {
594 case R100:
595 return QByteArrayLiteral("R100");
596 case R200:
597 return QByteArrayLiteral("R200");
598 case R300:
599 return QByteArrayLiteral("R300");
600 case R400:
601 return QByteArrayLiteral("R400");
602 case R500:
603 return QByteArrayLiteral("R500");
604 case R600:
605 return QByteArrayLiteral("R600");
606 case R700:
607 return QByteArrayLiteral("R700");
608 case Evergreen:
609 return QByteArrayLiteral("EVERGREEN");
610 case NorthernIslands:
611 return QByteArrayLiteral("Northern Islands");
612 case SouthernIslands:
613 return QByteArrayLiteral("Southern Islands");
614 case SeaIslands:
615 return QByteArrayLiteral("Sea Islands");
616 case VolcanicIslands:
617 return QByteArrayLiteral("Volcanic Islands");
618 case ArcticIslands:
619 return QByteArrayLiteral("Arctic Islands");
620 case Vega:
621 return QByteArrayLiteral("Vega");
622 case Navi:
623 return QByteArrayLiteral("Navi");
624
625 case NV10:
626 return QByteArrayLiteral("NV10");
627 case NV20:
628 return QByteArrayLiteral("NV20");
629 case NV30:
630 return QByteArrayLiteral("NV30");
631 case NV40:
632 return QByteArrayLiteral("NV40/G70");
633 case G80:
634 return QByteArrayLiteral("G80/G90");
635 case GF100:
636 return QByteArrayLiteral("GF100");
637
638 case I8XX:
639 return QByteArrayLiteral("i830/i835");
640 case I915:
641 return QByteArrayLiteral("i915/i945");
642 case I965:
643 return QByteArrayLiteral("i965");
644 case SandyBridge:
645 return QByteArrayLiteral("SandyBridge");
646 case IvyBridge:
647 return QByteArrayLiteral("IvyBridge");
648 case Haswell:
649 return QByteArrayLiteral("Haswell");
650 case BayTrail:
651 return QByteArrayLiteral("Bay Trail");
652 case Cherryview:
653 return QByteArrayLiteral("Cherryview");
654 case Broadwell:
655 return QByteArrayLiteral("Broadwell");
656 case ApolloLake:
657 return QByteArrayLiteral("Apollo Lake");
658 case Skylake:
659 return QByteArrayLiteral("Skylake");
660 case GeminiLake:
661 return QByteArrayLiteral("Gemini Lake");
662 case KabyLake:
663 return QByteArrayLiteral("Kaby Lake");
664 case CoffeeLake:
665 return QByteArrayLiteral("Coffee Lake");
666 case WhiskeyLake:
667 return QByteArrayLiteral("Whiskey Lake");
668 case CometLake:
669 return QByteArrayLiteral("Comet Lake");
670 case CannonLake:
671 return QByteArrayLiteral("Cannon Lake");
672 case IceLake:
673 return QByteArrayLiteral("Ice Lake");
674 case TigerLake:
675 return QByteArrayLiteral("Tiger Lake");
676
677 case Adreno1XX:
678 return QByteArrayLiteral("Adreno 1xx series");
679 case Adreno2XX:
680 return QByteArrayLiteral("Adreno 2xx series");
681 case Adreno3XX:
682 return QByteArrayLiteral("Adreno 3xx series");
683 case Adreno4XX:
684 return QByteArrayLiteral("Adreno 4xx series");
685 case Adreno5XX:
686 return QByteArrayLiteral("Adreno 5xx series");
687
688 case Mali400:
689 return QByteArrayLiteral("Mali 400 series");
690 case Mali450:
691 return QByteArrayLiteral("Mali 450 series");
692 case Mali470:
693 return QByteArrayLiteral("Mali 470 series");
694
695 case MaliT7XX:
696 return QByteArrayLiteral("Mali T7xx series");
697 case MaliT8XX:
698 return QByteArrayLiteral("Mali T8xx series");
699 case MaliGXX:
700 return QByteArrayLiteral("Mali Gxx series");
701
702 case VC4_2_1:
703 return QByteArrayLiteral("VideoCore IV");
704 case V3D_4_2:
705 return QByteArrayLiteral("VideoCore 3D");
706
707 default:
708 return QByteArrayLiteral("Unknown");
709 }
710}
711
712// -------
713
714GLPlatform::GLPlatform()
715 : m_driver(Driver_Unknown)
716 , m_chipClass(UnknownChipClass)
717 , m_recommendedCompositor(QPainterCompositing)
718 , m_looseBinding(false)
719 , m_packInvert(false)
720 , m_virtualMachine(false)
721 , m_preferBufferSubData(false)
722 , m_platformInterface(NoOpenGLPlatformInterface)
723{
724}
725
729
731{
732 m_platformInterface = platformInterface;
733
734 m_context = std::make_unique<OpenGlContext>();
735
736 // Parse the Mesa version
737 const auto versionTokens = m_context->openglVersionString().toByteArray().split(' ');
738 const int mesaIndex = versionTokens.indexOf("Mesa");
739 if (mesaIndex != -1) {
740 m_mesaVersion = Version::parseString(versionTokens.at(mesaIndex + 1));
741 }
742
743 m_glsl_version = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
744 m_glslVersion = Version::parseString(m_glsl_version);
745
746 m_chipset = QByteArrayLiteral("Unknown");
747 m_preferBufferSubData = false;
748 m_packInvert = m_context->hasOpenglExtension("GL_MESA_pack_invert");
749
750 // Mesa classic drivers
751 // ====================================================
752
753 // Radeon
754 if (m_context->renderer().startsWith("Mesa DRI R")) {
755 // Sample renderer string: Mesa DRI R600 (RV740 94B3) 20090101 x86/MMX/SSE2 TCL DRI2
756 const QList<QByteArray> tokens = m_context->renderer().toByteArray().split(' ');
757 const QByteArray &chipClass = tokens.at(2);
758 m_chipset = tokens.at(3).mid(1, -1); // Strip the leading '('
759
760 if (chipClass == "R100") {
761 // Vendor: Tungsten Graphics, Inc.
762 m_driver = Driver_R100;
763
764 } else if (chipClass == "R200") {
765 // Vendor: Tungsten Graphics, Inc.
766 m_driver = Driver_R200;
767
768 } else if (chipClass == "R300") {
769 // Vendor: DRI R300 Project
770 m_driver = Driver_R300C;
771
772 } else if (chipClass == "R600") {
773 // Vendor: Advanced Micro Devices, Inc.
774 m_driver = Driver_R600C;
775 }
776
777 m_chipClass = detectRadeonClass(m_chipset);
778 }
779
780 // Intel
781 else if (m_context->renderer().contains("Intel")) {
782 // Vendor: Tungsten Graphics, Inc.
783 // Sample renderer string: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100328 2010Q1
784
785 QByteArrayView chipset;
786 if (m_context->renderer().startsWith("Intel(R) Integrated Graphics Device")) {
787 chipset = "IGD";
788 } else {
789 chipset = m_context->renderer();
790 }
791
792 m_driver = Driver_Intel;
793 m_chipClass = detectIntelClass(chipset);
794 }
795
796 // Properietary drivers
797 // ====================================================
798 else if (m_context->vendor() == "ATI Technologies Inc.") {
799 m_chipClass = detectRadeonClass(m_context->renderer());
800 m_driver = Driver_Catalyst;
801
802 if (versionTokens.count() > 1 && versionTokens.at(2)[0] == '(') {
803 m_driverVersion = Version::parseString(versionTokens.at(1));
804 } else if (versionTokens.count() > 0) {
805 m_driverVersion = Version::parseString(versionTokens.at(0));
806 } else {
807 m_driverVersion = Version(0, 0, 0);
808 }
809 }
810
811 else if (m_context->vendor() == "NVIDIA Corporation") {
812 m_chipClass = detectNVidiaClass(m_context->renderer());
813 m_driver = Driver_NVidia;
814
815 int index = versionTokens.indexOf("NVIDIA");
816 if (versionTokens.count() > index) {
817 m_driverVersion = Version::parseString(versionTokens.at(index + 1));
818 } else {
819 m_driverVersion = Version(0, 0, 0);
820 }
821 }
822
823 else if (m_context->vendor() == "Qualcomm") {
824 m_driver = Driver_Qualcomm;
825 m_chipClass = detectQualcommClass(m_context->renderer());
826 }
827
828 else if (m_context->renderer().contains("Panfrost")) {
829 m_driver = Driver_Panfrost;
830 m_chipClass = detectPanfrostClass(m_context->renderer());
831 }
832
833 else if (m_context->renderer().contains("Mali")) {
834 m_driver = Driver_Lima;
835 m_chipClass = detectLimaClass(m_context->renderer());
836 }
837
838 else if (m_context->renderer().startsWith("VC4 ")) {
839 m_driver = Driver_VC4;
840 m_chipClass = detectVC4Class(m_context->renderer());
841 }
842
843 else if (m_context->renderer().startsWith("V3D ")) {
844 m_driver = Driver_V3D;
845 m_chipClass = detectV3DClass(m_context->renderer());
846 }
847
848 else if (m_context->renderer() == "Software Rasterizer") {
849 m_driver = Driver_Swrast;
850 }
851
852 // Virtual Hardware
853 // ====================================================
854 else if (m_context->vendor() == "Humper" && m_context->renderer() == "Chromium") {
855 // Virtual Box
856 m_driver = Driver_VirtualBox;
857
858 const int index = versionTokens.indexOf("Chromium");
859 if (versionTokens.count() > index) {
860 m_driverVersion = Version::parseString(versionTokens.at(index + 1));
861 } else {
862 m_driverVersion = Version(0, 0, 0);
863 }
864 }
865
866 // Gallium drivers
867 // ====================================================
868 else {
869 const QList<QByteArray> tokens = m_context->renderer().toByteArray().split(' ');
870 if (m_context->renderer().contains("Gallium")) {
871 // Sample renderer string: Gallium 0.4 on AMD RV740
872 m_chipset = (tokens.at(3) == "AMD" || tokens.at(3) == "ATI") ? tokens.at(4) : tokens.at(3);
873 } else {
874 // The renderer string does not contain "Gallium" anymore.
875 m_chipset = tokens.at(0);
876 }
877
878 // R300G
879 if (m_context->vendor() == QByteArrayLiteral("X.Org R300 Project")) {
880 m_chipClass = detectRadeonClass(m_chipset);
881 m_driver = Driver_R300G;
882 }
883
884 // R600G
885 else if (m_context->vendor() == "X.Org" && (m_context->renderer().contains("R6") || m_context->renderer().contains("R7") || m_context->renderer().contains("RV6") || m_context->renderer().contains("RV7") || m_context->renderer().contains("RS780") || m_context->renderer().contains("RS880") || m_context->renderer().contains("CEDAR") || m_context->renderer().contains("REDWOOD") || m_context->renderer().contains("JUNIPER") || m_context->renderer().contains("CYPRESS") || m_context->renderer().contains("HEMLOCK") || m_context->renderer().contains("PALM") || m_context->renderer().contains("EVERGREEN") || m_context->renderer().contains("SUMO") || m_context->renderer().contains("SUMO2") || m_context->renderer().contains("BARTS") || m_context->renderer().contains("TURKS") || m_context->renderer().contains("CAICOS") || m_context->renderer().contains("CAYMAN"))) {
886 m_chipClass = detectRadeonClass(m_chipset);
887 m_driver = Driver_R600G;
888 }
889
890 // RadeonSI
891 else if ((m_context->vendor() == "X.Org" || m_context->vendor() == "AMD") && (m_context->renderer().contains("TAHITI") || m_context->renderer().contains("PITCAIRN") || m_context->renderer().contains("VERDE") || m_context->renderer().contains("OLAND") || m_context->renderer().contains("HAINAN") || m_context->renderer().contains("BONAIRE") || m_context->renderer().contains("KAVERI") || m_context->renderer().contains("KABINI") || m_context->renderer().contains("HAWAII") || m_context->renderer().contains("MULLINS") || m_context->renderer().contains("TOPAZ") || m_context->renderer().contains("TONGA") || m_context->renderer().contains("FIJI") || m_context->renderer().contains("CARRIZO") || m_context->renderer().contains("STONEY") || m_context->renderer().contains("POLARIS10") || m_context->renderer().contains("POLARIS11") || m_context->renderer().contains("POLARIS12") || m_context->renderer().contains("VEGAM") || m_context->renderer().contains("VEGA10") || m_context->renderer().contains("VEGA12") || m_context->renderer().contains("VEGA20") || m_context->renderer().contains("RAVEN") || m_context->renderer().contains("RAVEN2") || m_context->renderer().contains("RENOIR") || m_context->renderer().contains("ARCTURUS") || m_context->renderer().contains("NAVI10") || m_context->renderer().contains("NAVI12") || m_context->renderer().contains("NAVI14"))) {
892 m_chipClass = detectRadeonClass(m_context->renderer());
893 m_driver = Driver_RadeonSI;
894 }
895
896 // Nouveau
897 else if (m_context->vendor() == "nouveau") {
898 m_chipClass = detectNVidiaClass(m_chipset);
899 m_driver = Driver_Nouveau;
900 }
901
902 // softpipe
903 else if (m_chipset == "softpipe") {
904 m_driver = Driver_Softpipe;
905 }
906
907 // llvmpipe
908 else if (m_chipset == "llvmpipe") {
909 m_driver = Driver_Llvmpipe;
910 }
911
912 // SVGA3D
913 else if (m_context->vendor() == "VMware, Inc." && m_chipset.contains("SVGA3D")) {
914 m_driver = Driver_VMware;
915 }
916
917 // virgl
918 else if (m_context->renderer() == "virgl") {
919 m_driver = Driver_Virgl;
920 }
921 }
922
923 // Driver/GPU specific features
924 // ====================================================
925 if (isRadeon()) {
926 if (m_chipClass < R300) {
927 // fallback to NoCompositing for R100 and R200
928 m_recommendedCompositor = NoCompositing;
929 } else if (m_chipClass < R600) {
930 // NoCompositing due to NPOT limitations not supported by KWin's shaders
931 m_recommendedCompositor = NoCompositing;
932 } else {
933 m_recommendedCompositor = OpenGLCompositing;
934 }
935
936 if (driver() == Driver_R600G || (driver() == Driver_R600C && m_context->renderer().contains("DRI2"))) {
937 m_looseBinding = true;
938 }
939 }
940
941 if (isNvidia()) {
942 if (m_driver == Driver_NVidia) {
943 m_looseBinding = true;
944 m_preferBufferSubData = true;
945 }
946
947 if (m_chipClass < NV40) {
948 m_recommendedCompositor = NoCompositing;
949 } else {
950 m_recommendedCompositor = OpenGLCompositing;
951 }
952 }
953
954 if (isIntel()) {
955 // see https://bugs.freedesktop.org/show_bug.cgi?id=80349#c1
956 m_looseBinding = false;
957
958 if (m_chipClass < I915) {
959 m_recommendedCompositor = NoCompositing;
960 } else {
961 m_recommendedCompositor = OpenGLCompositing;
962 }
963 }
964
965 if (isPanfrost()) {
966 m_recommendedCompositor = OpenGLCompositing;
967 }
968
969 if (isLima()) {
970 m_recommendedCompositor = OpenGLCompositing;
971 }
972
973 if (isVideoCore4()) {
974 // OpenGL works, but is much slower than QPainter
975 m_recommendedCompositor = QPainterCompositing;
976 }
977
978 if (isVideoCore3D()) {
979 // OpenGL works, but is much slower than QPainter
980 m_recommendedCompositor = QPainterCompositing;
981 }
982
984 // According to the reference implementation in
985 // mesa/demos/src/egl/opengles1/texture_from_pixmap
986 // the mesa egl implementation does not require a strict binding (so far).
987 m_looseBinding = true;
988 }
989
990 if (isSoftwareEmulation()) {
991 if (m_driver < Driver_Llvmpipe) {
992 // we recommend QPainter
993 m_recommendedCompositor = QPainterCompositing;
994 } else {
995 // llvmpipe does support GLSL
996 m_recommendedCompositor = OpenGLCompositing;
997 }
998 }
999
1000 if (m_driver == Driver_Qualcomm) {
1001 if (m_chipClass == Adreno1XX) {
1002 m_recommendedCompositor = NoCompositing;
1003 } else {
1004 // all other drivers support at least GLES 2
1005 m_recommendedCompositor = OpenGLCompositing;
1006 }
1007 }
1008
1009 if (m_chipClass == UnknownChipClass && m_driver == Driver_Unknown) {
1010 // we don't know the hardware. Let's be optimistic and assume OpenGL compatible hardware
1011 m_recommendedCompositor = OpenGLCompositing;
1012 }
1013
1014 if (isVirtualBox()) {
1015 m_virtualMachine = true;
1016 m_recommendedCompositor = OpenGLCompositing;
1017 }
1018
1019 if (isVMware()) {
1020 m_virtualMachine = true;
1021 m_recommendedCompositor = OpenGLCompositing;
1022 }
1023
1024 if (m_driver == Driver_Virgl) {
1025 m_virtualMachine = true;
1026 m_recommendedCompositor = OpenGLCompositing;
1027 }
1028}
1029
1030static void print(const QByteArray &label, QByteArrayView setting)
1031{
1032 qInfo("%-40s%s", label.data(), setting.data());
1033}
1034
1036{
1037 print(QByteArrayLiteral("OpenGL vendor string:"), m_context->vendor());
1038 print(QByteArrayLiteral("OpenGL renderer string:"), m_context->renderer());
1039 print(QByteArrayLiteral("OpenGL version string:"), m_context->openglVersionString());
1040 print(QByteArrayLiteral("OpenGL shading language version string:"), m_glsl_version);
1041 print(QByteArrayLiteral("Driver:"), driverToString8(m_driver));
1042 if (!isMesaDriver()) {
1043 print(QByteArrayLiteral("Driver version:"), m_driverVersion.toByteArray());
1044 }
1045 print(QByteArrayLiteral("GPU class:"), chipClassToString8(m_chipClass));
1046 print(QByteArrayLiteral("OpenGL version:"), m_context->openglVersion().toByteArray());
1047 print(QByteArrayLiteral("GLSL version:"), m_glslVersion.toByteArray());
1048 if (isMesaDriver()) {
1049 print(QByteArrayLiteral("Mesa version:"), mesaVersion().toByteArray());
1050 }
1051 print(QByteArrayLiteral("Requires strict binding:"), !m_looseBinding ? QByteArrayLiteral("yes") : QByteArrayLiteral("no"));
1052 print(QByteArrayLiteral("Virtual Machine:"), m_virtualMachine ? QByteArrayLiteral("yes") : QByteArrayLiteral("no"));
1053 print(QByteArrayLiteral("Timer query support:"), supports(GLFeature::TimerQuery) ? QByteArrayLiteral("yes") : QByteArrayLiteral("no"));
1054}
1055
1057{
1058 switch (feature) {
1060 return m_looseBinding;
1062 return m_packInvert;
1064 return m_context && m_context->supportsTimerQueries();
1065 }
1066 return false;
1067}
1068
1070{
1071 return m_context ? m_context->openglVersion() : Version();
1072}
1073
1075{
1076 return m_glslVersion;
1077}
1078
1080{
1081 return m_mesaVersion;
1082}
1083
1085{
1086 if (isMesaDriver()) {
1087 return mesaVersion();
1088 }
1089
1090 return m_driverVersion;
1091}
1092
1094{
1095 return m_driver;
1096}
1097
1099{
1100 return m_chipClass;
1101}
1102
1104{
1105 return mesaVersion().isValid();
1106}
1107
1109{
1110 return m_chipClass >= R100 && m_chipClass <= UnknownRadeon;
1111}
1112
1114{
1115 return m_chipClass >= NV10 && m_chipClass <= UnknownNVidia;
1116}
1117
1119{
1120 return m_chipClass >= I8XX && m_chipClass <= UnknownIntel;
1121}
1122
1124{
1125 return m_driver == Driver_VirtualBox;
1126}
1127
1129{
1130 return m_driver == Driver_VMware;
1131}
1132
1134{
1135 return m_driver == Driver_Virgl;
1136}
1137
1139{
1140 return m_context ? m_context->isSoftwareRenderer() : false;
1141}
1142
1144{
1145 return m_chipClass >= Adreno1XX && m_chipClass <= UnknownAdreno;
1146}
1147
1149{
1150 return m_chipClass >= MaliT7XX && m_chipClass <= UnknownPanfrost;
1151}
1152
1154{
1155 return m_chipClass >= Mali400 && m_chipClass <= UnknownLima;
1156}
1157
1159{
1160 return m_chipClass >= VC4_2_1 && m_chipClass <= UnknownVideoCore4;
1161}
1162
1164{
1165 return m_chipClass >= V3D_4_2 && m_chipClass <= UnknownVideoCore3D;
1166}
1167
1168QByteArrayView GLPlatform::glRendererString() const
1169{
1170 return m_context ? m_context->renderer() : "";
1171}
1172
1173QByteArrayView GLPlatform::glVendorString() const
1174{
1175 return m_context ? m_context->vendor() : "";
1176}
1177
1178QByteArrayView GLPlatform::glVersionString() const
1179{
1180 return m_context ? m_context->openglVersionString() : "";
1181}
1182
1184{
1185 return m_glsl_version;
1186}
1187
1189{
1190 return m_looseBinding;
1191}
1192
1194{
1195 return m_virtualMachine;
1196}
1197
1199{
1200 return m_recommendedCompositor;
1201}
1202
1204{
1205 return m_preferBufferSubData;
1206}
1207
1209{
1210 return m_platformInterface;
1211}
1212
1214{
1215 return m_context ? m_context->isOpenglES() : false;
1216}
1217
1218void GLPlatform::cleanup()
1219{
1220 s_platform.reset();
1221}
1222
1223} // namespace KWin
void printResults() const
bool isAdreno() const
Driver driver() const
Version glslVersion() const
void detect(OpenGLPlatformInterface platformInterface)
bool isVideoCore3D() const
bool isVideoCore4() const
QByteArrayView glVersionString() const
bool isVirtualMachine() const
CompositingType recommendedCompositor() const
static QString chipClassToString(ChipClass chipClass)
static QString driverToString(Driver driver)
QByteArrayView glVendorString() const
bool isVirgl() const
OpenGLPlatformInterface platformInterface() const
bool isNvidia() const
bool isPanfrost() const
bool isVirtualBox() const
static QByteArray driverToString8(Driver driver)
bool isGLES() const
Version glVersion() const
bool isLooseBinding() const
bool isMesaDriver() const
bool isLima() const
ChipClass chipClass() const
QByteArrayView glShadingLanguageVersionString() const
static QByteArray chipClassToString8(ChipClass chipClass)
bool isVMware() const
Version driverVersion() const
bool isIntel() const
Version mesaVersion() const
bool supports(GLFeature feature) const
QByteArrayView glRendererString() const
bool isSoftwareEmulation() const
bool isRadeon() const
bool preferBufferSubData() const
bool isValid() const
Definition version.cpp:24
static Version parseString(QByteArrayView versionString)
Definition version.cpp:44
QByteArray toByteArray() const
Definition version.cpp:79
GLFeature
Definition glplatform.h:26
@ Driver_V3D
Definition glplatform.h:67
@ Driver_R300G
Definition glplatform.h:49
@ Driver_Swrast
Definition glplatform.h:56
@ Driver_Qualcomm
Definition glplatform.h:61
@ Driver_VC4
Definition glplatform.h:66
@ Driver_VMware
Definition glplatform.h:60
@ Driver_VirtualBox
Definition glplatform.h:59
@ Driver_NVidia
Definition glplatform.h:54
@ Driver_Llvmpipe
Definition glplatform.h:58
@ Driver_R600G
Definition glplatform.h:51
@ Driver_RadeonSI
Definition glplatform.h:62
@ Driver_R200
Definition glplatform.h:47
@ Driver_Lima
Definition glplatform.h:65
@ Driver_R100
Definition glplatform.h:46
@ Driver_Virgl
Definition glplatform.h:63
@ Driver_Catalyst
Definition glplatform.h:55
@ Driver_R300C
Definition glplatform.h:48
@ Driver_Panfrost
Definition glplatform.h:64
@ Driver_Unknown
Definition glplatform.h:68
@ Driver_Intel
Definition glplatform.h:53
@ Driver_Nouveau
Definition glplatform.h:52
@ Driver_R600C
Definition glplatform.h:50
@ Driver_Softpipe
Definition glplatform.h:57
OpenGLPlatformInterface
Definition globals.h:42
@ EglPlatformInterface
Definition globals.h:45
@ NoOpenGLPlatformInterface
Definition globals.h:43
CompositingType
Definition globals.h:28
@ QPainterCompositing
Definition globals.h:39
@ NoCompositing
Definition globals.h:29
@ OpenGLCompositing
Definition globals.h:37
bool match(QList< GlobalShortcut > &shortcuts, Args... args)
ChipClass
Definition glplatform.h:72
@ NV40
Definition glplatform.h:95
@ BayTrail
Definition glplatform.h:107
@ NV30
Definition glplatform.h:94
@ UnknownVideoCore3D
Definition glplatform.h:151
@ IceLake
Definition glplatform.h:118
@ Adreno5XX
Definition glplatform.h:128
@ UnknownRadeon
Definition glplatform.h:89
@ CometLake
Definition glplatform.h:116
@ CoffeeLake
Definition glplatform.h:114
@ NV20
Definition glplatform.h:93
@ KabyLake
Definition glplatform.h:113
@ R300
Definition glplatform.h:76
@ VolcanicIslands
Definition glplatform.h:85
@ UnknownChipClass
Definition glplatform.h:153
@ MaliGXX
Definition glplatform.h:135
@ IvyBridge
Definition glplatform.h:105
@ VC4_2_1
Definition glplatform.h:146
@ ApolloLake
Definition glplatform.h:110
@ WhiskeyLake
Definition glplatform.h:115
@ R700
Definition glplatform.h:80
@ Adreno3XX
Definition glplatform.h:126
@ R600
Definition glplatform.h:79
@ UnknownPanfrost
Definition glplatform.h:136
@ Evergreen
Definition glplatform.h:81
@ UnknownVideoCore4
Definition glplatform.h:147
@ ArcticIslands
Definition glplatform.h:86
@ NV10
Definition glplatform.h:92
@ SandyBridge
Definition glplatform.h:104
@ G80
Definition glplatform.h:96
@ Adreno4XX
Definition glplatform.h:127
@ GeminiLake
Definition glplatform.h:112
@ UnknownAdreno
Definition glplatform.h:129
@ Adreno2XX
Definition glplatform.h:125
@ Skylake
Definition glplatform.h:111
@ Mali450
Definition glplatform.h:141
@ GF100
Definition glplatform.h:97
@ SeaIslands
Definition glplatform.h:84
@ MaliT8XX
Definition glplatform.h:134
@ CannonLake
Definition glplatform.h:117
@ R400
Definition glplatform.h:77
@ MaliT7XX
Definition glplatform.h:133
@ UnknownIntel
Definition glplatform.h:120
@ Haswell
Definition glplatform.h:106
@ UnknownLima
Definition glplatform.h:143
@ R100
Definition glplatform.h:74
@ Broadwell
Definition glplatform.h:109
@ Adreno1XX
Definition glplatform.h:124
@ UnknownNVidia
Definition glplatform.h:98
@ R500
Definition glplatform.h:78
@ NorthernIslands
Definition glplatform.h:82
@ SouthernIslands
Definition glplatform.h:83
@ Mali470
Definition glplatform.h:142
@ Mali400
Definition glplatform.h:140
@ Vega
Definition glplatform.h:87
@ Cherryview
Definition glplatform.h:108
@ R200
Definition glplatform.h:75
@ V3D_4_2
Definition glplatform.h:150
@ Navi
Definition glplatform.h:88
@ TigerLake
Definition glplatform.h:119