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));
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);
103QString QOpenGLProgramBinaryCache::cacheFileName(
const QByteArray &cacheKey)
const
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);
251 if (
const MemCacheEntry *
e = m_memCache.
object(cacheKey))
252 return setProgramBinary(programId,
e->format,
e->blob.constData(),
e->blob.size());
255 const QString fn = cacheFileName(cacheKey);
272 if (!verifyHeader(
buf)) {
286 p =
reinterpret_cast<const uchar *
>(
buf.constData());
292 if (vendor !=
info.glvendor) {
295 qCDebug(lcOpenGLProgramDiskCache) <<
"GL_VENDOR does not match" << vendor <<
info.glvendor;
301 qCDebug(lcOpenGLProgramDiskCache) <<
"GL_RENDERER does not match" <<
renderer <<
info.glrenderer;
306 if (version !=
info.glversion) {
307 qCDebug(lcOpenGLProgramDiskCache) <<
"GL_VERSION does not match" << version <<
info.glversion;
317 return setProgramBinary(programId, blobFormat,
p, blobSize)
318 && m_memCache.
insert(cacheKey,
new MemCacheEntry(
p, blobSize, blobFormat));
336#if QT_CONFIG(temporaryfile)
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);
419 QString filename = cacheFileName(cacheKey);
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) {
427 filename = cacheFileName(cacheKey);
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.
QByteArray toHex(char separator='\0') const
Returns a hex encoded copy of the 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.
void addData(QByteArrayView data) noexcept
Adds the characters in bytes to the cryptographic hash.
QByteArray result() const
Returns the final hash value.
static QDir root()
Returns the root directory.
bool mkpath(const QString &dirPath) const
Creates the directory path dirPath.
\inmodule QtCore \reentrant
bool isWritable() const
Returns true if the user can write to the file; otherwise returns false.
qint64 size() const
Returns the file size in bytes.
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
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...
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
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
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#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
typedef GLsizei(GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC)(GLuint target)
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLsizei GLenum * binaryFormat
#define GL_NUM_PROGRAM_BINARY_FORMATS
#define GL_PROGRAM_BINARY_LENGTH
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)
QFileInfo info(fileName)
[8]
void writeFile(QCborStreamWriter &writer, const QString &fileName)
[6]
QSvgRenderer * renderer
[0]
QList< ShaderDesc > shaders
QByteArray cacheKey() const