Added PerformanceHints flags to QSGPaintedItem.
authorYoann Lopes <yoann.lopes@nokia.com>
Fri, 9 Sep 2011 11:00:58 +0000 (13:00 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 20 Sep 2011 05:22:35 +0000 (07:22 +0200)
At the moment only contains FastFBOResizing.
If this flag is set to true and when using a FBO as render target,
the FBO will use a larger texture than the size of the item to avoid
too many resizing.

Change-Id: I3b8a51a5a07329ff3ed010a35dc8235913201a8e
Reviewed-on: http://codereview.qt-project.org/4651
Reviewed-by: Yoann Lopes <yoann.lopes@nokia.com>
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
src/declarative/items/qsgpainteditem.cpp
src/declarative/items/qsgpainteditem.h
src/declarative/items/qsgpainteditem_p.h
src/declarative/scenegraph/util/qsgpainternode.cpp
src/declarative/scenegraph/util/qsgpainternode_p.h

index 76d5a00..19d2a9a 100644 (file)
@@ -93,6 +93,19 @@ QT_BEGIN_NAMESPACE
 */
 
 /*!
+    \enum QSGPaintedItem::PerformanceHint
+
+    This enum describes flags that you can enable to improve rendering
+    performance in QSGPaintedItem. By default, none of these flags are set.
+
+    \value FastFBOResizing If your item gets resized often and you are using the
+    QSGPaintedItem::FramebufferObject render target, set this flag to true to reduce the
+    item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
+    is a costly operation, by enabling this property the Framebuffer Object will use a texture
+    larger than the actual size of the item to avoid as much as possible resizing it.
+*/
+
+/*!
     \internal
 */
 QSGPaintedItemPrivate::QSGPaintedItemPrivate()
@@ -100,6 +113,7 @@ QSGPaintedItemPrivate::QSGPaintedItemPrivate()
     , contentsScale(1.0)
     , fillColor(Qt::transparent)
     , renderTarget(QSGPaintedItem::Image)
+    , performanceHints(0)
     , geometryDirty(false)
     , contentsDirty(false)
     , opaquePainting(false)
@@ -257,6 +271,55 @@ void QSGPaintedItem::setMipmap(bool enable)
 }
 
 /*!
+    Returns the performance hints.
+
+    By default, no performance hint is enabled/
+
+    \sa setPerformanceHint(), setPerformanceHints()
+*/
+QSGPaintedItem::PerformanceHints QSGPaintedItem::performanceHints() const
+{
+    Q_D(const QSGPaintedItem);
+    return d->performanceHints;
+}
+
+/*!
+    Sets the given performance \a hint on the item if \a enabled is true;
+    otherwise clears the performance hint.
+
+    By default, no performance hint is enabled/
+
+    \sa setPerformanceHints(), performanceHints()
+*/
+void QSGPaintedItem::setPerformanceHint(QSGPaintedItem::PerformanceHint hint, bool enabled)
+{
+    Q_D(QSGPaintedItem);
+    PerformanceHints oldHints = d->performanceHints;
+    if (enabled)
+        d->performanceHints |= hint;
+    else
+        d->performanceHints &= ~hint;
+    if (oldHints != d->performanceHints)
+       update();
+}
+
+/*!
+    Sets the performance hints to \a hints
+
+    By default, no performance hint is enabled/
+
+    \sa setPerformanceHint(), performanceHints()
+*/
+void QSGPaintedItem::setPerformanceHints(QSGPaintedItem::PerformanceHints hints)
+{
+    Q_D(QSGPaintedItem);
+    if (d->performanceHints == hints)
+        return;
+    d->performanceHints = hints;
+    update();
+}
+
+/*!
     This function returns the outer bounds of the item as a rectangle; all painting must be
     restricted to inside an item's bounding rect.
 
@@ -450,6 +513,7 @@ QSGNode *QSGPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
     QRectF br = contentsBoundingRect();
 
     node->setPreferredRenderTarget(d->renderTarget);
+    node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
     node->setSize(QSize(qRound(br.width()), qRound(br.height())));
     node->setSmoothPainting(d->antialiasing);
     node->setLinearFiltering(d->smooth);
index 2d5d260..eaae3be 100644 (file)
@@ -68,6 +68,11 @@ public:
         FramebufferObject
     };
 
+    enum PerformanceHint {
+        FastFBOResizing = 0x1
+    };
+    Q_DECLARE_FLAGS(PerformanceHints, PerformanceHint)
+
     void update(const QRect &rect = QRect());
 
     bool opaquePainting() const;
@@ -79,6 +84,10 @@ public:
     bool mipmap() const;
     void setMipmap(bool enable);
 
+    PerformanceHints performanceHints() const;
+    void setPerformanceHint(PerformanceHint hint, bool enabled = true);
+    void setPerformanceHints(PerformanceHints hints);
+
     QRectF contentsBoundingRect() const;
 
     QSize contentsSize() const;
@@ -112,6 +121,8 @@ private:
     Q_DECLARE_PRIVATE(QSGPaintedItem)
 };
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGPaintedItem::PerformanceHints)
+
 QT_END_NAMESPACE
 
 QT_END_HEADER
index 3ad4466..f698e18 100644 (file)
@@ -57,6 +57,7 @@ public:
     qreal contentsScale;
     QColor fillColor;
     QSGPaintedItem::RenderTarget renderTarget;
+    QSGPaintedItem::PerformanceHints performanceHints;
 
     QRect dirtyRect;
 
index 5d54879..fb35467 100644 (file)
@@ -42,6 +42,7 @@
 #include "qsgpainternode_p.h"
 
 #include "qsgpainteditem.h"
+#include <private/qsgpainteditem_p.h>
 #include <private/qsgcontext_p.h>
 #include <private/qopenglextensions_p.h>
 #include <qopenglframebufferobject.h>
@@ -52,7 +53,7 @@
 
 QT_BEGIN_NAMESPACE
 
-#define QT_MINIMUM_FBO_SIZE 64
+#define QT_MINIMUM_DYNAMIC_FBO_SIZE 64
 
 static inline int qt_next_power_of_two(int v)
 {
@@ -122,12 +123,15 @@ QSGPainterNode::QSGPainterNode(QSGPaintedItem *item)
     , m_smoothPainting(false)
     , m_extensionsChecked(false)
     , m_multisamplingSupported(false)
+    , m_fastFBOResizing(false)
     , m_fillColor(Qt::transparent)
     , m_contentsScale(1.0)
     , m_dirtyGeometry(false)
     , m_dirtyRenderTarget(false)
     , m_dirtyTexture(false)
 {
+    m_context = static_cast<QSGPaintedItemPrivate *>(QObjectPrivate::get(item))->sceneGraphContext();
+
     setMaterial(&m_materialO);
     setOpaqueMaterial(&m_material);
     setGeometry(&m_geometry);
@@ -268,7 +272,7 @@ void QSGPainterNode::updateRenderTarget()
     }
 
     if (m_actualRenderTarget == QSGPaintedItem::FramebufferObject) {
-        QOpenGLContext *ctx = QOpenGLContext::currentContext();
+        const QOpenGLContext *ctx = m_context->glContext();
         if (m_fbo && !m_dirtyGeometry && (!ctx->format().samples() || !m_multisamplingSupported))
             return;
 
@@ -323,8 +327,17 @@ void QSGPainterNode::updateRenderTarget()
 
 void QSGPainterNode::updateFBOSize()
 {
-    int fboWidth = qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(m_size.width()));
-    int fboHeight = qMax(QT_MINIMUM_FBO_SIZE, qt_next_power_of_two(m_size.height()));
+    int fboWidth;
+    int fboHeight;
+    if (m_fastFBOResizing) {
+        fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.width()));
+        fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.height()));
+    } else {
+        QSize minimumFBOSize = m_context->minimumFBOSize();
+        fboWidth = qMax(minimumFBOSize.width(), m_size.width());
+        fboHeight = qMax(minimumFBOSize.height(), m_size.height());
+    }
+
     m_fboSize = QSize(fboWidth, fboHeight);
 }
 
@@ -426,6 +439,11 @@ void QSGPainterNode::setContentsScale(qreal s)
     markDirty(DirtyMaterial);
 }
 
+void QSGPainterNode::setFastFBOResizing(bool dynamic)
+{
+    m_fastFBOResizing = dynamic;
+}
+
 QImage QSGPainterNode::toImage() const
 {
     if (m_actualRenderTarget == QSGPaintedItem::Image)
index 435e86e..e30dc7c 100644 (file)
@@ -102,6 +102,9 @@ public:
     void setContentsScale(qreal s);
     qreal contentsScale() const { return m_contentsScale; }
 
+    void setFastFBOResizing(bool dynamic);
+    bool fastFBOResizing() const { return m_fastFBOResizing; }
+
     QImage toImage() const;
     void update();
 
@@ -113,6 +116,8 @@ private:
     void updateRenderTarget();
     void updateFBOSize();
 
+    QSGContext *m_context;
+
     QSGPaintedItem::RenderTarget m_preferredRenderTarget;
     QSGPaintedItem::RenderTarget m_actualRenderTarget;
 
@@ -138,6 +143,7 @@ private:
     bool m_smoothPainting;
     bool m_extensionsChecked;
     bool m_multisamplingSupported;
+    bool m_fastFBOResizing;
     QColor m_fillColor;
     qreal m_contentsScale;