summaryrefslogtreecommitdiffstats
path: root/src/opengl/gl2paintengineex
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-08-16 09:29:44 +0200
committerSamuel Rødal <samuel.rodal@nokia.com>2011-08-29 10:24:55 +0200
commitaaa4a26f82f99fa8724841eba91bad029306e0ce (patch)
tree3d24e874bff00efc0e73af610bc80e645d14f789 /src/opengl/gl2paintengineex
parent00fd783a39d55d2365ddead4fab2cc06091c119f (diff)
Move GL resource handling enablers to QtGui.
Made resource handling more robust by attempting to free GL resources in the correct thread, and not forcing a context to become current to free resources. Change-Id: Ie81d4005b608972375755571d9b50ce82080709b Reviewed-on: http://codereview.qt.nokia.com/3258 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
Diffstat (limited to 'src/opengl/gl2paintengineex')
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp55
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h1
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache.cpp25
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache_p.h9
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp5
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp70
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h48
7 files changed, 134 insertions, 79 deletions
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index 4c50089f6d..05a612c311 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -44,6 +44,8 @@
#include "qpaintengineex_opengl2_p.h"
#include "qglshadercache_p.h"
+#include <QtGui/private/qguiglcontext_qpa_p.h>
+
#if defined(QT_DEBUG)
#include <QMetaEnum>
#endif
@@ -52,18 +54,50 @@
QT_BEGIN_NAMESPACE
+class QGLEngineSharedShadersResource : public QGLSharedResource
+{
+public:
+ QGLEngineSharedShadersResource(QGuiGLContext *ctx)
+ : QGLSharedResource(ctx->shareGroup())
+ , m_shaders(new QGLEngineSharedShaders(QGLContext::fromGuiGLContext(ctx)))
+ {
+ }
+
+ ~QGLEngineSharedShadersResource()
+ {
+ delete m_shaders;
+ }
+
+ void invalidateResource()
+ {
+ delete m_shaders;
+ m_shaders = 0;
+ }
+
+ void freeResource(QGuiGLContext *)
+ {
+ }
+
+ QGLEngineSharedShaders *shaders() const { return m_shaders; }
+
+private:
+ QGLEngineSharedShaders *m_shaders;
+};
+
class QGLShaderStorage
{
public:
QGLEngineSharedShaders *shadersForThread(const QGLContext *context) {
- QGLContextGroupResource<QGLEngineSharedShaders> *&shaders = m_storage.localData();
+ QGLMultiGroupSharedResource *&shaders = m_storage.localData();
if (!shaders)
- shaders = new QGLContextGroupResource<QGLEngineSharedShaders>();
- return shaders->value(context);
+ shaders = new QGLMultiGroupSharedResource;
+ QGLEngineSharedShadersResource *resource =
+ shaders->value<QGLEngineSharedShadersResource>(context->contextHandle());
+ return resource ? resource->shaders() : 0;
}
private:
- QThreadStorage<QGLContextGroupResource<QGLEngineSharedShaders> *> m_storage;
+ QThreadStorage<QGLMultiGroupSharedResource *> m_storage;
};
Q_GLOBAL_STATIC(QGLShaderStorage, qt_shader_storage);
@@ -81,8 +115,7 @@ const char* QGLEngineSharedShaders::qShaderSnippets[] = {
};
QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
- : ctxGuard(context)
- , blitShaderProg(0)
+ : blitShaderProg(0)
, simpleShaderProg(0)
{
@@ -327,14 +360,14 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
- QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram(ctxGuard.context(), 0));
+ QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram);
CachedShader shaderCache(fragSource, vertexSource);
- bool inCache = shaderCache.load(shaderProgram.data(), ctxGuard.context());
+ bool inCache = shaderCache.load(shaderProgram.data(), QGLContext::currentContext());
if (!inCache) {
- QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment, ctxGuard.context(), 0));
+ QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment));
QByteArray description;
#if defined(QT_DEBUG)
// Name the shader for easier debugging
@@ -357,7 +390,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
break;
}
- QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex, ctxGuard.context(), 0));
+ QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex));
#if defined(QT_DEBUG)
// Name the shader for easier debugging
description.clear();
@@ -396,7 +429,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
newProg->program->link();
if (newProg->program->isLinked()) {
if (!inCache)
- shaderCache.store(newProg->program, ctxGuard.context());
+ shaderCache.store(newProg->program, QGLContext::currentContext());
} else {
QLatin1String none("none");
QLatin1String br("\n");
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index 921df369f4..58c761df43 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -365,7 +365,6 @@ public:
void cleanupCustomStage(QGLCustomShaderStage* stage);
private:
- QGLSharedResourceGuard ctxGuard;
QGLShaderProgram *blitShaderProg;
QGLShaderProgram *simpleShaderProg;
QList<QGLEngineShaderProg*> cachedPrograms;
diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp
index 9e6b801c40..bd408ffdc4 100644
--- a/src/opengl/gl2paintengineex/qglgradientcache.cpp
+++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp
@@ -51,21 +51,42 @@ class QGL2GradientCacheWrapper
public:
QGL2GradientCache *cacheForContext(const QGLContext *context) {
QMutexLocker lock(&m_mutex);
- return m_resource.value(context);
+ return m_resource.value<QGL2GradientCache>(context->contextHandle());
}
private:
- QGLContextGroupResource<QGL2GradientCache> m_resource;
+ QGLMultiGroupSharedResource m_resource;
QMutex m_mutex;
};
Q_GLOBAL_STATIC(QGL2GradientCacheWrapper, qt_gradient_caches)
+QGL2GradientCache::QGL2GradientCache(QGuiGLContext *ctx)
+ : QGLSharedResource(ctx->shareGroup())
+{
+}
+
+QGL2GradientCache::~QGL2GradientCache()
+{
+ cache.clear();
+}
+
QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context)
{
return qt_gradient_caches()->cacheForContext(context);
}
+void QGL2GradientCache::invalidateResource()
+{
+ QMutexLocker lock(&m_mutex);
+ cache.clear();
+}
+
+void QGL2GradientCache::freeResource(QGuiGLContext *)
+{
+ cleanCache();
+}
+
void QGL2GradientCache::cleanCache()
{
QMutexLocker lock(&m_mutex);
diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h
index 1c2d0a029a..1b001c3405 100644
--- a/src/opengl/gl2paintengineex/qglgradientcache_p.h
+++ b/src/opengl/gl2paintengineex/qglgradientcache_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class QGL2GradientCache
+class QGL2GradientCache : public QGLSharedResource
{
struct CacheInfo
{
@@ -76,12 +76,15 @@ class QGL2GradientCache
public:
static QGL2GradientCache *cacheForContext(const QGLContext *context);
- QGL2GradientCache(const QGLContext *) {}
- ~QGL2GradientCache() { cleanCache(); }
+ QGL2GradientCache(QGuiGLContext *);
+ ~QGL2GradientCache();
GLuint getBuffer(const QGradient &gradient, qreal opacity);
inline int paletteSize() const { return 1024; }
+ void invalidateResource();
+ void freeResource(QGuiGLContext *ctx);
+
private:
inline int maxCacheSize() const { return 60; }
inline void generateGradientColorTable(const QGradient& gradient,
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 49d6b297e4..771d42be3f 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1580,10 +1580,9 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
QGLTextureGlyphCache *cache =
(QGLTextureGlyphCache *) staticTextItem->fontEngine()->glyphCache(cacheKey, glyphType, QTransform());
- if (!cache || cache->cacheType() != glyphType || cache->context() == 0) {
- cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform());
+ if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) {
+ cache = new QGLTextureGlyphCache(glyphType, QTransform());
staticTextItem->fontEngine()->setGlyphCache(cacheKey, cache);
- cache->insert(ctx, cache);
recreateVertexArrays = true;
}
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 4838ab09e7..214bfa5b47 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -51,19 +51,16 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled;
QBasicAtomicInt qgltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1);
-QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
- : QImageTextureGlyphCache(type, matrix), QGLContextGroupResourceBase()
- , ctx(0)
+QGLTextureGlyphCache::QGLTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
+ : QImageTextureGlyphCache(type, matrix)
, pex(0)
, m_blitProgram(0)
, m_filterMode(Nearest)
, m_serialNumber(qgltextureglyphcache_serial_number.fetchAndAddRelaxed(1))
{
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
- qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, ctx);
+ qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, QGuiGLContext::currentContext());
#endif
- setContext(context);
-
m_vertexCoordinateArray[0] = -1.0f;
m_vertexCoordinateArray[1] = -1.0f;
m_vertexCoordinateArray[2] = 1.0f;
@@ -91,14 +88,9 @@ QGLTextureGlyphCache::~QGLTextureGlyphCache()
delete m_blitProgram;
}
-void QGLTextureGlyphCache::setContext(const QGLContext *context)
-{
- ctx = context;
- m_h = 0;
-}
-
void QGLTextureGlyphCache::createTextureData(int width, int height)
{
+ QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
if (ctx == 0) {
qWarning("QGLTextureGlyphCache::createTextureData: Called with no context");
return;
@@ -116,12 +108,17 @@ void QGLTextureGlyphCache::createTextureData(int width, int height)
if (height < 16)
height = 16;
- QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx);
- glGenTextures(1, &glyphTexture->m_texture);
- glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
+ if (m_textureResource && !m_textureResource->m_texture)
+ delete m_textureResource;
- glyphTexture->m_width = width;
- glyphTexture->m_height = height;
+ if (!m_textureResource)
+ m_textureResource = new QGLGlyphTexture(ctx);
+
+ glGenTextures(1, &m_textureResource->m_texture);
+ glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+
+ m_textureResource->m_width = width;
+ m_textureResource->m_height = height;
if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {
QVarLengthArray<uchar> data(width * height * 4);
@@ -144,14 +141,14 @@ void QGLTextureGlyphCache::createTextureData(int width, int height)
void QGLTextureGlyphCache::resizeTextureData(int width, int height)
{
+ QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
if (ctx == 0) {
qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context");
return;
}
- QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx);
- int oldWidth = glyphTexture->m_width;
- int oldHeight = glyphTexture->m_height;
+ int oldWidth = m_textureResource->m_width;
+ int oldHeight = m_textureResource->m_height;
// Make the lower glyph texture size 16 x 16.
if (width < 16)
@@ -159,7 +156,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
if (height < 16)
height = 16;
- GLuint oldTexture = glyphTexture->m_texture;
+ GLuint oldTexture = m_textureResource->m_texture;
createTextureData(width, height);
if (ctx->d_ptr->workaround_brokenFBOReadBack) {
@@ -173,7 +170,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
// ### the QTextureGlyphCache API needs to be reworked to allow
// ### resizeTextureData to fail
- glBindFramebuffer(GL_FRAMEBUFFER_EXT, glyphTexture->m_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_textureResource->m_fbo);
GLuint tmp_texture;
glGenTextures(1, &tmp_texture);
@@ -257,7 +254,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
+ glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
@@ -276,16 +273,16 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition)
{
+ QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
if (ctx == 0) {
qWarning("QGLTextureGlyphCache::fillTexture: Called with no context");
return;
}
- QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx);
if (ctx->d_ptr->workaround_brokenFBOReadBack) {
QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition);
- glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
+ glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
const QImage &texture = image();
const uchar *bits = texture.constBits();
bits += c.y * texture.bytesPerLine() + c.x;
@@ -322,7 +319,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
}
}
- glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
+ glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
if (mask.format() == QImage::Format_RGB32) {
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
} else {
@@ -358,6 +355,7 @@ int QGLTextureGlyphCache::glyphPadding() const
int QGLTextureGlyphCache::maxTextureWidth() const
{
+ QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
if (ctx == 0)
return QImageTextureGlyphCache::maxTextureWidth();
else
@@ -366,6 +364,7 @@ int QGLTextureGlyphCache::maxTextureWidth() const
int QGLTextureGlyphCache::maxTextureHeight() const
{
+ QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
if (ctx == 0)
return QImageTextureGlyphCache::maxTextureHeight();
@@ -377,16 +376,15 @@ int QGLTextureGlyphCache::maxTextureHeight() const
void QGLTextureGlyphCache::clear()
{
- if (ctx != 0) {
- m_textureResource.cleanup(ctx);
-
- m_w = 0;
- m_h = 0;
- m_cx = 0;
- m_cy = 0;
- m_currentRowHeight = 0;
- coords.clear();
- }
+ m_textureResource->free();
+ m_textureResource = 0;
+
+ m_w = 0;
+ m_h = 0;
+ m_cx = 0;
+ m_cy = 0;
+ m_currentRowHeight = 0;
+ coords.clear();
}
QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
index 83ca06d040..2fcc551667 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
@@ -63,10 +63,11 @@ QT_BEGIN_NAMESPACE
class QGL2PaintEngineExPrivate;
-struct QGLGlyphTexture
+struct QGLGlyphTexture : public QGLSharedResource
{
QGLGlyphTexture(const QGLContext *ctx)
- : m_width(0)
+ : QGLSharedResource(ctx->contextHandle()->shareGroup())
+ , m_width(0)
, m_height(0)
{
if (ctx && !ctx->d_ptr->workaround_brokenFBOReadBack)
@@ -77,19 +78,24 @@ struct QGLGlyphTexture
#endif
}
- ~QGLGlyphTexture() {
- const QGLContext *ctx = QGLContext::currentContext();
+ void freeResource(QGuiGLContext *context)
+ {
+ const QGLContext *ctx = QGLContext::fromGuiGLContext(context);
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
qDebug("~QGLGlyphTexture() %p for context %p.", this, ctx);
#endif
- // At this point, the context group is made current, so it's safe to
- // release resources without a makeCurrent() call
- if (ctx) {
- if (!ctx->d_ptr->workaround_brokenFBOReadBack)
- glDeleteFramebuffers(1, &m_fbo);
- if (m_width || m_height)
- glDeleteTextures(1, &m_texture);
- }
+ if (!ctx->d_ptr->workaround_brokenFBOReadBack)
+ glDeleteFramebuffers(1, &m_fbo);
+ if (m_width || m_height)
+ glDeleteTextures(1, &m_texture);
+ }
+
+ void invalidateResource()
+ {
+ m_texture = 0;
+ m_fbo = 0;
+ m_width = 0;
+ m_height = 0;
}
GLuint m_texture;
@@ -98,10 +104,10 @@ struct QGLGlyphTexture
int m_height;
};
-class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache, public QGLContextGroupResourceBase
+class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache
{
public:
- QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix);
+ QGLTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix);
~QGLTextureGlyphCache();
virtual void createTextureData(int width, int height);
@@ -113,25 +119,24 @@ public:
inline GLuint texture() const {
QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
- QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx);
+ QGLGlyphTexture *glyphTexture = that->m_textureResource;
return glyphTexture ? glyphTexture->m_texture : 0;
}
inline int width() const {
QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
- QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx);
+ QGLGlyphTexture *glyphTexture = that->m_textureResource;
return glyphTexture ? glyphTexture->m_width : 0;
}
inline int height() const {
QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
- QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx);
+ QGLGlyphTexture *glyphTexture = that->m_textureResource;
return glyphTexture ? glyphTexture->m_height : 0;
}
inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; }
- void setContext(const QGLContext *context);
- inline const QGLContext *context() const { return ctx; }
+ inline const QGuiGLContextGroup *contextGroup() const { return m_textureResource ? m_textureResource->group() : 0; }
inline int serialNumber() const { return m_serialNumber; }
@@ -144,12 +149,9 @@ public:
void clear();
- void freeResource(void *) { ctx = 0; }
-
private:
- QGLContextGroupResource<QGLGlyphTexture> m_textureResource;
+ QGLGlyphTexture *m_textureResource;
- const QGLContext *ctx;
QGL2PaintEngineExPrivate *pex;
QGLShaderProgram *m_blitProgram;
FilterMode m_filterMode;