diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2011-08-27 01:43:46 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2011-08-27 01:43:46 (GMT) |
commit | e2c2e7e7fb3bee99260dc5b7bfab42c9217c18c8 (patch) | |
tree | c466ef854854b646f590efbd63563fd872177880 /src/imports | |
parent | 20b1263695169e88207c8a4c4aac968a6044931b (diff) | |
parent | e028a54690f2fedfae6da19fb24b7401e4a71e56 (diff) | |
download | Qt-e2c2e7e7fb3bee99260dc5b7bfab42c9217c18c8.zip Qt-e2c2e7e7fb3bee99260dc5b7bfab42c9217c18c8.tar.gz Qt-e2c2e7e7fb3bee99260dc5b7bfab42c9217c18c8.tar.bz2 |
Merge branch 'qt-4.8-from-4.7' of scm.dev.nokia.troll.no:qt/qt-integration into master-integration
* 'qt-4.8-from-4.7' of scm.dev.nokia.troll.no:qt/qt-integration:
Fixed use of deleted object in XmlPatterns EvaluationCache
Crash when creating scroll bar skin graphics on S60 (debug only)
QS60Style omits drawing theme background in some Symbian SDKs
Fix for qml1shaderplugin GPU resource handling on Symbian
Make it easier to select words at the start of a line.
Doc: Fixing typo
In landscape mode QComboboBox popup can not be showed completely
Fix left alignment of native RTL pre-edit text.
Diffstat (limited to 'src/imports')
-rwxr-xr-x[-rw-r--r--] | src/imports/shaders/shadereffectitem.cpp | 110 | ||||
-rw-r--r-- | src/imports/shaders/shadereffectitem.h | 4 | ||||
-rw-r--r-- | src/imports/shaders/shadereffectsource.cpp | 43 | ||||
-rw-r--r-- | src/imports/shaders/shadereffectsource.h | 3 |
4 files changed, 116 insertions, 44 deletions
diff --git a/src/imports/shaders/shadereffectitem.cpp b/src/imports/shaders/shadereffectitem.cpp index ca5c9a3..b954e5a 100644..100755 --- a/src/imports/shaders/shadereffectitem.cpp +++ b/src/imports/shaders/shadereffectitem.cpp @@ -199,8 +199,13 @@ Rectangle { */ +#ifdef Q_OS_SYMBIAN +#define OBSERVE_GL_CONTEXT_LOSS 1 +#endif + ShaderEffectItem::ShaderEffectItem(QDeclarativeItem *parent) : QDeclarativeItem(parent) + , m_program(0) , m_meshResolution(1, 1) , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) , m_blending(true) @@ -214,15 +219,21 @@ ShaderEffectItem::ShaderEffectItem(QDeclarativeItem *parent) , m_hasShaderPrograms(false) , m_mirrored(false) , m_defaultVertexShader(true) + , m_contextObserver(0) { setFlag(QGraphicsItem::ItemHasNoContents, false); connect(this, SIGNAL(visibleChanged()), this, SLOT(handleVisibilityChange())); m_active = isVisible(); + +#ifndef OBSERVE_GL_CONTEXT_LOSS + m_program = new QGLShaderProgram(this); +#endif } ShaderEffectItem::~ShaderEffectItem() { reset(); + delete m_contextObserver; } @@ -402,10 +413,38 @@ void ShaderEffectItem::renderEffect(QPainter *painter, const QMatrix4x4 &matrix) if (!painter || !painter->device()) return; - if (!m_program.isLinked() || m_program_dirty) +#ifdef OBSERVE_GL_CONTEXT_LOSS + QGLContext *context = const_cast <QGLContext*> (QGLContext::currentContext()); + if (!m_program || !m_contextObserver || !m_contextObserver->isValid()) { + // Context has changed, re-create QGLShaderProgram + if (context) { + delete m_program; + m_program = 0; + + delete m_contextObserver; + m_contextObserver = 0; + + m_program = new QGLShaderProgram(this); + m_contextObserver = new QGLFramebufferObject(QSize(2,2)); + + if (!m_contextObserver || !m_program) { + delete m_program; + m_program = 0; + delete m_contextObserver; + m_contextObserver = 0; + qWarning() << "ShaderEffectItem::renderEffect - Creating QGLShaderProgram or QGLFrameBufferObject failed!"; + } + } + } +#endif + + if (!m_program) + return; + + if (!m_program->isLinked() || m_program_dirty) updateShaderProgram(); - m_program.bind(); + m_program->bind(); QMatrix4x4 combinedMatrix; combinedMatrix.scale(2.0 / painter->device()->width(), -2.0 / painter->device()->height(), 1.0); @@ -414,7 +453,7 @@ void ShaderEffectItem::renderEffect(QPainter *painter, const QMatrix4x4 &matrix) updateEffectState(combinedMatrix); for (int i = 0; i < m_attributeNames.size(); ++i) { - m_program.enableAttributeArray(m_geometry.attributes()[i].position); + m_program->enableAttributeArray(m_geometry.attributes()[i].position); } bindGeometry(); @@ -452,11 +491,14 @@ void ShaderEffectItem::renderEffect(QPainter *painter, const QMatrix4x4 &matrix) glDisable(GL_DEPTH_TEST); for (int i = 0; i < m_attributeNames.size(); ++i) - m_program.disableAttributeArray(m_geometry.attributes()[i].position); + m_program->disableAttributeArray(m_geometry.attributes()[i].position); } void ShaderEffectItem::updateEffectState(const QMatrix4x4 &matrix) { + if (!m_program) + return; + for (int i = m_sources.size() - 1; i >= 0; --i) { const ShaderEffectItem::SourceData &source = m_sources.at(i); if (!source.source) @@ -467,10 +509,10 @@ void ShaderEffectItem::updateEffectState(const QMatrix4x4 &matrix) } if (m_respectsOpacity) - m_program.setUniformValue("qt_Opacity", static_cast<float> (effectiveOpacity())); + m_program->setUniformValue("qt_Opacity", static_cast<float> (effectiveOpacity())); if (m_respectsMatrix){ - m_program.setUniformValue("qt_ModelViewProjectionMatrix", matrix); + m_program->setUniformValue("qt_ModelViewProjectionMatrix", matrix); } QSet<QByteArray>::const_iterator it; @@ -480,37 +522,37 @@ void ShaderEffectItem::updateEffectState(const QMatrix4x4 &matrix) switch (v.type()) { case QVariant::Color: - m_program.setUniformValue(name.constData(), qvariant_cast<QColor>(v)); + m_program->setUniformValue(name.constData(), qvariant_cast<QColor>(v)); break; case QVariant::Double: - m_program.setUniformValue(name.constData(), (float) qvariant_cast<double>(v)); + m_program->setUniformValue(name.constData(), (float) qvariant_cast<double>(v)); break; case QVariant::Transform: - m_program.setUniformValue(name.constData(), qvariant_cast<QTransform>(v)); + m_program->setUniformValue(name.constData(), qvariant_cast<QTransform>(v)); break; case QVariant::Int: - m_program.setUniformValue(name.constData(), v.toInt()); + m_program->setUniformValue(name.constData(), GLint(v.toInt())); break; case QVariant::Bool: - m_program.setUniformValue(name.constData(), GLint(v.toBool())); + m_program->setUniformValue(name.constData(), GLint(v.toBool())); break; case QVariant::Size: case QVariant::SizeF: - m_program.setUniformValue(name.constData(), v.toSizeF()); + m_program->setUniformValue(name.constData(), v.toSizeF()); break; case QVariant::Point: case QVariant::PointF: - m_program.setUniformValue(name.constData(), v.toPointF()); + m_program->setUniformValue(name.constData(), v.toPointF()); break; case QVariant::Rect: case QVariant::RectF: { QRectF r = v.toRectF(); - m_program.setUniformValue(name.constData(), r.x(), r.y(), r.width(), r.height()); + m_program->setUniformValue(name.constData(), r.x(), r.y(), r.width(), r.height()); } break; case QVariant::Vector3D: - m_program.setUniformValue(name.constData(), qvariant_cast<QVector3D>(v)); + m_program->setUniformValue(name.constData(), qvariant_cast<QVector3D>(v)); break; default: break; @@ -538,6 +580,9 @@ static inline int size_of_type(GLenum type) void ShaderEffectItem::bindGeometry() { + if (!m_program) + return; + char const *const *attrNames = m_attributeNames.constData(); int offset = 0; for (int j = 0; j < m_attributeNames.size(); ++j) { @@ -554,7 +599,7 @@ void ShaderEffectItem::bindGeometry() if (normalize) qWarning() << "ShaderEffectItem::bindGeometry() - non supported attribute type!"; - m_program.setAttributeArray(a.position, (GLfloat*) (((char*) m_geometry.vertexData()) + offset), a.tupleSize, m_geometry.stride()); + m_program->setAttributeArray(a.position, (GLfloat*) (((char*) m_geometry.vertexData()) + offset), a.tupleSize, m_geometry.stride()); //glVertexAttribPointer(a.position, a.tupleSize, a.type, normalize, m_geometry.stride(), (char *) m_geometry.vertexData() + offset); offset += a.tupleSize * size_of_type(a.type); } @@ -637,6 +682,16 @@ void ShaderEffectItem::setActive(bool enable) } } + // QGLShaderProgram is deleted when not active (to minimize GPU memory usage). +#ifdef OBSERVE_GL_CONTEXT_LOSS + if (!m_active && m_program) { + delete m_program; + m_program = 0; + delete m_contextObserver; + m_contextObserver = 0; + } +#endif + emit activeChanged(); markDirty(); } @@ -756,7 +811,9 @@ void ShaderEffectItem::reset() { disconnectPropertySignals(); - m_program.removeAllShaders(); + if (m_program) + m_program->removeAllShaders(); + m_attributeNames.clear(); m_uniformNames.clear(); for (int i = 0; i < m_sources.size(); ++i) { @@ -801,6 +858,9 @@ void ShaderEffectItem::updateProperties() void ShaderEffectItem::updateShaderProgram() { + if (!m_program) + return; + QString vertexCode = m_vertex_code; QString fragmentCode = m_fragment_code; @@ -810,16 +870,16 @@ void ShaderEffectItem::updateShaderProgram() if (fragmentCode.isEmpty()) fragmentCode = QString::fromLatin1(qt_default_fragment_code); - m_program.addShaderFromSourceCode(QGLShader::Vertex, vertexCode); - m_program.addShaderFromSourceCode(QGLShader::Fragment, fragmentCode); + m_program->addShaderFromSourceCode(QGLShader::Vertex, vertexCode); + m_program->addShaderFromSourceCode(QGLShader::Fragment, fragmentCode); for (int i = 0; i < m_attributeNames.size(); ++i) { - m_program.bindAttributeLocation(m_attributeNames.at(i), m_geometry.attributes()[i].position); + m_program->bindAttributeLocation(m_attributeNames.at(i), m_geometry.attributes()[i].position); } - if (!m_program.link()) { + if (!m_program->link()) { qWarning("ShaderEffectItem: Shader compilation failed:"); - qWarning() << m_program.log(); + qWarning() << m_program->log(); } if (!m_attributeNames.contains(qt_postion_attribute_name)) @@ -829,10 +889,10 @@ void ShaderEffectItem::updateShaderProgram() if (!m_respectsMatrix) qWarning("ShaderEffectItem: Missing reference to \'qt_ModelViewProjectionMatrix\'."); - if (m_program.isLinked()) { - m_program.bind(); + if (m_program->isLinked()) { + m_program->bind(); for (int i = 0; i < m_sources.size(); ++i) - m_program.setUniformValue(m_sources.at(i).name.constData(), i); + m_program->setUniformValue(m_sources.at(i).name.constData(), (GLint) i); } m_program_dirty = false; diff --git a/src/imports/shaders/shadereffectitem.h b/src/imports/shaders/shadereffectitem.h index aebe897..6c225a2 100644 --- a/src/imports/shaders/shadereffectitem.h +++ b/src/imports/shaders/shadereffectitem.h @@ -115,7 +115,7 @@ private: private: QString m_fragment_code; QString m_vertex_code; - QGLShaderProgram m_program; + QGLShaderProgram* m_program; QVector<const char *> m_attributeNames; QSet<QByteArray> m_uniformNames; QSize m_meshResolution; @@ -143,6 +143,8 @@ private: bool m_hasShaderPrograms : 1; bool m_mirrored : 1; bool m_defaultVertexShader : 1; + + QGLFramebufferObject* m_contextObserver; }; QT_END_HEADER diff --git a/src/imports/shaders/shadereffectsource.cpp b/src/imports/shaders/shadereffectsource.cpp index 7916538..f7a8a93 100644 --- a/src/imports/shaders/shadereffectsource.cpp +++ b/src/imports/shaders/shadereffectsource.cpp @@ -160,15 +160,11 @@ void ShaderEffectSource::setSourceRect(const QRectF &rect) return; m_sourceRect = rect; updateSizeAndTexture(); - updateBackbuffer(); emit sourceRectChanged(); emit repaintRequired(); - if (m_sourceItem) { - ShaderEffect* effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect()); - if (effect) - effect->m_changed = true; - } + m_dirtyTexture = true; + markSourceItemDirty(); } /*! @@ -192,11 +188,8 @@ void ShaderEffectSource::setTextureSize(const QSize &size) emit textureSizeChanged(); emit repaintRequired(); - if (m_sourceItem) { - ShaderEffect* effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect()); - if (effect) - effect->m_changed = true; - } + m_dirtyTexture = true; + markSourceItemDirty(); } /*! @@ -264,8 +257,10 @@ void ShaderEffectSource::setWrapMode(WrapMode mode) return; m_wrapMode = mode; - updateBackbuffer(); emit wrapModeChanged(); + + m_dirtyTexture = true; + markSourceItemDirty(); } /*! @@ -284,7 +279,7 @@ void ShaderEffectSource::grab() emit repaintRequired(); } -void ShaderEffectSource::bind() const +void ShaderEffectSource::bind() { GLint filtering = smooth() ? GL_LINEAR : GL_NEAREST; GLuint hwrap = (m_wrapMode == Repeat || m_wrapMode == RepeatHorizontally) ? GL_REPEAT : GL_CLAMP_TO_EDGE; @@ -293,9 +288,13 @@ void ShaderEffectSource::bind() const #if !defined(QT_OPENGL_ES_2) glEnable(GL_TEXTURE_2D); #endif - if (m_fbo) { + + if (m_fbo && m_fbo->isValid()) { glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); } else { + m_dirtyTexture = true; + emit repaintRequired(); + markSourceItemDirty(); glBindTexture(GL_TEXTURE_2D, 0); } @@ -324,7 +323,7 @@ void ShaderEffectSource::derefFromEffectItem() void ShaderEffectSource::updateBackbuffer() { - if (!m_sourceItem) + if (!m_sourceItem || !QGLContext::currentContext()) return; // Multisampling is not (for now) supported. @@ -340,7 +339,7 @@ void ShaderEffectSource::updateBackbuffer() if (!m_fbo) { m_fbo = new ShaderEffectBuffer(size, format); } else { - if (m_fbo->size() != size || m_fbo->format().internalTextureFormat() != GLenum(m_format)) { + if (!m_fbo->isValid() || m_fbo->size() != size || m_fbo->format().internalTextureFormat() != GLenum(m_format)) { delete m_fbo; m_fbo = 0; m_fbo = new ShaderEffectBuffer(size, format); @@ -367,6 +366,16 @@ void ShaderEffectSource::markSourceSizeDirty() emit repaintRequired(); } +void ShaderEffectSource::markSourceItemDirty() +{ + m_dirtyTexture = true; + if (m_sourceItem) { + ShaderEffect* effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect()); + if (effect) + effect->m_changed = true; + } +} + void ShaderEffectSource::updateSizeAndTexture() { if (m_sourceItem) { @@ -377,7 +386,7 @@ void ShaderEffectSource::updateSizeAndTexture() size.setWidth(1); if (size.height() < 1) size.setHeight(1); - if (m_fbo && m_fbo->size() != size) { + if (m_fbo && (m_fbo->size() != size || !m_fbo->isValid())) { delete m_fbo; m_fbo = 0; delete m_multisampledFbo; diff --git a/src/imports/shaders/shadereffectsource.h b/src/imports/shaders/shadereffectsource.h index 0f03a6a..af8a815 100644 --- a/src/imports/shaders/shadereffectsource.h +++ b/src/imports/shaders/shadereffectsource.h @@ -99,7 +99,7 @@ public: void setWrapMode(WrapMode mode); bool isActive() const { return m_refs; } - void bind() const; + void bind(); void refFromEffectItem(); void derefFromEffectItem(); void updateBackbuffer(); @@ -124,6 +124,7 @@ Q_SIGNALS: public Q_SLOTS: void markSceneGraphDirty(); void markSourceSizeDirty(); + void markSourceItemDirty(); private: void updateSizeAndTexture(); |