53 #ifndef QGLSHADERCACHE_MEEGO_P_H 54 #define QGLSHADERCACHE_MEEGO_P_H 56 #include <QtCore/qglobal.h> 58 #if defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE) && defined(QT_OPENGL_ES_2) 60 #include <QtCore/qcryptographichash.h> 61 #include <QtCore/qsharedmemory.h> 62 #include <QtCore/qsystemsemaphore.h> 64 #ifndef QT_BOOTSTRAPPED 65 # include <GLES2/gl2ext.h> 67 #if defined(QT_DEBUG) || defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE_TRACE) 108 struct CachedShaderHeader
123 ShaderCacheMaxEntries = 20
126 typedef CachedShaderHeader CachedShaderHeaders[ShaderCacheMaxEntries];
131 ShaderCacheDataSize = 1024 * ShaderCacheMaxEntries -
sizeof(CachedShaderHeaders) - 2 *
sizeof(
int)
137 inline int availableSize()
const {
return ShaderCacheDataSize - dataSize; }
146 CachedShaderHeaders headers;
149 char data[ShaderCacheDataSize];
153 #ifdef QT_DEBUG_SHADER_CACHE 154 static QDebug shaderCacheDebug()
162 class ShaderCacheSharedMemory
165 ShaderCacheSharedMemory()
171 if (!attachSemaphore.acquire()) {
172 shaderCacheDebug() <<
"Unable to require shader cache semaphore:" << attachSemaphore.errorString();
178 shaderCacheDebug() <<
"Attached to shader cache";
182 if (shm.create(
sizeof(CachedShaders))) {
183 shaderCacheDebug() <<
"Created new shader cache";
186 shaderCacheDebug() <<
"Unable to create shader cache:" << shm.errorString();
190 attachSemaphore.release();
193 inline bool isAttached()
const {
return shm.isAttached(); }
195 inline bool lock() {
return shm.lock(); }
196 inline bool unlock() {
return shm.
unlock(); }
197 inline void *
data() {
return shm.data(); }
200 ~ShaderCacheSharedMemory()
203 shaderCacheDebug() <<
"Unable to detach shader cache" << shm.errorString();
207 void initializeCache()
212 void *
data = shm.data();
215 memset(data, 0,
sizeof(CachedShaders));
221 class ShaderCacheLocker
224 inline ShaderCacheLocker(ShaderCacheSharedMemory *cache)
225 : shm(cache->
lock() ? cache : (ShaderCacheSharedMemory *)0)
228 shaderCacheDebug() <<
"Unable to lock shader cache" << cache->errorString();
231 inline bool isLocked()
const {
return shm; }
233 inline ~ShaderCacheLocker()
238 shaderCacheDebug() <<
"Unable to unlock shader cache" << shm->errorString();
242 ShaderCacheSharedMemory *shm;
245 #ifdef QT_BOOTSTRAPPED 249 static void traceCacheOverflow(
const char *message)
251 #if defined(QT_DEBUG) || defined (QT_MEEGO_EXPERIMENTAL_SHADERCACHE_TRACE) 253 syslog(LOG_DEBUG, message);
256 shaderCacheDebug() << message;
267 static int qt_cache_index_unlocked(
const QByteArray &md5Sum, CachedShaders *cache)
269 for (
int i = 0; i < cache->shaderCount; ++i) {
278 static int qt_cache_index(
const QByteArray &md5Sum)
280 ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
281 if (!shm || !shm->isAttached())
286 ShaderCacheLocker locker(shm);
287 if (!locker.isLocked())
290 void *data = shm->data();
293 CachedShaders *cache =
reinterpret_cast<CachedShaders *
>(
data);
295 return qt_cache_index_unlocked(md5Sum, cache);
303 Q_ASSERT(shaderIndex >= 0 && shaderIndex <= ShaderCacheMaxEntries);
306 ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
307 if (!shm || !shm->isAttached())
310 void *data = shm->data();
313 CachedShaders *cache =
reinterpret_cast<CachedShaders *
>(
data);
315 shaderCacheDebug() <<
"fetching cached shader at index" << shaderIndex
316 <<
"dataIndex" << cache->headers[shaderIndex].index
317 <<
"size" << cache->headers[shaderIndex].size
318 <<
"format" << cache->headers[shaderIndex].format;
322 glProgramBinaryOES(programId, cache->headers[shaderIndex].format,
323 cache->data + cache->headers[shaderIndex].index,
324 cache->headers[shaderIndex].size);
333 ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
334 if (!shm || !shm->isAttached())
337 void *data = shm->data();
340 CachedShaders *cache =
reinterpret_cast<CachedShaders *
>(
data);
342 ShaderCacheLocker locker(shm);
343 if (!locker.isLocked())
346 int cacheIdx = cache->shaderCount;
347 if (cacheIdx >= ShaderCacheMaxEntries) {
348 traceCacheOverflow(
"Qt OpenGL shader cache index overflow!");
354 if (qt_cache_index_unlocked(md5Sum, cache) != -1)
357 shaderCacheDebug() <<
"Caching shader at index" << cacheIdx;
359 GLint binaryLength = 0;
363 shaderCacheDebug() <<
"Unable to determine binary shader size!";
367 if (binaryLength > cache->availableSize()) {
368 traceCacheOverflow(
"Qt OpenGL shader cache data overflow!");
374 glGetProgramBinaryOES(shader->
programId(), binaryLength, &size, &
format,
375 cache->data + cache->dataSize);
378 shaderCacheDebug() <<
"Unable to get binary shader!";
382 cache->headers[cacheIdx].index = cache->dataSize;
383 cache->dataSize += binaryLength;
384 ++cache->shaderCount;
385 cache->headers[cacheIdx].size = binaryLength;
386 cache->headers[cacheIdx].format =
format;
388 memcpy(cache->headers[cacheIdx].md5Sum, md5Sum.
constData(), 16);
390 shaderCacheDebug() <<
"cached shader size" << size
391 <<
"format" << format
392 <<
"binarySize" << binaryLength
393 <<
"cache index" << cacheIdx
394 <<
"data index" << cache->headers[cacheIdx].index;
413 md5Hash.addData(fragSource);
414 md5Hash.addData(vertexSource);
416 md5Sum = md5Hash.result();
421 return cacheIndex() != -1;
428 cacheIdx = qt_cache_index(md5Sum);
434 if (cacheIndex() == -1)
436 return qt_cached_shader(program, ctx, cacheIdx);
441 return qt_cache_shader(program, ctx, md5Sum);
The QDebug class provides an output stream for debugging information.
#define QT_END_NAMESPACE
This macro expands to.
GLuint programId() const
Returns the OpenGL identifier associated with this shader program.
void unlock()
Unlocks the lock.
The QByteArray class provides an array of bytes.
The QSystemSemaphore class provides a general counting system semaphore.
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
The QString class provides a Unicode character string.
Q_GUI_EXPORT QString errorString(EGLint code=eglGetError())
#define QT_BEGIN_NAMESPACE
This macro expands to.
The QGLContext class encapsulates an OpenGL rendering context.
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
static const char * data(const QByteArray &arr)
#define QT_VERSION_STR
This macro expands to a string that specifies Qt's version number (for example, "4.
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
int length() const
Same as size().
const char * constData() const
Returns a pointer to the data stored in the byte array.
int qstrncmp(const char *str1, const char *str2, uint len)
static QReadWriteLock lock
The QSharedMemory class provides access to a shared memory segment.
static QString applicationName()
#define qPrintable(string)
The QGLShaderProgram class allows OpenGL shader programs to be linked and used.
The QCryptographicHash class provides a way to generate cryptographic hashes.