1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qsgpainteditem.h"
43 #include <private/qsgpainteditem_p.h>
44 #include <private/qsgpainternode_p.h>
46 #include <private/qsgcontext_p.h>
47 #include <private/qsgadaptationlayer_p.h>
54 \brief The QSGPaintedItem class provides a way to use the QPainter API in the
57 \inmodule QtDeclarative
59 The QSGPaintedItem makes it possible to use the QPainter API with the QML Scene Graph.
60 It sets up a textured rectangle in the Scene Graph and uses a QPainter to paint
61 onto the texture. The render target can be either a QImage or a QOpenGLFramebufferObject.
62 When the render target is a QImage, QPainter first renders into the image then
63 the content is uploaded to the texture.
64 When a QOpenGLFramebufferObject is used, QPainter paints directly onto the texture.
65 Call update() to trigger a repaint.
67 To enable QPainter to do anti-aliased rendering, use setAntialiasing().
69 QSGPaintedItem is meant to make it easier to port old code that is using the
70 QPainter API to the QML Scene Graph API and it should be used only for that purpose.
72 To write your own painted item, you first create a subclass of QSGPaintedItem, and then
73 start by implementing its only pure virtual public function: paint(), which implements
74 the actual painting. To get the size of the area painted by the item, use
75 contentsBoundingRect().
79 \enum QSGPaintedItem::RenderTarget
81 This enum describes QSGPaintedItem's render targets. The render target is the
82 surface QPainter paints onto before the item is rendered on screen.
84 \value Image The default; QPainter paints into a QImage using the raster paint engine.
85 The image's content needs to be uploaded to graphics memory afterward, this operation
86 can potentially be slow if the item is large. This render target allows high quality
87 anti-aliasing and fast item resizing.
89 \value FramebufferObject QPainter paints into a QOpenGLFramebufferObject using the GL
90 paint engine. Painting can be faster as no texture upload is required, but anti-aliasing
91 quality is not as good as if using an image. This render target allows faster rendering
92 in some cases, but you should avoid using it if the item is resized often.
98 \enum QSGPaintedItem::PerformanceHint
100 This enum describes flags that you can enable to improve rendering
101 performance in QSGPaintedItem. By default, none of these flags are set.
103 \value FastFBOResizing If your item gets resized often and you are using the
104 QSGPaintedItem::FramebufferObject render target, set this flag to true to reduce the
105 item resizing time at the cost of using more graphics memory. Resizing a Framebuffer object
106 is a costly operation, by enabling this property the Framebuffer Object will use a texture
107 larger than the actual size of the item to avoid as much as possible resizing it.
113 QSGPaintedItemPrivate::QSGPaintedItemPrivate()
116 , fillColor(Qt::transparent)
117 , renderTarget(QSGPaintedItem::Image)
118 , performanceHints(0)
119 , geometryDirty(false)
120 , contentsDirty(false)
121 , opaquePainting(false)
122 , antialiasing(false)
128 Constructs a QSGPaintedItem with the given \a parent item.
130 QSGPaintedItem::QSGPaintedItem(QSGItem *parent)
131 : QSGItem(*(new QSGPaintedItemPrivate), parent)
133 setFlag(ItemHasContents);
139 QSGPaintedItem::QSGPaintedItem(QSGPaintedItemPrivate &dd, QSGItem *parent)
140 : QSGItem(dd, parent)
142 setFlag(ItemHasContents);
146 Destroys the QSGPaintedItem.
148 QSGPaintedItem::~QSGPaintedItem()
153 Schedules a redraw of the area covered by \a rect in this item. You can call this function
154 whenever your item needs to be redrawn, such as if it changes appearance or size.
156 This function does not cause an immediate paint; instead it schedules a paint request that
157 is processed by the QML Scene Graph when the next frame is rendered. The item will only be
158 redrawn if it is visible.
160 Note that calling this function will trigger a repaint of the whole scene.
164 void QSGPaintedItem::update(const QRect &rect)
167 d->contentsDirty = true;
169 if (rect.isNull() && !d->dirtyRect.isNull())
170 d->dirtyRect = contentsBoundingRect().toAlignedRect();
172 d->dirtyRect |= (contentsBoundingRect() & rect).toAlignedRect();
177 Returns true if this item is opaque; otherwise, false is returned.
179 By default, painted items are not opaque.
181 \sa setOpaquePainting()
183 bool QSGPaintedItem::opaquePainting() const
185 Q_D(const QSGPaintedItem);
186 return d->opaquePainting;
190 If \a opaque is true, the item is opaque; otherwise, it is considered as translucent.
192 Opaque items are not blended with the rest of the scene, you should set this to true
193 if the content of the item is opaque to speed up rendering.
195 By default, painted items are not opaque.
199 void QSGPaintedItem::setOpaquePainting(bool opaque)
203 if (d->opaquePainting == opaque)
206 d->opaquePainting = opaque;
211 Returns true if antialiased painting is enabled; otherwise, false is returned.
213 By default, antialiasing is not enabled.
215 \sa setAntialiasing()
217 bool QSGPaintedItem::antialiasing() const
219 Q_D(const QSGPaintedItem);
220 return d->antialiasing;
224 If \a enable is true, antialiased painting is enabled.
226 By default, antialiasing is not enabled.
230 void QSGPaintedItem::setAntialiasing(bool enable)
234 if (d->antialiasing == enable)
237 d->antialiasing = enable;
242 Returns true if mipmaps are enabled; otherwise, false is returned.
244 By default, mipmapping is not enabled.
248 bool QSGPaintedItem::mipmap() const
250 Q_D(const QSGPaintedItem);
255 If \a enable is true, mipmapping is enabled on the associated texture.
257 Mipmapping increases rendering speed and reduces aliasing artifacts when the item is
260 By default, mipmapping is not enabled.
264 void QSGPaintedItem::setMipmap(bool enable)
268 if (d->mipmap == enable)
276 Returns the performance hints.
278 By default, no performance hint is enabled/
280 \sa setPerformanceHint(), setPerformanceHints()
282 QSGPaintedItem::PerformanceHints QSGPaintedItem::performanceHints() const
284 Q_D(const QSGPaintedItem);
285 return d->performanceHints;
289 Sets the given performance \a hint on the item if \a enabled is true;
290 otherwise clears the performance hint.
292 By default, no performance hint is enabled/
294 \sa setPerformanceHints(), performanceHints()
296 void QSGPaintedItem::setPerformanceHint(QSGPaintedItem::PerformanceHint hint, bool enabled)
299 PerformanceHints oldHints = d->performanceHints;
301 d->performanceHints |= hint;
303 d->performanceHints &= ~hint;
304 if (oldHints != d->performanceHints)
309 Sets the performance hints to \a hints
311 By default, no performance hint is enabled/
313 \sa setPerformanceHint(), performanceHints()
315 void QSGPaintedItem::setPerformanceHints(QSGPaintedItem::PerformanceHints hints)
318 if (d->performanceHints == hints)
320 d->performanceHints = hints;
325 This function returns the outer bounds of the item as a rectangle; all painting must be
326 restricted to inside an item's bounding rect.
328 If the contents size has not been set it reflects the size of the item; otherwise
329 it reflects the contents size scaled by the contents scale.
331 Use this function to know the area painted by the item.
333 \sa QSGItem::width(), QSGItem::height(), contentsSize(), contentsScale()
335 QRectF QSGPaintedItem::contentsBoundingRect() const
337 Q_D(const QSGPaintedItem);
340 QSizeF sz = d->contentsSize * d->contentsScale;
347 return QRectF(0, 0, w, h);
351 \property QSGPaintedItem::contentsSize
352 \brief The size of the contents
354 The contents size is the size of the item in regards to how it is painted
355 using the paint() function. This is distinct from the size of the
356 item in regards to height() and width().
358 QSize QSGPaintedItem::contentsSize() const
360 Q_D(const QSGPaintedItem);
361 return d->contentsSize;
364 void QSGPaintedItem::setContentsSize(const QSize &size)
368 if (d->contentsSize == size)
371 d->contentsSize = size;
376 This convenience function is equivalent to calling setContentsSize(QSize()).
378 void QSGPaintedItem::resetContentsSize()
380 setContentsSize(QSize());
384 \property QSGPaintedItem::contentsScale
385 \brief The scale of the contents
387 All painting happening in paint() is scaled by the contents scale. This is distinct
388 from the scale of the item in regards to scale().
390 The default value is 1.
392 qreal QSGPaintedItem::contentsScale() const
394 Q_D(const QSGPaintedItem);
395 return d->contentsScale;
398 void QSGPaintedItem::setContentsScale(qreal scale)
402 if (d->contentsScale == scale)
405 d->contentsScale = scale;
410 \property QSGPaintedItem::fillColor
411 \brief The item's background fill color.
413 By default, the fill color is set to Qt::transparent.
415 QColor QSGPaintedItem::fillColor() const
417 Q_D(const QSGPaintedItem);
421 void QSGPaintedItem::setFillColor(const QColor &c)
425 if (d->fillColor == c)
431 emit fillColorChanged();
435 \property QSGPaintedItem::renderTarget
436 \brief The item's render target.
438 This property defines which render target the QPainter renders into, it can be either
439 QSGPaintedItem::Image or QSGPaintedItem::FramebufferObject. Both have certains benefits,
440 typically performance versus quality. Using a framebuffer object avoids a costly upload
441 of the image contents to the texture in graphics memory, while using an image enables
442 high quality anti-aliasing.
444 \warning Resizing a framebuffer object is a costly operation, avoid using
445 the QSGPaintedItem::FramebufferObject render target if the item gets resized often.
447 By default, the render target is QSGPaintedItem::Image.
449 QSGPaintedItem::RenderTarget QSGPaintedItem::renderTarget() const
451 Q_D(const QSGPaintedItem);
452 return d->renderTarget;
455 void QSGPaintedItem::setRenderTarget(RenderTarget target)
459 if (d->renderTarget == target)
462 d->renderTarget = target;
465 emit renderTargetChanged();
469 \fn virtual void QSGPaintedItem::paint(QPainter *painter) = 0
471 This function, which is usually called by the QML Scene Graph, paints the
472 contents of an item in local coordinates.
474 The function is called after the item has been filled with the fillColor.
476 Reimplement this function in a QSGPaintedItem subclass to provide the
477 item's painting implementation, using \a painter.
479 \note The QML Scene Graph uses two separate threads, the main thread does things such as
480 processing events or updating animations while a second thread does the actual OpenGL rendering.
481 As a consequence, paint() is not called from the main GUI thread but from the GL enabled
482 renderer thread. At the moment paint() is called, the GUI thread is blocked and this is
483 therefore thread-safe.
487 This function is called after the item's geometry has changed.
489 void QSGPaintedItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
492 d->geometryDirty = true;
493 QSGItem::geometryChanged(newGeometry, oldGeometry);
498 This function is called when the Scene Graph node associated to the item needs to
501 QSGNode *QSGPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
506 if (width() <= 0 || height() <= 0) {
511 QSGPainterNode *node = static_cast<QSGPainterNode *>(oldNode);
513 node = new QSGPainterNode(this);
515 QRectF br = contentsBoundingRect();
517 node->setPreferredRenderTarget(d->renderTarget);
518 node->setFastFBOResizing(d->performanceHints & FastFBOResizing);
519 node->setSize(QSize(qRound(br.width()), qRound(br.height())));
520 node->setSmoothPainting(d->antialiasing);
521 node->setLinearFiltering(d->smooth);
522 node->setMipmapping(d->mipmap);
523 node->setOpaquePainting(d->opaquePainting);
524 node->setFillColor(d->fillColor);
525 node->setContentsScale(d->contentsScale);
526 node->setDirty(d->contentsDirty || d->geometryDirty, d->dirtyRect);
529 d->contentsDirty = false;
530 d->geometryDirty = false;
531 d->dirtyRect = QRect();