aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar@sletta.org>2015-09-09 10:20:23 +0200
committerGunnar Sletta <gunnar@sletta.org>2015-09-15 07:45:51 +0000
commit0c7349fa9621f6460b754c2b3595d1c0f1d02ec4 (patch)
tree1f94b5dc0cdc1ae551bc784416f6d3473f1738f4
parentf3efdebc34d37137f256995984d2050375be25de (diff)
Introduce QQuickPaintedItem::textureSize and support HighDpi.
contentsSize/Scale/BoundingRect are confusing and will in most cases not produce what the user wants, but since they might be in use, we keep their behavior and simply obsolete them. New code should use textureSize, though most code can simply rely on implicit HighDpi support. [ChangeLog][QtQuick][QQuickPaintedItem] Implement high-dpi support and add function textureSize. This obsoletes the existing contentsSize, contentsScale and contentsBoundingRect functions. Task-number: QTBUG-32510 Task-number: QTBUG-40489 Change-Id: I660bbf394594b6ea588d4de9cc83c8c5eb28cb28 Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
-rw-r--r--src/quick/items/qquickpainteditem.cpp106
-rw-r--r--src/quick/items/qquickpainteditem.h6
-rw-r--r--src/quick/items/qquickpainteditem_p.h1
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h1
-rw-r--r--src/quick/scenegraph/util/qsgdefaultpainternode.cpp58
-rw-r--r--src/quick/scenegraph/util/qsgdefaultpainternode_p.h7
6 files changed, 137 insertions, 42 deletions
diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp
index 033000c159..4172b83419 100644
--- a/src/quick/items/qquickpainteditem.cpp
+++ b/src/quick/items/qquickpainteditem.cpp
@@ -67,15 +67,11 @@ public:
To enable QPainter to do anti-aliased rendering, use setAntialiasing().
- To write your own painted item, you first create a subclass of QQuickPaintedItem, and then
- start by implementing its only pure virtual public function: paint(), which implements
- the actual painting. To get the size of the area painted by the item, use
- contentsBoundingRect().
-
- Starting Qt 5.4, the QQuickPaintedItem is a
- \l{QSGTextureProvider}{texture provider}
- and can be used directly in \l {ShaderEffect}{ShaderEffects} and other
- classes that consume texture providers.
+ To write your own painted item, you first create a subclass of
+ QQuickPaintedItem, and then start by implementing its only pure virtual
+ public function: paint(), which implements the actual painting. The
+ painting will be inside the rectangle spanning from 0,0 to
+ width(),height().
*/
/*!
@@ -333,16 +329,47 @@ void QQuickPaintedItem::setPerformanceHints(QQuickPaintedItem::PerformanceHints
update();
}
+QSize QQuickPaintedItem::textureSize() const
+{
+ Q_D(const QQuickPaintedItem);
+ return d->textureSize;
+}
+
/*!
- This function returns the outer bounds of the item as a rectangle; all painting must be
- restricted to inside an item's bounding rect.
+ \property QQuickPaintedItem::textureSize
+
+ \brief Defines the size of the texture.
+
+ Changing the texture's size does not affect the coordinate system used in
+ paint(). A scale factor is instead applied so painting should still happen
+ inside 0,0 to width(),height().
+
+ By default, the texture size will have the same size as this item.
+
+ \note If the item is on a window with a device pixel ratio different from
+ 1, this scale factor will be implicitly applied to the texture size.
+
+ */
+void QQuickPaintedItem::setTextureSize(const QSize &size)
+{
+ Q_D(QQuickPaintedItem);
+ if (d->textureSize == size)
+ return;
+ d->textureSize = size;
+ emit textureSizeChanged();
+}
+
+#if QT_VERSION >= 0x060000
+#warning "Remove: QQuickPaintedItem::contentsBoundingRect, contentsScale, contentsSize. Also remove them from qsgadaptationlayer_p.h and qsgdefaultpainternode.h/cpp."
+#endif
- If the contents size has not been set it reflects the size of the item; otherwise
- it reflects the contents size scaled by the contents scale.
+/*!
+ \obsolete
- Use this function to know the area painted by the item.
+ This function is provided for compatibility, use size in combination
+ with textureSize to decide the size of what you are drawing.
- \sa QQuickItem::width(), QQuickItem::height(), contentsSize(), contentsScale()
+ \sa width(), height(), textureSize()
*/
QRectF QQuickPaintedItem::contentsBoundingRect() const
{
@@ -361,11 +388,13 @@ QRectF QQuickPaintedItem::contentsBoundingRect() const
/*!
\property QQuickPaintedItem::contentsSize
- \brief The size of the contents
+ \brief Obsolete method for setting the contents size.
+ \obsolete
+
+ This function is provided for compatibility, use size in combination
+ with textureSize to decide the size of what you are drawing.
- The contents size is the size of the item in regards to how it is painted
- using the paint() function. This is distinct from the size of the
- item in regards to height() and width().
+ \sa width(), height(), textureSize()
*/
QSize QQuickPaintedItem::contentsSize() const
{
@@ -387,6 +416,7 @@ void QQuickPaintedItem::setContentsSize(const QSize &size)
}
/*!
+ \obsolete
This convenience function is equivalent to calling setContentsSize(QSize()).
*/
void QQuickPaintedItem::resetContentsSize()
@@ -396,12 +426,13 @@ void QQuickPaintedItem::resetContentsSize()
/*!
\property QQuickPaintedItem::contentsScale
- \brief The scale of the contents
+ \brief Obsolete method for scaling the contents.
+ \obsolete
- All painting happening in paint() is scaled by the contents scale. This is distinct
- from the scale of the item in regards to scale().
+ This function is provided for compatibility, use size() in combination
+ with textureSize() to decide the size of what you are drawing.
- The default value is 1.
+ \sa width(), height(), textureSize()
*/
qreal QQuickPaintedItem::contentsScale() const
{
@@ -488,6 +519,9 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target)
This function, which is usually called by the QML Scene Graph, paints the
contents of an item in local coordinates.
+ The underlying texture will have a size defined by textureSize when set,
+ or the item's size, multiplied by the window's device pixel ratio.
+
The function is called after the item has been filled with the fillColor.
Reimplement this function in a QQuickPaintedItem subclass to provide the
@@ -501,6 +535,8 @@ void QQuickPaintedItem::setRenderTarget(RenderTarget target)
\warning Extreme caution must be used when creating QObjects, emitting signals, starting
timers and similar inside this function as these will have affinity to the rendering thread.
+
+ \sa width(), height(), textureSize
*/
/*!
@@ -526,17 +562,35 @@ QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
d->node = node;
}
- QRectF br = contentsBoundingRect();
+ bool hasTextureSize = d->textureSize.width() > 0 && d->textureSize.height() > 0;
+
+ // Use the compat mode if any of the compat things are set and
+ // textureSize is 0x0.
+ if (!hasTextureSize
+ && (d->contentsScale != 1
+ || (d->contentsSize.width() > 0 && d->contentsSize.height() > 0))) {
+ QRectF br = contentsBoundingRect();
+ node->setContentsScale(d->contentsScale);
+ QSize size = QSize(qRound(br.width()), qRound(br.height()));
+ node->setSize(size);
+ node->setTextureSize(size);
+ } else {
+ // The default, use textureSize or item's size * device pixel ratio
+ node->setContentsScale(1);
+ QSize itemSize(qRound(width()), qRound(height()));
+ node->setSize(itemSize);
+ QSize textureSize = (hasTextureSize ? d->textureSize : itemSize)
+ * window()->effectiveDevicePixelRatio();
+ node->setTextureSize(textureSize);
+ }
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);
node->setMipmapping(d->mipmap);
node->setOpaquePainting(d->opaquePainting);
node->setFillColor(d->fillColor);
- node->setContentsScale(d->contentsScale);
node->setDirty(d->dirtyRect);
node->update();
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
index 28eb3398a0..8c9ae2eebb 100644
--- a/src/quick/items/qquickpainteditem.h
+++ b/src/quick/items/qquickpainteditem.h
@@ -48,6 +48,8 @@ class Q_QUICK_EXPORT QQuickPaintedItem : public QQuickItem
Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
Q_PROPERTY(qreal contentsScale READ contentsScale WRITE setContentsScale NOTIFY contentsScaleChanged)
Q_PROPERTY(RenderTarget renderTarget READ renderTarget WRITE setRenderTarget NOTIFY renderTargetChanged)
+ Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged)
+
public:
QQuickPaintedItem(QQuickItem *parent = 0);
virtual ~QQuickPaintedItem();
@@ -88,6 +90,9 @@ public:
qreal contentsScale() const;
void setContentsScale(qreal);
+ QSize textureSize() const;
+ void setTextureSize(const QSize &size);
+
QColor fillColor() const;
void setFillColor(const QColor&);
@@ -104,6 +109,7 @@ Q_SIGNALS:
void contentsSizeChanged();
void contentsScaleChanged();
void renderTargetChanged();
+ void textureSizeChanged();
protected:
QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = 0);
diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h
index 2759d9d683..e77254c0e6 100644
--- a/src/quick/items/qquickpainteditem_p.h
+++ b/src/quick/items/qquickpainteditem_p.h
@@ -52,6 +52,7 @@ public:
QColor fillColor;
QQuickPaintedItem::RenderTarget renderTarget;
QQuickPaintedItem::PerformanceHints performanceHints;
+ QSize textureSize;
QRect dirtyRect;
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index fde3fa06b2..ceb455fb28 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -160,6 +160,7 @@ public:
virtual void setFillColor(const QColor &c) = 0;
virtual void setContentsScale(qreal s) = 0;
virtual void setFastFBOResizing(bool dynamic) = 0;
+ virtual void setTextureSize(const QSize &size) = 0;
virtual QImage toImage() const = 0;
virtual void update() = 0;
diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
index 0ba9781e68..38bcc7a3f3 100644
--- a/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
+++ b/src/quick/scenegraph/util/qsgdefaultpainternode.cpp
@@ -136,18 +136,35 @@ void QSGDefaultPainterNode::paint()
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
}
- painter.scale(m_contentsScale, m_contentsScale);
-
- QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
- qFloor(dirtyRect.y()/m_contentsScale),
- qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
- qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
+ QRect clipRect;
+ QRect dirtyTextureRect;
+
+ if (m_contentsScale == 1) {
+ qreal scaleX = m_textureSize.width() / (qreal) m_size.width();
+ qreal scaleY = m_textureSize.height() / (qreal) m_size.height();
+ painter.scale(scaleX, scaleY);
+ clipRect = dirtyRect;
+ dirtyTextureRect = QRectF(dirtyRect.x() * scaleX,
+ dirtyRect.y() * scaleY,
+ dirtyRect.width() * scaleX,
+ dirtyRect.height() * scaleY).toAlignedRect();
+ } else {
+ painter.scale(m_contentsScale, m_contentsScale);
+ QRect sclip(qFloor(dirtyRect.x()/m_contentsScale),
+ qFloor(dirtyRect.y()/m_contentsScale),
+ qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)),
+ qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale)));
+ clipRect = sclip;
+ dirtyTextureRect = dirtyRect;
+ }
- if (!m_dirtyRect.isNull())
- painter.setClipRect(sclip);
+ // only clip if we were originally updating only a subrect
+ if (!m_dirtyRect.isNull()) {
+ painter.setClipRect(clipRect);
+ }
painter.setCompositionMode(QPainter::CompositionMode_Source);
- painter.fillRect(sclip, m_fillColor);
+ painter.fillRect(clipRect, m_fillColor);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
m_item->paint(&painter);
@@ -155,9 +172,9 @@ void QSGDefaultPainterNode::paint()
if (m_actualRenderTarget == QQuickPaintedItem::Image) {
m_texture->setImage(m_image);
- m_texture->setDirtyRect(dirtyRect);
+ m_texture->setDirtyRect(dirtyTextureRect);
} else if (m_multisampledFbo) {
- QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect);
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyTextureRect, m_multisampledFbo, dirtyTextureRect);
}
if (m_multisampledFbo)
@@ -276,7 +293,7 @@ void QSGDefaultPainterNode::updateRenderTarget()
if (!m_image.isNull() && !m_dirtyGeometry)
return;
- m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
+ m_image = QImage(m_textureSize, QImage::Format_ARGB32_Premultiplied);
m_image.fill(Qt::transparent);
}
@@ -302,12 +319,12 @@ void QSGDefaultPainterNode::updateFBOSize()
int fboWidth;
int fboHeight;
if (m_fastFBOResizing) {
- fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_size.width() - 1));
- fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_size.height() - 1));
+ fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_textureSize.width() - 1));
+ fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qNextPowerOfTwo(m_textureSize.height() - 1));
} else {
QSize minimumFBOSize = m_context->sceneGraphContext()->minimumFBOSize();
- fboWidth = qMax(minimumFBOSize.width(), m_size.width());
- fboHeight = qMax(minimumFBOSize.height(), m_size.height());
+ fboWidth = qMax(minimumFBOSize.width(), m_textureSize.width());
+ fboHeight = qMax(minimumFBOSize.height(), m_textureSize.height());
}
m_fboSize = QSize(fboWidth, fboHeight);
@@ -331,6 +348,15 @@ void QSGDefaultPainterNode::setSize(const QSize &size)
return;
m_size = size;
+ m_dirtyGeometry = true;
+}
+
+void QSGDefaultPainterNode::setTextureSize(const QSize &size)
+{
+ if (size == m_textureSize)
+ return;
+
+ m_textureSize = size;
updateFBOSize();
if (m_fbo)
diff --git a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
index 99e415b2d1..115ddc66f2 100644
--- a/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
+++ b/src/quick/scenegraph/util/qsgdefaultpainternode_p.h
@@ -94,6 +94,9 @@ public:
void setFastFBOResizing(bool dynamic);
bool fastFBOResizing() const { return m_fastFBOResizing; }
+ void setTextureSize(const QSize &textureSize);
+ QSize textureSize() const { return m_textureSize; }
+
QImage toImage() const;
void update();
@@ -126,8 +129,12 @@ private:
QSize m_size;
QSize m_fboSize;
+ QSize m_textureSize;
QRect m_dirtyRect;
QColor m_fillColor;
+#if QT_VERSION >= 0x060000
+#warning "Remove m_contentsScale and assume 1 everywhere"
+#endif
qreal m_contentsScale;
bool m_dirtyContents : 1;