Implemented minimum FBO size on the ShaderEffectSource.
authorKim Motoyoshi Kalland <kim.kalland@nokia.com>
Mon, 15 Aug 2011 12:46:23 +0000 (14:46 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 17 Aug 2011 11:19:47 +0000 (13:19 +0200)
Task-number: QTBUG-20193

Change-Id: I45020c094c4a4892c055700f084fde7b219cdc10
Reviewed-on: http://codereview.qt.nokia.com/2972
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>

src/declarative/items/qsgshadereffectsource.cpp
src/declarative/scenegraph/qsgcontext.cpp
src/declarative/scenegraph/qsgcontext_p.h

index 5114d8c..d7653b5 100644 (file)
@@ -558,8 +558,12 @@ void QSGShaderEffectSource::setSourceRect(const QRectF &rect)
 /*!
     \qmlproperty size ShaderEffectSource::textureSize
 
-    This property holds the size of the texture. If it is empty, which is the
-    default, the size of the source rectangle is used.
+    This property holds the requested size of the texture. If it is empty,
+    which is the default, the size of the source rectangle is used.
+
+    \note Some platforms have a limit on how small framebuffer objects can be,
+    which means the actual texture size might be larger than the requested
+    size.
 */
 
 QSize QSGShaderEffectSource::textureSize() const
@@ -762,7 +766,7 @@ QSGTexture *QSGShaderEffectSource::texture() const
 
 QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
 {
-    if (!m_sourceItem) {
+    if (!m_sourceItem || m_sourceItem->width() == 0 || m_sourceItem->height() == 0) {
         delete oldNode;
         return 0;
     }
@@ -782,13 +786,22 @@ QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
 
     tex->setLive(m_live);
     tex->setItem(QSGItemPrivate::get(m_sourceItem)->itemNode());
-    QRectF sourceRect = m_sourceRect.isNull()
+    QRectF sourceRect = m_sourceRect.width() == 0 || m_sourceRect.height() == 0
                       ? QRectF(0, 0, m_sourceItem->width(), m_sourceItem->height())
                       : m_sourceRect;
     tex->setRect(sourceRect);
     QSize textureSize = m_textureSize.isEmpty()
                       ? QSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())))
                       : m_textureSize;
+    Q_ASSERT(!textureSize.isEmpty());
+    QSGItemPrivate *d = static_cast<QSGItemPrivate *>(QObjectPrivate::get(this));
+    const QSize minTextureSize = d->sceneGraphContext()->minimumFBOSize();
+    // Keep power-of-two by doubling the size.
+    while (textureSize.width() < minTextureSize.width())
+        textureSize.rwidth() *= 2;
+    while (textureSize.height() < minTextureSize.height())
+        textureSize.rheight() *= 2;
+
     tex->setSize(textureSize);
     tex->setRecursive(m_recursive);
     tex->setFormat(GLenum(m_format));
index 1f6f6e1..2a9e007 100644 (file)
@@ -398,6 +398,21 @@ QSGTexture *QSGContext::createTexture(const QImage &image) const
 
 
 /*!
+    Returns the minimum supported framebuffer object size.
+ */
+
+QSize QSGContext::minimumFBOSize() const
+{
+#ifdef Q_WS_MAC
+    return QSize(33, 33);
+#else
+    return QSize(1, 1);
+#endif
+}
+
+
+
+/*!
     Returns a material shader for the given material.
  */
 
index be7dff8..29a5aac 100644 (file)
@@ -102,6 +102,7 @@ public:
                                                      QSize *size,
                                                      const QSize &requestSize);
     virtual QSGTexture *createTexture(const QImage &image = QImage()) const;
+    virtual QSize minimumFBOSize() const;
 
     static QSGContext *createDefaultContext();