5#include <QOpenGLContext>
6#include <QOpenGLExtraFunctions>
8#include <QStandardPaths>
11#include <QCoreApplication>
12#include <QCryptographicHash>
16#include <private/qcore_unix_p.h>
25#ifndef GL_CONTEXT_LOST
26#define GL_CONTEXT_LOST 0x0507
29#ifndef GL_PROGRAM_BINARY_LENGTH
30#define GL_PROGRAM_BINARY_LENGTH 0x8741
33#ifndef GL_NUM_PROGRAM_BINARY_FORMATS
34#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
57 const char *vendor =
reinterpret_cast<const char *
>(
f->glGetString(GL_VENDOR));
58 const char *
renderer =
reinterpret_cast<const char *
>(
f->glGetString(GL_RENDERER));
59 const char *version =
reinterpret_cast<const char *
>(
f->glGetString(GL_VERSION));
72 keyBuilder.addData(
shader.source);
74 return keyBuilder.result().toHex();
84 : m_cacheWritable(
false)
88 m_globalCacheDir = sharedCachePath +
subPath;
91 if (!sharedCachePath.isEmpty()) {
92 m_currentCacheDir = m_globalCacheDir;
95 if (!m_cacheWritable) {
96 m_currentCacheDir = m_localCacheDir;
100 qCDebug(lcOpenGLProgramDiskCache,
"Cache location '%s' writable = %d",
qPrintable(m_currentCacheDir), m_cacheWritable);
108#define BASE_HEADER_SIZE (int(4 * sizeof(quint32)))
109#define FULL_HEADER_SIZE(stringsSize) (BASE_HEADER_SIZE + 12 + stringsSize + 8)
110#define PADDING_SIZE(fullHeaderSize) (((fullHeaderSize + 3) & ~3) - fullHeaderSize)
128bool QOpenGLProgramBinaryCache::verifyHeader(
const QByteArray &
buf)
const
131 qCDebug(lcOpenGLProgramDiskCache,
"Cached size too small");
134 const uchar *
p =
reinterpret_cast<const uchar *
>(
buf.constData());
136 qCDebug(lcOpenGLProgramDiskCache,
"Magic does not match");
140 qCDebug(lcOpenGLProgramDiskCache,
"Version does not match");
144 qCDebug(lcOpenGLProgramDiskCache,
"Qt version does not match");
148 qCDebug(lcOpenGLProgramDiskCache,
"Architecture does not match");
154bool QOpenGLProgramBinaryCache::setProgramBinary(
uint programId,
uint blobFormat,
const void *
p,
uint blobSize)
163#if QT_CONFIG(opengles2)
164 if (
context->isOpenGLES() &&
context->format().majorVersion() < 3) {
165 initializeProgramBinaryOES(
context);
166 programBinaryOES(programId, blobFormat,
p, blobSize);
169 funcs->glProgramBinary(programId, blobFormat,
p, blobSize);
172 if (err != GL_NO_ERROR) {
173 qCDebug(lcOpenGLProgramDiskCache,
"Program binary failed to load for program %u, size %d, "
174 "format 0x%x, err = 0x%x",
175 programId, blobSize, blobFormat, err);
178 GLint linkStatus = 0;
180 if (linkStatus != GL_TRUE) {
181 qCDebug(lcOpenGLProgramDiskCache,
"Program binary failed to load for program %u, size %d, "
182 "format 0x%x, linkStatus = 0x%x, err = 0x%x",
183 programId, blobSize, blobFormat, linkStatus, err);
187 qCDebug(lcOpenGLProgramDiskCache,
"Program binary set for program %u, size %d, format 0x%x, err = 0x%x",
188 programId, blobSize, blobFormat, err);
204 munmap(
ptr, mapSize);
210 off_t offs = lseek(
fd, 0, SEEK_END);
211 if (offs == (off_t) -1) {
215 mapSize =
static_cast<size_t>(offs);
216 ptr = mmap(
nullptr, mapSize, PROT_READ, MAP_SHARED,
fd, 0);
252 return setProgramBinary(programId, e->format, e->blob.constData(), e->blob.size());
272 if (!verifyHeader(
buf)) {
273 undertaker.setActive();
280 undertaker.setActive();
286 p =
reinterpret_cast<const uchar *
>(
buf.constData());
292 if (vendor !=
info.glvendor) {
295 qCDebug(lcOpenGLProgramDiskCache) <<
"GL_VENDOR does not match" << vendor <<
info.glvendor;
296 undertaker.setActive();
301 qCDebug(lcOpenGLProgramDiskCache) <<
"GL_RENDERER does not match" <<
renderer <<
info.glrenderer;
302 undertaker.setActive();
306 if (version !=
info.glversion) {
307 qCDebug(lcOpenGLProgramDiskCache) <<
"GL_VERSION does not match" << version <<
info.glversion;
308 undertaker.setActive();
317 return setProgramBinary(programId, blobFormat,
p, blobSize)
318 && m_memCache.
insert(
cacheKey,
new MemCacheEntry(
p, blobSize, blobFormat));
336#if QT_CONFIG(temporaryfile)
337 QSaveFile
f(filename);
355 if (!m_cacheWritable)
377 const int totalSize =
headerSize + paddingSize + blobSize;
379 qCDebug(lcOpenGLProgramDiskCache,
"Program binary is %d bytes, err = 0x%x, total %d", blobSize,
funcs->glGetError(), totalSize);
400 for (
int i = 0;
i < paddingSize; ++
i)
404#if QT_CONFIG(opengles2)
405 if (
context->isOpenGLES() &&
context->format().majorVersion() < 3) {
407 initializeProgramBinaryOES(
context);
408 getProgramBinaryOES(programId, blobSize, &outSize, &blobFormat,
p);
411 funcs->glGetProgramBinary(programId, blobSize, &outSize, &blobFormat,
p);
412 if (blobSize != outSize) {
413 qCDebug(lcOpenGLProgramDiskCache,
"glGetProgramBinary returned size %d instead of %d", outSize, blobSize);
421 if (!
ok && m_currentCacheDir == m_globalCacheDir) {
422 m_currentCacheDir = m_localCacheDir;
424 qCDebug(lcOpenGLProgramDiskCache,
"Cache location changed to '%s' writable = %d",
425 qPrintable(m_currentCacheDir), m_cacheWritable);
426 if (m_cacheWritable) {
432 qCDebug(lcOpenGLProgramDiskCache,
"Failed to write %s to shader cache",
qPrintable(filename));
435#if QT_CONFIG(opengles2)
438 if (m_programBinaryOESInitialized)
440 m_programBinaryOESInitialized =
true;
453 qCDebug(lcOpenGLProgramDiskCache,
"Shader cache disabled via app attribute");
457 qCDebug(lcOpenGLProgramDiskCache,
"Shader cache disabled via env var");
463 if (
ctx->isOpenGLES()) {
464 qCDebug(lcOpenGLProgramDiskCache,
"OpenGL ES v%d context",
ctx->format().majorVersion());
465 if (
ctx->format().majorVersion() >= 3) {
468 const bool hasExt =
ctx->hasExtension(
"GL_OES_get_program_binary");
469 qCDebug(lcOpenGLProgramDiskCache,
"GL_OES_get_program_binary support = %d", hasExt);
474 const bool hasExt =
ctx->hasExtension(
"GL_ARB_get_program_binary");
475 qCDebug(lcOpenGLProgramDiskCache,
"GL_ARB_get_program_binary support = %d", hasExt);
482 qCDebug(lcOpenGLProgramDiskCache,
"Supported binary format count = %d", fmtCount);
483 m_supported = fmtCount > 0;
486 qCDebug(lcOpenGLProgramDiskCache,
"Shader cache supported = %d", m_supported);
DeferredFileRemove(const QString &fn)
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
T * object(const Key &key) const noexcept
bool insert(const Key &key, T *object, qsizetype cost=1)
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
static QDir root()
Returns the root directory.
bool isWritable() const
Returns true if the user can write to the file system entry this QFileInfo refers to; otherwise retur...
bool remove()
Removes the file specified by fileName().
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
QOpenGLProgramBinaryCache()
bool load(const QByteArray &cacheKey, uint programId)
void save(const QByteArray &cacheKey, uint programId)
QOpenGLProgramBinarySupportCheck(QOpenGLContext *context)
The QOpenGLSharedResource class is used to keep track of resources that are shared between OpenGL con...
static QString writableLocation(StandardLocation type)
\macro QT_RESTRICTED_CAST_FROM_ASCII
const QChar * constData() const
Returns a pointer to the data stored in the QString.
qsizetype size() const noexcept
Returns the number of characters in this string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString buildAbi()
static VulkanServerBufferGlFunctions * funcs
QMap< QString, QString > map
[6]
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
@ AA_DisableShaderDiskCache
constexpr Initialization Uninitialized
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
static qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
static int qt_safe_close(int fd)
static const QPainterPath::ElementType * subPath(const QPainterPath::ElementType *t, const QPainterPath::ElementType *end, const qreal *points, bool *closed)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
static QString header(const QString &name)
static const qint64 headerSize
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static QByteArray cacheKey(Args &&...args)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
static ControlElement< T > * ptr(QWidget *widget)
#define QOPENGLF_APIENTRYP
GLsizei GLsizei GLenum void * binary
typedef GLint(GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program
GLsizei const GLfloat * v
[13]
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
typedef GLsizei(GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC)(GLuint target)
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLenum GLuint GLenum GLsizei const GLchar * buf
GLsizei GLsizei GLenum * binaryFormat
#define GL_NUM_PROGRAM_BINARY_FORMATS
#define GL_PROGRAM_BINARY_LENGTH
GLsizei GLsizei GLuint * shaders
static bool qt_ensureWritableDir(const QString &name)
const quint32 BINSHADER_VERSION
static bool writeFile(const QString &filename, const QByteArray &data)
const quint32 BINSHADER_QTVERSION
static quint32 readUInt(const uchar **p)
#define PADDING_SIZE(fullHeaderSize)
static void writeStr(uchar **p, const QByteArray &str)
static QByteArray readStr(const uchar **p)
const quint32 BINSHADER_MAGIC
static void writeUInt(uchar **p, quint32 value)
#define FULL_HEADER_SIZE(stringsSize)
#define qPrintable(string)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
static QT_BEGIN_NAMESPACE uint readUInt(const uchar *data)
static void writeUInt(uchar *data, uint i)
void writeFile(QCborStreamWriter &writer, const QString &fileName)
[6]
QSvgRenderer * renderer
[0]
QByteArray cacheKey() const