~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kwin/libkwineffects/kwinglplatform.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************
 
2
 KWin - the KDE window manager
 
3
 This file is part of the KDE project.
 
4
 
 
5
Copyright (C) 2010 Fredrik Höglund <fredrik@kde.org>
 
6
 
 
7
This program is free software; you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation; either version 2 of the License, or
 
10
(at your option) any later version.
 
11
 
 
12
This program is distributed in the hope that it will be useful,
 
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
*********************************************************************/
 
20
 
 
21
#include "kwinglplatform.h"
 
22
#include "kwinglutils.h"
 
23
 
 
24
#include <kwinglobals.h>
 
25
 
 
26
#include <QRegExp>
 
27
#include <QStringList>
 
28
#include <QDebug>
 
29
 
 
30
#include <sys/utsname.h>
 
31
 
 
32
#include <iostream>
 
33
#include <iomanip>
 
34
#include <ios>
 
35
 
 
36
#ifdef KWIN_HAVE_OPENGL
 
37
 
 
38
namespace KWin
 
39
{
 
40
 
 
41
GLPlatform *GLPlatform::s_platform = 0;
 
42
 
 
43
static qint64 parseVersionString(const QByteArray &version)
 
44
{
 
45
    // Skip any leading non digit
 
46
    int start = 0;
 
47
    while (start < version.length() && !QChar(version[start]).isDigit())
 
48
        start++;
 
49
 
 
50
    // Strip any non digit, non '.' characters from the end
 
51
    int end = start;
 
52
    while (end < version.length() && (version[end] == '.' || QChar(version[end]).isDigit()))
 
53
        end++;
 
54
 
 
55
    const QByteArray result = version.mid(start, end-start);
 
56
    const QList<QByteArray> tokens = result.split('.');
 
57
    const qint64 major = tokens.at(0).toInt();
 
58
    const qint64 minor = tokens.count() > 1 ? tokens.at(1).toInt() : 0;
 
59
    const qint64 patch = tokens.count() > 2 ? tokens.at(2).toInt() : 0;
 
60
 
 
61
    return kVersionNumber(major, minor, patch);
 
62
}
 
63
 
 
64
static qint64 getXServerVersion()
 
65
{
 
66
    qint64 major, minor, patch;
 
67
 
 
68
    Display *dpy = display();
 
69
    if (strstr(ServerVendor(dpy), "X.Org")) {
 
70
        const int release  = VendorRelease(dpy);
 
71
        major = (release / 10000000);
 
72
        minor = (release /   100000) % 100;
 
73
        patch = (release /     1000) % 100;
 
74
    } else {
 
75
        major = 0;
 
76
        minor = 0;
 
77
        patch = 0;
 
78
    }
 
79
 
 
80
    return kVersionNumber(major, minor, patch);
 
81
}
 
82
 
 
83
static qint64 getKernelVersion()
 
84
{
 
85
    struct utsname name;
 
86
    uname(&name);
 
87
 
 
88
    if (QByteArray(name.sysname) == "Linux")
 
89
        return parseVersionString(name.release);
 
90
 
 
91
    return 0;
 
92
}
 
93
 
 
94
// Extracts the portion of a string that matches a regular expression
 
95
static QString extract(const QString &string, const QString &match, int offset = 0)
 
96
{
 
97
    QString result;
 
98
    QRegExp rx(match);
 
99
    int pos = rx.indexIn(string, offset);
 
100
    if (pos != -1)
 
101
        result = string.mid(pos, rx.matchedLength());
 
102
    return result;
 
103
}
 
104
 
 
105
static ChipClass detectRadeonClass(const QString &chipset)
 
106
{
 
107
    if (chipset.isEmpty())
 
108
        return UnknownRadeon;
 
109
 
 
110
    if (chipset.contains("R100")  ||
 
111
            chipset.contains("RV100") ||
 
112
            chipset.contains("RS100"))
 
113
        return R100;
 
114
 
 
115
    if (chipset.contains("RV200") ||
 
116
            chipset.contains("RS200") ||
 
117
            chipset.contains("R200")  ||
 
118
            chipset.contains("RV250") ||
 
119
            chipset.contains("RS300") ||
 
120
            chipset.contains("RV280"))
 
121
        return R200;
 
122
 
 
123
    if (chipset.contains("R300")  ||
 
124
            chipset.contains("R350")  ||
 
125
            chipset.contains("R360")  ||
 
126
            chipset.contains("RV350") ||
 
127
            chipset.contains("RV370") ||
 
128
            chipset.contains("RV380"))
 
129
        return R300;
 
130
 
 
131
    if (chipset.contains("R420")  ||
 
132
            chipset.contains("R423")  ||
 
133
            chipset.contains("R430")  ||
 
134
            chipset.contains("R480")  ||
 
135
            chipset.contains("R481")  ||
 
136
            chipset.contains("RV410") ||
 
137
            chipset.contains("RS400") ||
 
138
            chipset.contains("RC410") ||
 
139
            chipset.contains("RS480") ||
 
140
            chipset.contains("RS482") ||
 
141
            chipset.contains("RS600") ||
 
142
            chipset.contains("RS690") ||
 
143
            chipset.contains("RS740"))
 
144
        return R400;
 
145
 
 
146
    if (chipset.contains("RV515") ||
 
147
            chipset.contains("R520")  ||
 
148
            chipset.contains("RV530") ||
 
149
            chipset.contains("R580")  ||
 
150
            chipset.contains("RV560") ||
 
151
            chipset.contains("RV570"))
 
152
        return R500;
 
153
 
 
154
    if (chipset.contains("R600")  ||
 
155
            chipset.contains("RV610") ||
 
156
            chipset.contains("RV630") ||
 
157
            chipset.contains("RV670") ||
 
158
            chipset.contains("RV620") ||
 
159
            chipset.contains("RV635") ||
 
160
            chipset.contains("RS780") ||
 
161
            chipset.contains("RS880"))
 
162
        return R600;
 
163
 
 
164
    if (chipset.contains("R700")  ||
 
165
            chipset.contains("RV770") ||
 
166
            chipset.contains("RV730") ||
 
167
            chipset.contains("RV710") ||
 
168
            chipset.contains("RV740"))
 
169
        return R700;
 
170
 
 
171
    if (chipset.contains("EVERGREEN") ||  // Not an actual chipset, but returned by R600G in 7.9
 
172
            chipset.contains("CEDAR")     ||
 
173
            chipset.contains("REDWOOD")   ||
 
174
            chipset.contains("JUNIPER")   ||
 
175
            chipset.contains("CYPRESS")   ||
 
176
            chipset.contains("PALM")      ||
 
177
            chipset.contains("HEMLOCK"))
 
178
        return Evergreen;
 
179
 
 
180
    if (chipset.contains("BARTS") ||
 
181
            chipset.contains("TURKS") ||
 
182
            chipset.contains("CAICOS"))
 
183
        return NorthernIslands;
 
184
 
 
185
    QString name = extract(chipset, "HD [0-9]{4}"); // HD followed by a space and 4 digits
 
186
    if (!name.isEmpty()) {
 
187
        const int id = name.right(4).toInt();
 
188
        if (id == 6250 || id == 6310)   // Palm
 
189
            return Evergreen;
 
190
 
 
191
        if (id >= 6000 && id < 7000)
 
192
            return NorthernIslands;    // HD 6xxx
 
193
 
 
194
        if (id >= 5000 && id < 6000)
 
195
            return Evergreen;          // HD 5xxx
 
196
 
 
197
        if (id >= 4000 && id < 5000)
 
198
            return R700;               // HD 4xxx
 
199
 
 
200
        if (id >= 2000 && id < 4000)    // HD 2xxx/3xxx
 
201
            return R600;
 
202
 
 
203
        return UnknownRadeon;
 
204
    }
 
205
 
 
206
    name = extract(chipset, "X[0-9]{3,4}"); // X followed by 3-4 digits
 
207
    if (!name.isEmpty()) {
 
208
        const int id = name.mid(1, -1).toInt();
 
209
 
 
210
        // X1xxx
 
211
        if (id >= 1300)
 
212
            return R500;
 
213
 
 
214
        // X7xx, X8xx, X12xx, 2100
 
215
        if ((id >= 700 && id < 1000) || id >= 1200)
 
216
            return R400;
 
217
 
 
218
        // X200, X3xx, X5xx, X6xx, X10xx, X11xx
 
219
        if ((id >= 300 && id < 700) || (id >= 1000 && id < 1200))
 
220
            return R300;
 
221
 
 
222
        return UnknownRadeon;
 
223
    }
 
224
 
 
225
    name = extract(chipset, "\\b[0-9]{4}\\b"); // A group of 4 digits
 
226
    if (!name.isEmpty()) {
 
227
        const int id = name.toInt();
 
228
 
 
229
        // 7xxx
 
230
        if (id >= 7000 && id < 8000)
 
231
            return R100;
 
232
 
 
233
        // 8xxx, 9xxx
 
234
        if (id >= 8000 && id < 9500)
 
235
            return R200;
 
236
 
 
237
        // 9xxx
 
238
        if (id >= 9500)
 
239
            return R300;
 
240
 
 
241
        if (id == 2100)
 
242
            return R400;
 
243
    }
 
244
 
 
245
    return UnknownRadeon;
 
246
}
 
247
 
 
248
static ChipClass detectNVidiaClass(const QString &chipset)
 
249
{
 
250
    QString name = extract(chipset, "\\bNV[0-9,A-F]{2}\\b"); // NV followed by two hexadecimal digits
 
251
    if (!name.isEmpty()) {
 
252
        const int id = chipset.mid(2, -1).toInt(0, 16); // Strip the 'NV' from the id
 
253
 
 
254
        switch(id & 0xf0) {
 
255
        case 0x00:
 
256
        case 0x10:
 
257
            return NV10;
 
258
 
 
259
        case 0x20:
 
260
            return NV20;
 
261
 
 
262
        case 0x30:
 
263
            return NV30;
 
264
 
 
265
        case 0x40:
 
266
        case 0x60:
 
267
            return NV40;
 
268
 
 
269
        case 0x50:
 
270
        case 0x80:
 
271
        case 0x90:
 
272
        case 0xA0:
 
273
            return G80;
 
274
 
 
275
        default:
 
276
            return UnknownNVidia;
 
277
        }
 
278
    }
 
279
 
 
280
    if (chipset.contains("GeForce2") || chipset.contains("GeForce 256"))
 
281
        return NV10;
 
282
 
 
283
    if (chipset.contains("GeForce3"))
 
284
        return NV20;
 
285
 
 
286
    if (chipset.contains("GeForce4")) {
 
287
        if (chipset.contains("MX 420")  ||
 
288
                chipset.contains("MX 440")  || // including MX 440SE
 
289
                chipset.contains("MX 460")  ||
 
290
                chipset.contains("MX 4000") ||
 
291
                chipset.contains("PCX 4300"))
 
292
            return NV10;
 
293
 
 
294
        return NV20;
 
295
    }
 
296
 
 
297
    // GeForce 5,6,7,8,9
 
298
    name = extract(chipset, "GeForce (FX |PCX |Go )?\\d{4}(M|\\b)").trimmed();
 
299
    if (!name.isEmpty()) {
 
300
        if (!name[name.length() - 1].isDigit())
 
301
            name.chop(1);
 
302
 
 
303
        const int id = name.right(4).toInt();
 
304
        if (id < 6000)
 
305
            return NV30;
 
306
 
 
307
        if (id >= 6000 && id < 8000)
 
308
            return NV40;
 
309
 
 
310
        if (id >= 8000)
 
311
            return G80;
 
312
 
 
313
        return UnknownNVidia;
 
314
    }
 
315
 
 
316
    // GeForce 100/200/300/400/500
 
317
    name = extract(chipset, "GeForce (G |GT |GTX |GTS )?\\d{3}(M|\\b)").trimmed();
 
318
    if (!name.isEmpty()) {
 
319
        if (!name[name.length() - 1].isDigit())
 
320
            name.chop(1);
 
321
 
 
322
        const int id = name.right(3).toInt();
 
323
        if (id >= 100 && id < 600) {
 
324
            if (id >= 400)
 
325
                return GF100;
 
326
 
 
327
            return G80;
 
328
        }
 
329
        return UnknownNVidia;
 
330
    }
 
331
 
 
332
    return UnknownNVidia;
 
333
}
 
334
 
 
335
static ChipClass detectIntelClass(const QByteArray &chipset)
 
336
{
 
337
    // GL 1.3, DX8? SM ?
 
338
    if (chipset.contains("845G")        ||
 
339
            chipset.contains("830M")        ||
 
340
            chipset.contains("852GM/855GM") ||
 
341
            chipset.contains("865G"))
 
342
        return I8XX;
 
343
 
 
344
    // GL 1.4, DX 9.0, SM 2.0
 
345
    if (chipset.contains("915G")   ||
 
346
            chipset.contains("E7221G") ||
 
347
            chipset.contains("915GM")  ||
 
348
            chipset.contains("945G")   ||   // DX 9.0c
 
349
            chipset.contains("945GM")  ||
 
350
            chipset.contains("945GME") ||
 
351
            chipset.contains("Q33")    ||   // GL1.5
 
352
            chipset.contains("Q35")    ||
 
353
            chipset.contains("G33")    ||
 
354
            chipset.contains("965Q")   ||   // GMA 3000, but apparently considered gen 4 by the driver
 
355
            chipset.contains("946GZ")  ||   // GMA 3000, but apparently considered gen 4 by the driver
 
356
            chipset.contains("IGD"))
 
357
        return I915;
 
358
 
 
359
    // GL 2.0, DX 9.0c, SM 3.0
 
360
    if (chipset.contains("965G")       ||
 
361
            chipset.contains("G45/G43")    || // SM 4.0
 
362
            chipset.contains("965GM")      || // GL 2.1
 
363
            chipset.contains("965GME/GLE") ||
 
364
            chipset.contains("GM45")       ||
 
365
            chipset.contains("Q45/Q43")    ||
 
366
            chipset.contains("G41")        ||
 
367
            chipset.contains("B43")        ||
 
368
            chipset.contains("Ironlake")   ||
 
369
            chipset.contains("Sandybridge"))  // GL 3.1, CL 1.1, DX 10.1
 
370
        return I965;
 
371
 
 
372
    return UnknownIntel;
 
373
}
 
374
 
 
375
static QString versionToString(qint64 version)
 
376
{
 
377
    int major = (version >> 32);
 
378
    int minor = (version >> 16) & 0xffff;
 
379
    int patch = version & 0xffff;
 
380
 
 
381
    QString string = QString::number(major) + QChar('.') + QString::number(minor);
 
382
    if (patch != 0)
 
383
        string += QChar('.') + QString::number(patch);
 
384
 
 
385
    return string;
 
386
}
 
387
 
 
388
static QString driverToString(Driver driver)
 
389
{
 
390
    switch(driver) {
 
391
    case Driver_R100:
 
392
        return "Radeon";
 
393
    case Driver_R200:
 
394
        return "R200";
 
395
    case Driver_R300C:
 
396
        return "R300C";
 
397
    case Driver_R300G:
 
398
        return "R300G";
 
399
    case Driver_R600C:
 
400
        return "R600C";
 
401
    case Driver_R600G:
 
402
        return "R600G";
 
403
    case Driver_Nouveau:
 
404
        return "Nouveau";
 
405
    case Driver_Intel:
 
406
        return "Intel";
 
407
    case Driver_NVidia:
 
408
        return "NVIDIA";
 
409
    case Driver_Catalyst:
 
410
        return "Catalyst";
 
411
    case Driver_Swrast:
 
412
        return "Software rasterizer";
 
413
    case Driver_Softpipe:
 
414
        return "softpipe";
 
415
    case Driver_Llvmpipe:
 
416
        return "LLVMpipe";
 
417
 
 
418
    default:
 
419
        return "Unknown";
 
420
    }
 
421
}
 
422
 
 
423
static QString chipClassToString(ChipClass chipClass)
 
424
{
 
425
    switch(chipClass) {
 
426
    case R100:
 
427
        return "R100";
 
428
    case R200:
 
429
        return "R200";
 
430
    case R300:
 
431
        return "R300";
 
432
    case R400:
 
433
        return "R400";
 
434
    case R500:
 
435
        return "R500";
 
436
    case R600:
 
437
        return "R600";
 
438
    case R700:
 
439
        return "R700";
 
440
    case Evergreen:
 
441
        return "EVERGREEN";
 
442
    case NorthernIslands:
 
443
        return "NI";
 
444
 
 
445
    case NV10:
 
446
        return "NV10";
 
447
    case NV20:
 
448
        return "NV20";
 
449
    case NV30:
 
450
        return "NV30";
 
451
    case NV40:
 
452
        return "NV40/G70";
 
453
    case G80:
 
454
        return "G80/G90";
 
455
    case GF100:
 
456
        return "GF100";
 
457
 
 
458
    case I8XX:
 
459
        return "i830/i835";
 
460
    case I915:
 
461
        return "i915/i945";
 
462
    case I965:
 
463
        return "i965";
 
464
    case SandyBridge:
 
465
        return "SandyBridge";
 
466
 
 
467
    default:
 
468
        return "Unknown";
 
469
    }
 
470
}
 
471
 
 
472
 
 
473
 
 
474
// -------
 
475
 
 
476
 
 
477
 
 
478
GLPlatform::GLPlatform()
 
479
    : m_driver(Driver_Unknown),
 
480
      m_chipClass(UnknownChipClass),
 
481
      m_mesaVersion(0),
 
482
      m_galliumVersion(0),
 
483
      m_looseBinding(false),
 
484
      m_directRendering(false),
 
485
      m_supportsGLSL(false),
 
486
      m_limitedGLSL(false)
 
487
{
 
488
}
 
489
 
 
490
GLPlatform::~GLPlatform()
 
491
{
 
492
}
 
493
 
 
494
void GLPlatform::detect()
 
495
{
 
496
    m_vendor       = (const char*)glGetString(GL_VENDOR);
 
497
    m_renderer     = (const char*)glGetString(GL_RENDERER);
 
498
    m_version      = (const char*)glGetString(GL_VERSION);
 
499
 
 
500
    const QByteArray extensions = (const char*)glGetString(GL_EXTENSIONS);
 
501
    m_extensions = QSet<QByteArray>::fromList(extensions.split(' '));
 
502
 
 
503
    // Parse the OpenGL version
 
504
    const QList<QByteArray> versionTokens = m_version.split(' ');
 
505
    if (versionTokens.count() > 0) {
 
506
        const QByteArray version = QByteArray(m_version);
 
507
        m_glVersion = parseVersionString(version);
 
508
    }
 
509
 
 
510
    // Parse the Mesa version
 
511
    const int mesaIndex = versionTokens.indexOf("Mesa");
 
512
    if (mesaIndex != -1) {
 
513
        const QByteArray version = versionTokens.at(mesaIndex + 1);
 
514
        m_mesaVersion = parseVersionString(version);
 
515
    }
 
516
 
 
517
#ifdef KWIN_HAVE_OPENGLES
 
518
    m_directRendering = true;
 
519
    m_supportsGLSL = true;
 
520
    m_textureNPOT = true;
 
521
#else
 
522
    GLXContext ctx = glXGetCurrentContext();
 
523
    m_directRendering = glXIsDirect(display(), ctx);
 
524
 
 
525
    m_supportsGLSL = m_extensions.contains("GL_ARB_shading_language_100") &&
 
526
                     m_extensions.contains("GL_ARB_shader_objects") &&
 
527
                     m_extensions.contains("GL_ARB_fragment_shader") &&
 
528
                     m_extensions.contains("GL_ARB_vertex_shader");
 
529
 
 
530
    m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two");
 
531
#endif
 
532
 
 
533
    m_serverVersion = getXServerVersion();
 
534
    m_kernelVersion = getKernelVersion();
 
535
 
 
536
    m_glslVersion = 0;
 
537
    m_glsl_version = QByteArray();
 
538
 
 
539
    if (m_supportsGLSL) {
 
540
        // Parse the GLSL version
 
541
        m_glsl_version = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
 
542
        m_glslVersion = parseVersionString(m_glsl_version);
 
543
    }
 
544
 
 
545
    m_chipset = "Unknown";
 
546
 
 
547
 
 
548
    // Mesa classic drivers
 
549
    // ====================================================
 
550
 
 
551
    // Radeon
 
552
    if (m_renderer.startsWith("Mesa DRI R")) {
 
553
        // Sample renderer string: Mesa DRI R600 (RV740 94B3) 20090101 x86/MMX/SSE2 TCL DRI2
 
554
        const QList<QByteArray> tokens = m_renderer.split(' ');
 
555
        const QByteArray chipClass = tokens.at(2);
 
556
        m_chipset = tokens.at(3).mid(1, -1); // Strip the leading '('
 
557
 
 
558
        if (chipClass == "R100")
 
559
            // Vendor: Tungsten Graphics, Inc.
 
560
            m_driver = Driver_R100;
 
561
 
 
562
        else if (chipClass == "R200")
 
563
            // Vendor: Tungsten Graphics, Inc.
 
564
            m_driver = Driver_R200;
 
565
 
 
566
        else if (chipClass == "R300")
 
567
            // Vendor: DRI R300 Project
 
568
            m_driver = Driver_R300C;
 
569
 
 
570
        else if (chipClass == "R600")
 
571
            // Vendor: Advanced Micro Devices, Inc.
 
572
            m_driver = Driver_R600C;
 
573
 
 
574
        m_chipClass = detectRadeonClass(m_chipset);
 
575
    }
 
576
 
 
577
    // Intel
 
578
    else if (m_renderer.contains("Intel")) {
 
579
        // Vendor: Tungsten Graphics, Inc.
 
580
        // Sample renderer string: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100328 2010Q1
 
581
 
 
582
        QByteArray chipset;
 
583
        if (m_renderer.startsWith("Intel(R) Integrated Graphics Device"))
 
584
            chipset = "IGD";
 
585
        else
 
586
            chipset = m_renderer;
 
587
 
 
588
        m_driver = Driver_Intel;
 
589
        m_chipClass = detectIntelClass(chipset);
 
590
    }
 
591
 
 
592
    // Gallium drivers
 
593
    // ====================================================
 
594
    else if (m_renderer.contains("Gallium")) {
 
595
        // Sample renderer string: Gallium 0.4 on AMD RV740
 
596
        const QList<QByteArray> tokens = m_renderer.split(' ');
 
597
        m_galliumVersion = parseVersionString(tokens.at(1));
 
598
        m_chipset = (tokens.at(3) == "AMD" || tokens.at(3) == "ATI") ?
 
599
                    tokens.at(4) : tokens.at(3);
 
600
 
 
601
        // R300G
 
602
        if (m_vendor == "X.Org R300 Project") {
 
603
            m_chipClass = detectRadeonClass(m_chipset);
 
604
            m_driver = Driver_R300G;
 
605
        }
 
606
 
 
607
        // R600G
 
608
        else if (m_vendor == "X.Org" &&
 
609
                (m_renderer.contains("R6")        ||
 
610
                 m_renderer.contains("R7")        ||
 
611
                 m_renderer.contains("RV6")       ||
 
612
                 m_renderer.contains("RV7")       ||
 
613
                 m_renderer.contains("RS780")     ||
 
614
                 m_renderer.contains("RS880")     ||
 
615
                 m_renderer.contains("CEDAR")     ||
 
616
                 m_renderer.contains("REDWOOD")   ||
 
617
                 m_renderer.contains("JUNIPER")   ||
 
618
                 m_renderer.contains("CYPRESS")   ||
 
619
                 m_renderer.contains("HEMLOCK")   ||
 
620
                 m_renderer.contains("PALM")      ||
 
621
                 m_renderer.contains("EVERGREEN") ||
 
622
                 m_renderer.contains("BARTS")     ||
 
623
                 m_renderer.contains("TURKS")     ||
 
624
                 m_renderer.contains("CAICOS"))) {
 
625
            m_chipClass = detectRadeonClass(m_chipset);
 
626
            m_driver = Driver_R600G;
 
627
        }
 
628
 
 
629
        // Nouveau
 
630
        else if (m_vendor == "nouveau") {
 
631
            m_chipClass = detectNVidiaClass(m_chipset);
 
632
            m_driver = Driver_Nouveau;
 
633
        }
 
634
 
 
635
        // softpipe
 
636
        else if (m_vendor == "VMware, Inc." && m_chipset == "softpipe" ) {
 
637
            m_driver = Driver_Softpipe;
 
638
        }
 
639
 
 
640
        // llvmpipe
 
641
        else if (m_vendor == "VMware, Inc." && m_chipset == "llvmpipe") {
 
642
            m_driver = Driver_Llvmpipe;
 
643
        }
 
644
    }
 
645
 
 
646
 
 
647
    // Properietary drivers
 
648
    // ====================================================
 
649
    else if (m_vendor == "ATI Technologies Inc.") {
 
650
        m_chipClass = detectRadeonClass(m_renderer);
 
651
        m_driver = Driver_Catalyst;
 
652
 
 
653
        if (versionTokens.count() > 1 && versionTokens.at(2)[0] == '(')
 
654
            m_driverVersion = parseVersionString(versionTokens.at(1));
 
655
        else if (versionTokens.count() > 0)
 
656
            m_driverVersion = parseVersionString(versionTokens.at(0));
 
657
        else
 
658
            m_driverVersion = 0;
 
659
    }
 
660
 
 
661
    else if (m_vendor == "NVIDIA Corporation") {
 
662
        m_chipClass = detectNVidiaClass(m_renderer);
 
663
        m_driver = Driver_NVidia;
 
664
 
 
665
        int index = versionTokens.indexOf("NVIDIA");
 
666
        if (versionTokens.count() > index)
 
667
            m_driverVersion = parseVersionString(versionTokens.at(index + 1));
 
668
        else
 
669
            m_driverVersion = 0;
 
670
    }
 
671
 
 
672
 
 
673
    // Driver/GPU specific features
 
674
    // ====================================================
 
675
    if (isRadeon()) {
 
676
        // R200 technically has a programmable pipeline, but since it's SM 1.4,
 
677
        // it's too limited to to be of any practical value to us.
 
678
        if (m_chipClass < R300)
 
679
            m_supportsGLSL = false;
 
680
 
 
681
        m_limitedGLSL = false;
 
682
        m_limitedNPOT = false;
 
683
 
 
684
        if (m_chipClass < R600) {
 
685
            if (driver() == Driver_Catalyst)
 
686
                m_textureNPOT = m_limitedNPOT = false; // Software fallback
 
687
            else if (driver() == Driver_R300G)
 
688
                m_limitedNPOT = m_textureNPOT;
 
689
 
 
690
            m_limitedGLSL = m_supportsGLSL;
 
691
        }
 
692
 
 
693
        if (driver() == Driver_R600G ||
 
694
                (driver() == Driver_R600C && m_renderer.contains("DRI2"))) {
 
695
            m_looseBinding = true;
 
696
        }
 
697
    }
 
698
 
 
699
    if (isNvidia()) {
 
700
        if (m_driver == Driver_NVidia && m_chipClass < NV40)
 
701
            m_supportsGLSL = false; // High likelihood of software emulation
 
702
 
 
703
        if (m_driver == Driver_NVidia)
 
704
            m_looseBinding = true;
 
705
 
 
706
        m_limitedNPOT = m_textureNPOT && m_chipClass < NV40;
 
707
        m_limitedGLSL = m_supportsGLSL && m_chipClass < G80;
 
708
    }
 
709
 
 
710
    if (isIntel()) {
 
711
        if (m_chipClass < I915)
 
712
            m_supportsGLSL = false;
 
713
 
 
714
        m_limitedGLSL = m_supportsGLSL && m_chipClass < I965;
 
715
    }
 
716
 
 
717
    // Loose binding is broken with Gallium drivers in Mesa 7.10
 
718
    if (isGalliumDriver() && mesaVersion() >= kVersionNumber(7, 10))
 
719
        m_looseBinding = false;
 
720
 
 
721
    if (isSoftwareEmulation()) {
 
722
        // Software emulation does not provide GLSL
 
723
        m_limitedGLSL = m_supportsGLSL = false;
 
724
    }
 
725
}
 
726
 
 
727
static void print(const QString &label, const QString &setting)
 
728
{
 
729
    std::cout << std::setw(40) << std::left
 
730
              << qPrintable(label) << qPrintable(setting) << std::endl;
 
731
}
 
732
 
 
733
void GLPlatform::printResults() const
 
734
{
 
735
    print("OpenGL vendor string:",   m_vendor);
 
736
    print("OpenGL renderer string:", m_renderer);
 
737
    print("OpenGL version string:",  m_version);
 
738
 
 
739
    if (m_supportsGLSL)
 
740
        print("OpenGL shading language version string:", m_glsl_version);
 
741
 
 
742
    print("Driver:", driverToString(m_driver));
 
743
    if (!isMesaDriver())
 
744
        print("Driver version:", versionToString(m_driverVersion));
 
745
 
 
746
    print("GPU class:", chipClassToString(m_chipClass));
 
747
 
 
748
    print("OpenGL version:", versionToString(m_glVersion));
 
749
 
 
750
    if (m_supportsGLSL)
 
751
        print("GLSL version:", versionToString(m_glslVersion));
 
752
 
 
753
    if (isMesaDriver())
 
754
        print("Mesa version:", versionToString(mesaVersion()));
 
755
    //if (galliumVersion() > 0)
 
756
    //    print("Gallium version:", versionToString(m_galliumVersion));
 
757
    if (serverVersion() > 0)
 
758
        print("X server version:", versionToString(m_serverVersion));
 
759
    if (kernelVersion() > 0)
 
760
        print("Linux kernel version:", versionToString(m_kernelVersion));
 
761
 
 
762
    print("Direct rendering:", m_directRendering ? "yes" : "no");
 
763
    print("Requires strict binding:", !m_looseBinding ? "yes" : "no");
 
764
    print("GLSL shaders:", m_supportsGLSL ? (m_limitedGLSL ? "limited" : "yes") : "no");
 
765
    print("Texture NPOT support:", m_textureNPOT ? (m_limitedNPOT ? "limited" : "yes") : "no");
 
766
}
 
767
 
 
768
bool GLPlatform::supports(GLFeature feature) const
 
769
{
 
770
    switch(feature) {
 
771
    case LooseBinding:
 
772
        return m_looseBinding;
 
773
 
 
774
    case GLSL:
 
775
        return m_supportsGLSL;
 
776
 
 
777
    case LimitedGLSL:
 
778
        return m_limitedGLSL;
 
779
 
 
780
    case TextureNPOT:
 
781
        return m_textureNPOT;
 
782
 
 
783
    case LimitedNPOT:
 
784
        return m_limitedNPOT;
 
785
 
 
786
    default:
 
787
        return false;
 
788
    }
 
789
}
 
790
 
 
791
qint64 GLPlatform::glVersion() const
 
792
{
 
793
    return m_glVersion;
 
794
}
 
795
 
 
796
qint64 GLPlatform::glslVersion() const
 
797
{
 
798
    return m_glslVersion;
 
799
}
 
800
 
 
801
qint64 GLPlatform::mesaVersion() const
 
802
{
 
803
    return m_mesaVersion;
 
804
}
 
805
 
 
806
qint64 GLPlatform::galliumVersion() const
 
807
{
 
808
    return m_galliumVersion;
 
809
}
 
810
 
 
811
qint64 GLPlatform::serverVersion() const
 
812
{
 
813
    return m_serverVersion;
 
814
}
 
815
 
 
816
qint64 GLPlatform::kernelVersion() const
 
817
{
 
818
    return m_kernelVersion;
 
819
}
 
820
 
 
821
qint64 GLPlatform::driverVersion() const
 
822
{
 
823
    if (isMesaDriver())
 
824
        return mesaVersion();
 
825
 
 
826
    return m_driverVersion;
 
827
}
 
828
 
 
829
Driver GLPlatform::driver() const
 
830
{
 
831
    return m_driver;
 
832
}
 
833
 
 
834
ChipClass GLPlatform::chipClass() const
 
835
{
 
836
    return m_chipClass;
 
837
}
 
838
 
 
839
bool GLPlatform::isMesaDriver() const
 
840
{
 
841
    return mesaVersion() > 0;
 
842
}
 
843
 
 
844
bool GLPlatform::isGalliumDriver() const
 
845
{
 
846
    return galliumVersion() > 0;
 
847
}
 
848
 
 
849
bool GLPlatform::isRadeon() const
 
850
{
 
851
    return m_chipClass >= R100 && m_chipClass <= UnknownRadeon;
 
852
}
 
853
 
 
854
bool GLPlatform::isNvidia() const
 
855
{
 
856
    return m_chipClass >= NV10 && m_chipClass <= UnknownNVidia;
 
857
}
 
858
 
 
859
bool GLPlatform::isIntel() const
 
860
{
 
861
    return m_chipClass >= I8XX && m_chipClass <= UnknownIntel;
 
862
}
 
863
 
 
864
bool GLPlatform::isSoftwareEmulation() const
 
865
{
 
866
    return m_driver == Driver_Softpipe || m_driver == Driver_Swrast || m_driver == Driver_Llvmpipe;
 
867
}
 
868
 
 
869
} // namespace KWin
 
870
 
 
871
#endif // KWIN_HAVE_OPENGL
 
872