qopengl.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/opengl/qopengl.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qopengl.h"-
41#include "qopengl_p.h"-
42-
43#include "qopenglcontext.h"-
44#include "qopenglfunctions.h"-
45#include "qoffscreensurface.h"-
46-
47#include <QtCore/QDebug>-
48#include <QtCore/QJsonDocument>-
49#include <QtCore/QJsonValue>-
50#include <QtCore/QJsonObject>-
51#include <QtCore/QJsonArray>-
52#include <QtCore/QTextStream>-
53#include <QtCore/QFile>-
54#include <QtCore/QDir>-
55-
56#include <set>-
57-
58QT_BEGIN_NAMESPACE-
59-
60#if defined(QT_OPENGL_3)-
61typedef const GLubyte * (QOPENGLF_APIENTRYP qt_glGetStringi)(GLenum, GLuint);-
62#endif-
63-
64QOpenGLExtensionMatcher::QOpenGLExtensionMatcher()-
65{-
66 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
67 QOpenGLFunctions *funcs = ctx->functions();-
68 const char *extensionStr = 0;-
69-
70 if (ctx->isOpenGLES() || ctx->format().majorVersion() < 3)-
71 extensionStr = reinterpret_cast<const char *>(funcs->glGetString(GL_EXTENSIONS));-
72-
73 if (extensionStr) {-
74 QByteArray ba(extensionStr);-
75 QList<QByteArray> extensions = ba.split(' ');-
76 m_extensions = extensions.toSet();-
77 } else {-
78#ifdef QT_OPENGL_3-
79 // clear error state-
80 while (funcs->glGetError()) {}-
81-
82 if (ctx) {-
83 qt_glGetStringi glGetStringi = (qt_glGetStringi)ctx->getProcAddress("glGetStringi");-
84-
85 if (!glGetStringi)-
86 return;-
87-
88 GLint numExtensions = 0;-
89 funcs->glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);-
90-
91 for (int i = 0; i < numExtensions; ++i) {-
92 const char *str = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));-
93 m_extensions.insert(str);-
94 }-
95 }-
96#endif // QT_OPENGL_3-
97 }-
98}-
99-
100/* Helpers to read out the list of features matching a device from-
101 * a Chromium driver bug list. Note that not all keys are supported and-
102 * some may behave differently: gl_vendor is a substring match instead of regex.-
103 {-
104 "entries": [-
105 {-
106 "id": 20,-
107 "description": "Disable EXT_draw_buffers on GeForce GT 650M on Linux due to driver bugs",-
108 "os": {-
109 "type": "linux"-
110 },-
111 // Optional: "exceptions" list-
112 "vendor_id": "0x10de",-
113 "device_id": ["0x0fd5"],-
114 "multi_gpu_category": "any",-
115 "features": [-
116 "disable_ext_draw_buffers"-
117 ]-
118 },-
119 ....-
120 }-
121*/-
122-
123QDebug operator<<(QDebug d, const QOpenGLConfig::Gpu &g)-
124{-
125 QDebugStateSaver s(d);-
126 d.nospace();-
127 d << "Gpu(";-
128 if (g.isValid()) {-
129 d << "vendor=" << hex << showbase <<g.vendorId << ", device=" << g.deviceId-
130 << "version=" << g.driverVersion;-
131 } else {-
132 d << 0;-
133 }-
134 d << ')';-
135 return d;-
}
static inline QString valueKey() { return QStringLiteral("value"); }
static inline QString opKey() { return QStringLiteral("op"); }
static inline QString versionKey() { return QStringLiteral("version"); }
static inline QString releaseKey() { return QStringLiteral("release"); }
static inline QString typeKey() { return QStringLiteral("type"); }
static inline QString osKey() { return QStringLiteral("os"); }
static inline QString vendorIdKey() { return QStringLiteral("vendor_id"); }
static inline QString glVendorKey() { return QStringLiteral("gl_vendor"); }
static inline QString deviceIdKey() { return QStringLiteral("device_id"); }
static inline QString driverVersionKey() { return QStringLiteral("driver_version"); }
static inline QString driverDescriptionKey() { return QStringLiteral("driver_description"); }
static inline QString featuresKey() { return QStringLiteral("features"); }
static inline QString idKey() { return QStringLiteral("id"); }
static inline QString descriptionKey() { return QStringLiteral("description"); }
static inline QString exceptionsKey() { return QStringLiteral("exceptions");}
137-
138typedef QJsonArray::ConstIterator JsonArrayConstIt;-
139-
140static inline bool contains(const QJsonArray &haystack, unsigned needle)-
141{-
142 for (JsonArrayConstIt it = haystack.constBegin(), cend = haystack.constEnd(); it != cend; ++it) {-
143 if (needle == it->toString().toUInt(Q_NULLPTR, /* base */ 0))-
144 return true;-
145 }-
146 return false;-
147}-
148-
149static inline bool contains(const QJsonArray &haystack, const QString &needle)-
150{-
151 for (JsonArrayConstIt it = haystack.constBegin(), cend = haystack.constEnd(); it != cend; ++it) {-
152 if (needle == it->toString())-
153 return true;-
154 }-
155 return false;-
156}-
157-
158namespace {-
159enum Operator { NotEqual, LessThan, LessEqualThan, Equals, GreaterThan, GreaterEqualThan };-
160static const char operators[][3] = {"!=", "<", "<=", "=", ">", ">="};-
161-
162// VersionTerm describing a version term consisting of number and operator-
163// found in os.version and driver_version.-
164struct VersionTerm {-
165 VersionTerm() : op(NotEqual) {}-
166 static VersionTerm fromJson(const QJsonValue &v);-
167 bool isNull() const { return number.isNull(); }-
168 bool matches(const QVersionNumber &other) const;-
169-
170 QVersionNumber number;-
171 Operator op;-
172};-
173-
174bool VersionTerm::matches(const QVersionNumber &other) const-
175{-
176 if (isNull() || other.isNull()) {-
177 qWarning("called with invalid parameters");-
178 return false;-
179 }-
180 switch (op) {-
181 case NotEqual:-
182 return other != number;-
183 case LessThan:-
184 return other < number;-
185 case LessEqualThan:-
186 return other <= number;-
187 case Equals:-
188 return other == number;-
189 case GreaterThan:-
190 return other > number;-
191 case GreaterEqualThan:-
192 return other >= number;-
193 }-
194 return false;-
195}-
196-
197VersionTerm VersionTerm::fromJson(const QJsonValue &v)-
198{-
199 VersionTerm result;-
200 if (!v.isObject())
!v.isObject()Description
TRUEnever evaluated
FALSEnever evaluated
0
201 return result;
never executed: return result;
0
202 const QJsonObject o = v.toObject();-
203 result.number = QVersionNumber::fromString(o.value(valueKey()).QLatin1String("value")).toString());-
204 const QString opS = o.value(opKey()).QLatin1String("op")).toString();-
205 for (size_t i = 0; i < sizeof(operators) / sizeof(operators[0]); ++i) {
i < sizeof(ope...(operators[0])Description
TRUEnever evaluated
FALSEnever evaluated
0
206 if (opS == QLatin1String(operators[i])) {
opS == QLatin1...(operators[i])Description
TRUEnever evaluated
FALSEnever evaluated
0
207 result.op = static_cast<Operator>(i);-
208 break;
never executed: break;
0
209 }-
210 }
never executed: end of block
0
211 return result;
never executed: return result;
0
212}-
213-
214// OS term consisting of name and optional version found in-
215// under "os" in main array and in "exceptions" lists.-
216struct OsTypeTerm-
217{-
218 static OsTypeTerm fromJson(const QJsonValue &v);-
219 static QString hostOs();-
220 static QVersionNumber hostKernelVersion() { return QVersionNumber::fromString(QSysInfo::kernelVersion()); }-
221 static QString hostOsRelease() {-
222 QString ver;-
223#ifdef Q_OS_WIN-
224 switch (QSysInfo::windowsVersion()) {-
225 case QSysInfo::WV_XP:-
226 case QSysInfo::WV_2003:-
227 ver = QStringLiteral("xp");-
228 break;-
229 case QSysInfo::WV_VISTA:-
230 ver = QStringLiteral("vista");-
231 break;-
232 case QSysInfo::WV_WINDOWS7:-
233 ver = QStringLiteral("7");-
234 break;-
235 case QSysInfo::WV_WINDOWS8:-
236 ver = QStringLiteral("8");-
237 break;-
238 case QSysInfo::WV_WINDOWS8_1:-
239 ver = QStringLiteral("8.1");-
240 break;-
241 case QSysInfo::WV_WINDOWS10:-
242 ver = QStringLiteral("10");-
243 break;-
244 default:-
245 break;-
246 }-
247#endif-
248 return ver;-
249 }-
250-
251 bool isNull() const { return type.isEmpty(); }-
252 bool matches(const QString &osName, const QVersionNumber &kernelVersion, const QString &osRelease) const-
253 {-
254 if (isNull() || osName.isEmpty() || kernelVersion.isNull()) {-
255 qWarning("called with invalid parameters");-
256 return false;-
257 }-
258 if (type != osName)-
259 return false;-
260 if (!versionTerm.isNull() && !versionTerm.matches(kernelVersion))-
261 return false;-
262 // release is a list of Windows versions where the rule should match-
263 if (!release.isEmpty() && !contains(release, osRelease))-
264 return false;-
265 return true;-
266 }-
267-
268 QString type;-
269 VersionTerm versionTerm;-
270 QJsonArray release;-
271};-
272-
273OsTypeTerm OsTypeTerm::fromJson(const QJsonValue &v)-
274{-
275 OsTypeTerm result;-
276 if (!v.isObject())
!v.isObject()Description
TRUEnever evaluated
FALSEnever evaluated
0
277 return result;
never executed: return result;
0
278 const QJsonObject o = v.toObject();-
279 result.type = o.value(typeKey()).QLatin1String("type")).toString();-
280 result.versionTerm = VersionTerm::fromJson(o.value(versionKey()));QLatin1String("version")));-
281 result.release = o.value(releaseKey()).QLatin1String("release")).toArray();-
282 return result;
never executed: return result;
0
283}-
284-
285QString OsTypeTerm::hostOs()-
286{-
287 // Determine Host OS.-
288#if defined(Q_OS_WIN)-
289 return QStringLiteral("win");-
290#elif defined(Q_OS_LINUX)-
291 return QStringLiteral("linux");-
292#elif defined(Q_OS_OSX)-
293 return QStringLiteral("macosx");-
294#elif defined(Q_OS_ANDROID)-
295 return QStringLiteral("android");-
296#else-
297 return QString();-
298#endif-
299}-
300} // anonymous namespace-
301-
302static QString msgSyntaxWarning(const QJsonObject &object, const QString &what)-
303{-
304 QString result;-
305 QTextStream(&result) << "Id " << object.value(idKey()).QLatin1String("id")).toInt()-
306 << " (\"" << object.value(descriptionKey()).QLatin1String("description")).toString()-
307 << "\"): " << what;-
308 return result;
never executed: return result;
0
309}-
310-
311// Check whether an entry matches. Called recursively for-
312// "exceptions" list.-
313-
314static bool matches(const QJsonObject &object,-
315 const QString &osName,-
316 const QVersionNumber &kernelVersion,-
317 const QString &osRelease,-
318 const QOpenGLConfig::Gpu &gpu)-
319{-
320 const OsTypeTerm os = OsTypeTerm::fromJson(object.value(osKey()));QLatin1String("os")));-
321 if (!os.isNull() && !os.matches(osName, kernelVersion, osRelease))
!os.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
!os.matches(os...on, osRelease)Description
TRUEnever evaluated
FALSEnever evaluated
0
322 return false;
never executed: return false;
0
323-
324 const QJsonValue exceptionsV = object.value(exceptionsKey());QLatin1String("exceptions"));-
325 if (exceptionsV.isArray()) {
exceptionsV.isArray()Description
TRUEnever evaluated
FALSEnever evaluated
0
326 const QJsonArray exceptionsA = exceptionsV.toArray();-
327 for (JsonArrayConstIt it = exceptionsA.constBegin(), cend = exceptionsA.constEnd(); it != cend; ++it) {
it != cendDescription
TRUEnever evaluated
FALSEnever evaluated
0
328 if (matches(it->toObject(), osName, kernelVersion, osRelease, gpu))
matches(it->to...sRelease, gpu)Description
TRUEnever evaluated
FALSEnever evaluated
0
329 return false;
never executed: return false;
0
330 }
never executed: end of block
0
331 }
never executed: end of block
0
332-
333 const QJsonValue vendorV = object.value(vendorIdKey());QLatin1String("vendor_id"));-
334 if (vendorV.isString()) {
vendorV.isString()Description
TRUEnever evaluated
FALSEnever evaluated
0
335 if (gpu.vendorId != vendorV.toString().toUInt(Q_NULLPTR, /* base */ 0))
gpu.vendorId !...nt(nullptr, 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
336 return false;
never executed: return false;
0
337 } else {
never executed: end of block
0
338 if (object.contains(glVendorKey()))QLatin1String("gl_vendor"))) {
object.contain...("gl_vendor"))Description
TRUEnever evaluated
FALSEnever evaluated
0
339 const QByteArray glVendorV = object.value(glVendorKey()).QLatin1String("gl_vendor")).toString().toUtf8();-
340 if (!gpu.glVendor.contains(glVendorV))
!gpu.glVendor....ins(glVendorV)Description
TRUEnever evaluated
FALSEnever evaluated
0
341 return false;
never executed: return false;
0
342 }
never executed: end of block
0
343 }
never executed: end of block
0
344-
345 if (gpu.deviceId) {
gpu.deviceIdDescription
TRUEnever evaluated
FALSEnever evaluated
0
346 const QJsonValue deviceIdV = object.value(deviceIdKey());QLatin1String("device_id"));-
347 switch (deviceIdV.type()) {-
348 case QJsonValue::Array:
never executed: case QJsonValue::Array:
0
349 if (!contains(deviceIdV.toArray(), gpu.deviceId))
!contains(devi... gpu.deviceId)Description
TRUEnever evaluated
FALSEnever evaluated
0
350 return false;
never executed: return false;
0
351 break;
never executed: break;
0
352 case QJsonValue::Undefined:
never executed: case QJsonValue::Undefined:
0
353 case QJsonValue::Null:
never executed: case QJsonValue::Null:
0
354 break;
never executed: break;
0
355 default:
never executed: default:
0
356 qWarning().noquote()-
357 << msgSyntaxWarning(object,-
358 QLatin1String("Device ID must be of type array."));-
359 }
never executed: end of block
0
360 }-
361 if (!gpu.driverVersion.isNull()) {
!gpu.driverVersion.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
362 const QJsonValue driverVersionV = object.value(driverVersionKey());QLatin1String("driver_version"));-
363 switch (driverVersionV.type()) {-
364 case QJsonValue::Object:
never executed: case QJsonValue::Object:
0
365 if (!VersionTerm::fromJson(driverVersionV).matches(gpu.driverVersion))
!VersionTerm::...driverVersion)Description
TRUEnever evaluated
FALSEnever evaluated
0
366 return false;
never executed: return false;
0
367 break;
never executed: break;
0
368 case QJsonValue::Undefined:
never executed: case QJsonValue::Undefined:
0
369 case QJsonValue::Null:
never executed: case QJsonValue::Null:
0
370 break;
never executed: break;
0
371 default:
never executed: default:
0
372 qWarning().noquote()-
373 << msgSyntaxWarning(object,-
374 QLatin1String("Driver version must be of type object."));-
375 }
never executed: end of block
0
376 }-
377-
378 if (!gpu.driverDescription.isEmpty()) {
!gpu.driverDes...tion.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
379 const QJsonValue driverDescriptionV = object.value(driverDescriptionKey());QLatin1String("driver_description"));-
380 if (driverDescriptionV.isString()) {
driverDescriptionV.isString()Description
TRUEnever evaluated
FALSEnever evaluated
0
381 if (!gpu.driverDescription.contains(driverDescriptionV.toString().toUtf8()))
!gpu.driverDes...ng().toUtf8())Description
TRUEnever evaluated
FALSEnever evaluated
0
382 return false;
never executed: return false;
0
383 }
never executed: end of block
0
384 }
never executed: end of block
0
385-
386 return true;
never executed: return true;
0
387}-
388-
389static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,-
390 const QString &osName,-
391 const QVersionNumber &kernelVersion,-
392 const QString &osRelease,-
393 const QJsonDocument &doc,-
394 QSet<QString> *result,-
395 QString *errorMessage)-
396{-
397 result->clear();-
398 errorMessage->clear();-
399 const QJsonValue entriesV = doc.object().value(QStringLiteralQLatin1String("entries"));-
400 if (!entriesV.isArray()) {
!entriesV.isArray()Description
TRUEnever evaluated
FALSEnever evaluated
0
401 *errorMessage = QLatin1String("No entries read.");-
402 return false;
never executed: return false;
0
403 }-
404-
405 const QJsonArray entriesA = entriesV.toArray();-
406 for (JsonArrayConstIt eit = entriesA.constBegin(), ecend = entriesA.constEnd(); eit != ecend; ++eit) {
eit != ecendDescription
TRUEnever evaluated
FALSEnever evaluated
0
407 if (eit->isObject()) {
eit->isObject()Description
TRUEnever evaluated
FALSEnever evaluated
0
408 const QJsonObject object = eit->toObject();-
409 if (matches(object, osName, kernelVersion, osRelease, gpu)) {
matches(object...sRelease, gpu)Description
TRUEnever evaluated
FALSEnever evaluated
0
410 const QJsonValue featuresListV = object.value(featuresKey());QLatin1String("features"));-
411 if (featuresListV.isArray()) {
featuresListV.isArray()Description
TRUEnever evaluated
FALSEnever evaluated
0
412 const QJsonArray featuresListA = featuresListV.toArray();-
413 for (JsonArrayConstIt fit = featuresListA.constBegin(), fcend = featuresListA.constEnd(); fit != fcend; ++fit)
fit != fcendDescription
TRUEnever evaluated
FALSEnever evaluated
0
414 result->insert(fit->toString());
never executed: result->insert(fit->toString());
0
415 }
never executed: end of block
0
416 }
never executed: end of block
0
417 }
never executed: end of block
0
418 }
never executed: end of block
0
419 return true;
never executed: return true;
0
420}-
421-
422static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,-
423 const QString &osName,-
424 const QVersionNumber &kernelVersion,-
425 const QString &osRelease,-
426 const QByteArray &jsonAsciiData,-
427 QSet<QString> *result, QString *errorMessage)-
428{-
429 result->clear();-
430 errorMessage->clear();-
431 QJsonParseError error;-
432 const QJsonDocument document = QJsonDocument::fromJson(jsonAsciiData, &error);-
433 if (document.isNull()) {-
434 const int lineNumber = 1 + jsonAsciiData.left(error.offset).count('\n');-
435 QTextStream str(errorMessage);-
436 str << "Failed to parse data: \"" << error.errorString()-
437 << "\" at line " << lineNumber << " (offset: "-
438 << error.offset << ").";-
439 return false;-
440 }-
441 return readGpuFeatures(gpu, osName, kernelVersion, osRelease, document, result, errorMessage);-
442}-
443-
444static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,-
445 const QString &osName,-
446 const QVersionNumber &kernelVersion,-
447 const QString &osRelease,-
448 const QString &fileName,-
449 QSet<QString> *result, QString *errorMessage)-
450{-
451 result->clear();-
452 errorMessage->clear();-
453 QFile file(fileName);-
454 if (!file.open(QIODevice::ReadOnly)) {-
455 QTextStream str(errorMessage);-
456 str << "Cannot open \"" << QDir::toNativeSeparators(fileName) << "\": "-
457 << file.errorString();-
458 return false;-
459 }-
460 const bool success = readGpuFeatures(gpu, osName, kernelVersion, osRelease, file.readAll(), result, errorMessage);-
461 if (!success) {-
462 errorMessage->prepend(QLatin1String("Error reading \"")-
463 + QDir::toNativeSeparators(fileName)-
464 + QLatin1String("\": "));-
465 }-
466 return success;-
467}-
468-
469QSet<QString> QOpenGLConfig::gpuFeatures(const QOpenGLConfig::Gpu &gpu,-
470 const QString &osName,-
471 const QVersionNumber &kernelVersion,-
472 const QString &osRelease,-
473 const QJsonDocument &doc)-
474{-
475 QSet<QString> result;-
476 QString errorMessage;-
477 if (!readGpuFeatures(gpu, osName, kernelVersion, osRelease, doc, &result, &errorMessage))-
478 qWarning().noquote() << errorMessage;-
479 return result;-
480}-
481-
482QSet<QString> QOpenGLConfig::gpuFeatures(const QOpenGLConfig::Gpu &gpu,-
483 const QString &osName,-
484 const QVersionNumber &kernelVersion,-
485 const QString &osRelease,-
486 const QString &fileName)-
487{-
488 QSet<QString> result;-
489 QString errorMessage;-
490 if (!readGpuFeatures(gpu, osName, kernelVersion, osRelease, fileName, &result, &errorMessage))-
491 qWarning().noquote() << errorMessage;-
492 return result;-
493}-
494-
495QSet<QString> QOpenGLConfig::gpuFeatures(const Gpu &gpu, const QJsonDocument &doc)-
496{-
497 return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), OsTypeTerm::hostOsRelease(), doc);-
498}-
499-
500QSet<QString> QOpenGLConfig::gpuFeatures(const Gpu &gpu, const QString &fileName)-
501{-
502 return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), OsTypeTerm::hostOsRelease(), fileName);-
503}-
504-
505QOpenGLConfig::Gpu QOpenGLConfig::Gpu::fromContext()-
506{-
507 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
508 QScopedPointer<QOpenGLContext> tmpContext;-
509 QScopedPointer<QOffscreenSurface> tmpSurface;-
510 if (!ctx) {-
511 tmpContext.reset(new QOpenGLContext);-
512 if (!tmpContext->create()) {-
513 qWarning("QOpenGLConfig::Gpu::fromContext: Failed to create temporary context");-
514 return QOpenGLConfig::Gpu();-
515 }-
516 tmpSurface.reset(new QOffscreenSurface);-
517 tmpSurface->setFormat(tmpContext->format());-
518 tmpSurface->create();-
519 tmpContext->makeCurrent(tmpSurface.data());-
520 }-
521-
522 QOpenGLConfig::Gpu gpu;-
523 ctx = QOpenGLContext::currentContext();-
524 const GLubyte *p = ctx->functions()->glGetString(GL_VENDOR);-
525 if (p)-
526 gpu.glVendor = QByteArray(reinterpret_cast<const char *>(p));-
527-
528 return gpu;-
529}-
530-
531Q_GUI_EXPORT std::set<QByteArray> *qgpu_features(const QString &filename)-
532{-
533 const QSet<QString> features = QOpenGLConfig::gpuFeatures(QOpenGLConfig::Gpu::fromContext(), filename);-
534 std::set<QByteArray> *result = new std::set<QByteArray>;-
535 foreachfor (const QString &feature ,: features)-
536 result->insert(feature.toUtf8());
never executed: result->insert(feature.toUtf8());
0
537 return result;
never executed: return result;
0
538}-
539-
540QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9