aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/util')
-rw-r--r--src/quick/scenegraph/util/qsgareaallocator.cpp290
-rw-r--r--src/quick/scenegraph/util/qsgareaallocator_p.h74
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil.cpp805
-rw-r--r--src/quick/scenegraph/util/qsgdistancefieldutil_p.h111
-rw-r--r--src/quick/scenegraph/util/qsgengine.cpp115
-rw-r--r--src/quick/scenegraph/util/qsgengine.h100
-rw-r--r--src/quick/scenegraph/util/qsgflatcolormaterial.cpp202
-rw-r--r--src/quick/scenegraph/util/qsgflatcolormaterial.h72
-rw-r--r--src/quick/scenegraph/util/qsgpainternode.cpp464
-rw-r--r--src/quick/scenegraph/util/qsgpainternode_p.h158
-rw-r--r--src/quick/scenegraph/util/qsgsimplematerial.h220
-rw-r--r--src/quick/scenegraph/util/qsgsimplerectnode.cpp132
-rw-r--r--src/quick/scenegraph/util/qsgsimplerectnode.h75
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.cpp154
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.h80
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp541
-rw-r--r--src/quick/scenegraph/util/qsgtexture.h132
-rw-r--r--src/quick/scenegraph/util/qsgtexture_p.h119
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp410
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.h99
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial_p.h71
-rw-r--r--src/quick/scenegraph/util/qsgtextureprovider.cpp59
-rw-r--r--src/quick/scenegraph/util/qsgtextureprovider_p.h66
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.cpp173
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.h67
25 files changed, 4789 insertions, 0 deletions
diff --git a/src/quick/scenegraph/util/qsgareaallocator.cpp b/src/quick/scenegraph/util/qsgareaallocator.cpp
new file mode 100644
index 0000000000..c5171f1c93
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgareaallocator.cpp
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgareaallocator_p.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpoint.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace
+{
+ enum SplitType
+ {
+ VerticalSplit,
+ HorizontalSplit
+ };
+
+ static const int maxMargin = 2;
+}
+
+struct QSGAreaAllocatorNode
+{
+ QSGAreaAllocatorNode(QSGAreaAllocatorNode *parent);
+ ~QSGAreaAllocatorNode();
+ inline bool isLeaf();
+
+ QSGAreaAllocatorNode *parent;
+ QSGAreaAllocatorNode *left;
+ QSGAreaAllocatorNode *right;
+ int split; // only valid for inner nodes.
+ SplitType splitType;
+ bool isOccupied; // only valid for leaf nodes.
+};
+
+QSGAreaAllocatorNode::QSGAreaAllocatorNode(QSGAreaAllocatorNode *parent)
+ : parent(parent)
+ , left(0)
+ , right(0)
+ , isOccupied(false)
+{
+}
+
+QSGAreaAllocatorNode::~QSGAreaAllocatorNode()
+{
+ delete left;
+ delete right;
+}
+
+bool QSGAreaAllocatorNode::isLeaf()
+{
+ Q_ASSERT((left != 0) == (right != 0));
+ return !left;
+}
+
+
+QSGAreaAllocator::QSGAreaAllocator(const QSize &size) : m_size(size)
+{
+ m_root = new QSGAreaAllocatorNode(0);
+}
+
+QSGAreaAllocator::~QSGAreaAllocator()
+{
+ delete m_root;
+}
+
+QRect QSGAreaAllocator::allocate(const QSize &size)
+{
+ QPoint point;
+ bool result = allocateInNode(size, point, QRect(QPoint(0, 0), m_size), m_root);
+ return result ? QRect(point, size) : QRect();
+}
+
+bool QSGAreaAllocator::deallocate(const QRect &rect)
+{
+ return deallocateInNode(rect.topLeft(), m_root);
+}
+
+bool QSGAreaAllocator::allocateInNode(const QSize &size, QPoint &result, const QRect &currentRect, QSGAreaAllocatorNode *node)
+{
+ if (size.width() > currentRect.width() || size.height() > currentRect.height())
+ return false;
+
+ if (node->isLeaf()) {
+ if (node->isOccupied)
+ return false;
+ if (size.width() + maxMargin >= currentRect.width() && size.height() + maxMargin >= currentRect.height()) {
+ //Snug fit, occupy entire rectangle.
+ node->isOccupied = true;
+ result = currentRect.topLeft();
+ return true;
+ }
+ // TODO: Reuse nodes.
+ // Split node.
+ node->left = new QSGAreaAllocatorNode(node);
+ node->right = new QSGAreaAllocatorNode(node);
+ QRect splitRect = currentRect;
+ if ((currentRect.width() - size.width()) * currentRect.height() < (currentRect.height() - size.height()) * currentRect.width()) {
+ node->splitType = HorizontalSplit;
+ node->split = currentRect.top() + size.height();
+ splitRect.setHeight(size.height());
+ } else {
+ node->splitType = VerticalSplit;
+ node->split = currentRect.left() + size.width();
+ splitRect.setWidth(size.width());
+ }
+ return allocateInNode(size, result, splitRect, node->left);
+ } else {
+ // TODO: avoid unnecessary recursion.
+ // has been split.
+ QRect leftRect = currentRect;
+ QRect rightRect = currentRect;
+ if (node->splitType == HorizontalSplit) {
+ leftRect.setHeight(node->split - leftRect.top());
+ rightRect.setTop(node->split);
+ } else {
+ leftRect.setWidth(node->split - leftRect.left());
+ rightRect.setLeft(node->split);
+ }
+ if (allocateInNode(size, result, leftRect, node->left))
+ return true;
+ if (allocateInNode(size, result, rightRect, node->right))
+ return true;
+ return false;
+ }
+}
+
+bool QSGAreaAllocator::deallocateInNode(const QPoint &pos, QSGAreaAllocatorNode *node)
+{
+ while (!node->isLeaf()) {
+ // has been split.
+ int cmp = node->splitType == HorizontalSplit ? pos.y() : pos.x();
+ node = cmp < node->split ? node->left : node->right;
+ }
+ if (!node->isOccupied)
+ return false;
+ node->isOccupied = false;
+ mergeNodeWithNeighbors(node);
+ return true;
+}
+
+void QSGAreaAllocator::mergeNodeWithNeighbors(QSGAreaAllocatorNode *node)
+{
+ bool done = false;
+ QSGAreaAllocatorNode *parent = 0;
+ QSGAreaAllocatorNode *current = 0;
+ QSGAreaAllocatorNode *sibling;
+ while (!done) {
+ Q_ASSERT(node->isLeaf());
+ Q_ASSERT(!node->isOccupied);
+ if (node->parent == 0)
+ return; // No neighbours.
+
+ SplitType splitType = SplitType(node->parent->splitType);
+ done = true;
+
+ /* Special case. Might be faster than going through the general code path.
+ // Merge with sibling.
+ parent = node->parent;
+ sibling = (node == parent->left ? parent->right : parent->left);
+ if (sibling->isLeaf() && !sibling->isOccupied) {
+ Q_ASSERT(!sibling->right);
+ node = parent;
+ parent->isOccupied = false;
+ delete parent->left;
+ delete parent->right;
+ parent->left = parent->right = 0;
+ done = false;
+ continue;
+ }
+ */
+
+ // Merge with left neighbour.
+ current = node;
+ parent = current->parent;
+ while (parent && current == parent->left && parent->splitType == splitType) {
+ current = parent;
+ parent = parent->parent;
+ }
+
+ if (parent && parent->splitType == splitType) {
+ Q_ASSERT(current == parent->right);
+ Q_ASSERT(parent->left);
+
+ QSGAreaAllocatorNode *neighbor = parent->left;
+ while (neighbor->right && neighbor->splitType == splitType)
+ neighbor = neighbor->right;
+
+ if (neighbor->isLeaf() && neighbor->parent->splitType == splitType && !neighbor->isOccupied) {
+ // Left neighbour can be merged.
+ parent->split = neighbor->parent->split;
+
+ parent = neighbor->parent;
+ sibling = neighbor == parent->left ? parent->right : parent->left;
+ QSGAreaAllocatorNode **nodeRef = &m_root;
+ if (parent->parent) {
+ if (parent == parent->parent->left)
+ nodeRef = &parent->parent->left;
+ else
+ nodeRef = &parent->parent->right;
+ }
+ sibling->parent = parent->parent;
+ *nodeRef = sibling;
+ parent->left = parent->right = 0;
+ delete parent;
+ delete neighbor;
+ done = false;
+ }
+ }
+
+ // Merge with right neighbour.
+ current = node;
+ parent = current->parent;
+ while (parent && current == parent->right && parent->splitType == splitType) {
+ current = parent;
+ parent = parent->parent;
+ }
+
+ if (parent && parent->splitType == splitType) {
+ Q_ASSERT(current == parent->left);
+ Q_ASSERT(parent->right);
+
+ QSGAreaAllocatorNode *neighbor = parent->right;
+ while (neighbor->left && neighbor->splitType == splitType)
+ neighbor = neighbor->left;
+
+ if (neighbor->isLeaf() && neighbor->parent->splitType == splitType && !neighbor->isOccupied) {
+ // Right neighbour can be merged.
+ parent->split = neighbor->parent->split;
+
+ parent = neighbor->parent;
+ sibling = neighbor == parent->left ? parent->right : parent->left;
+ QSGAreaAllocatorNode **nodeRef = &m_root;
+ if (parent->parent) {
+ if (parent == parent->parent->left)
+ nodeRef = &parent->parent->left;
+ else
+ nodeRef = &parent->parent->right;
+ }
+ sibling->parent = parent->parent;
+ *nodeRef = sibling;
+ parent->left = parent->right = 0;
+ delete parent;
+ delete neighbor;
+ done = false;
+ }
+ }
+ } // end while(!done)
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgareaallocator_p.h b/src/quick/scenegraph/util/qsgareaallocator_p.h
new file mode 100644
index 0000000000..be26046865
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgareaallocator_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AREAALLOCATOR_H
+#define AREAALLOCATOR_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRect;
+class QPoint;
+struct QSGAreaAllocatorNode;
+class Q_QUICK_EXPORT QSGAreaAllocator
+{
+public:
+ QSGAreaAllocator(const QSize &size);
+ ~QSGAreaAllocator();
+
+ QRect allocate(const QSize &size);
+ bool deallocate(const QRect &rect);
+ bool isEmpty() const { return m_root == 0; }
+ QSize size() const { return m_size; }
+private:
+ bool allocateInNode(const QSize &size, QPoint &result, const QRect &currentRect, QSGAreaAllocatorNode *node);
+ bool deallocateInNode(const QPoint &pos, QSGAreaAllocatorNode *node);
+ void mergeNodeWithNeighbors(QSGAreaAllocatorNode *node);
+
+ QSGAreaAllocatorNode *m_root;
+ QSize m_size;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil.cpp b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
new file mode 100644
index 0000000000..d1b0445ee0
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil.cpp
@@ -0,0 +1,805 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgdistancefieldutil_p.h"
+
+#include <qmath.h>
+#include <private/qsgpathsimplifier_p.h>
+#include <private/qsgadaptationlayer_p.h>
+#include <QtGui/private/qopenglengineshadersource_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static float defaultThresholdFunc(float glyphScale)
+{
+ static float base = qgetenv("QT_DF_BASE").isEmpty() ? 0.5f : qgetenv("QT_DF_BASE").toFloat();
+ static float baseDev = qgetenv("QT_DF_BASEDEVIATION").isEmpty() ? 0.065f : qgetenv("QT_DF_BASEDEVIATION").toFloat();
+ static float devScaleMin = qgetenv("QT_DF_SCALEFORMAXDEV").isEmpty() ? 0.15f : qgetenv("QT_DF_SCALEFORMAXDEV").toFloat();
+ static float devScaleMax = qgetenv("QT_DF_SCALEFORNODEV").isEmpty() ? 0.3f : qgetenv("QT_DF_SCALEFORNODEV").toFloat();
+ return base - ((qBound(devScaleMin, glyphScale, devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev);
+}
+
+static float defaultAntialiasingSpreadFunc(float glyphScale)
+{
+ static float range = qgetenv("QT_DF_RANGE").isEmpty() ? 0.06f : qgetenv("QT_DF_RANGE").toFloat();
+ return range / glyphScale;
+}
+
+namespace
+{
+ enum FillHDir
+ {
+ LeftToRight,
+ RightToLeft
+ };
+
+ enum FillVDir
+ {
+ TopDown,
+ BottomUp
+ };
+
+ enum FillClip
+ {
+ NoClip,
+ Clip
+ };
+}
+
+template <FillClip clip, FillHDir dir>
+inline void fillLine(qint32 *, int, int, int, qint32, qint32)
+{
+}
+
+template <>
+inline void fillLine<Clip, LeftToRight>(qint32 *line, int width, int lx, int rx, qint32 d, qint32 dd)
+{
+ int fromX = qMax(0, lx >> 8);
+ int toX = qMin(width, rx >> 8);
+ int x = toX - fromX;
+ if (x <= 0)
+ return;
+ qint32 val = d + (((fromX << 8) + 0xff - lx) * dd >> 8);
+ line += fromX;
+ do {
+ *line = abs(val) < abs(*line) ? val : *line;
+ val += dd;
+ ++line;
+ } while (--x);
+}
+
+template <>
+inline void fillLine<Clip, RightToLeft>(qint32 *line, int width, int lx, int rx, qint32 d, qint32 dd)
+{
+ int fromX = qMax(0, lx >> 8);
+ int toX = qMin(width, rx >> 8);
+ int x = toX - fromX;
+ if (x <= 0)
+ return;
+ qint32 val = d + (((toX << 8) + 0xff - rx) * dd >> 8);
+ line += toX;
+ do {
+ val -= dd;
+ --line;
+ *line = abs(val) < abs(*line) ? val : *line;
+ } while (--x);
+}
+
+template <>
+inline void fillLine<NoClip, LeftToRight>(qint32 *line, int, int lx, int rx, qint32 d, qint32 dd)
+{
+ int fromX = lx >> 8;
+ int toX = rx >> 8;
+ int x = toX - fromX;
+ if (x <= 0)
+ return;
+ qint32 val = d + ((~lx & 0xff) * dd >> 8);
+ line += fromX;
+ do {
+ *line = abs(val) < abs(*line) ? val : *line;
+ val += dd;
+ ++line;
+ } while (--x);
+}
+
+template <>
+inline void fillLine<NoClip, RightToLeft>(qint32 *line, int, int lx, int rx, qint32 d, qint32 dd)
+{
+ int fromX = lx >> 8;
+ int toX = rx >> 8;
+ int x = toX - fromX;
+ if (x <= 0)
+ return;
+ qint32 val = d + ((~rx & 0xff) * dd >> 8);
+ line += toX;
+ do {
+ val -= dd;
+ --line;
+ *line = abs(val) < abs(*line) ? val : *line;
+ } while (--x);
+}
+
+template <FillClip clip, FillVDir vDir, FillHDir hDir>
+inline void fillLines(qint32 *bits, int width, int height, int upperY, int lowerY,
+ int &lx, int ldx, int &rx, int rdx, qint32 &d, qint32 ddy, qint32 ddx)
+{
+ Q_UNUSED(height);
+ Q_ASSERT(upperY < lowerY);
+ int y = lowerY - upperY;
+ if (vDir == TopDown) {
+ qint32 *line = bits + upperY * width;
+ do {
+ fillLine<clip, hDir>(line, width, lx, rx, d, ddx);
+ lx += ldx;
+ d += ddy;
+ rx += rdx;
+ line += width;
+ } while (--y);
+ } else {
+ qint32 *line = bits + lowerY * width;
+ do {
+ lx -= ldx;
+ d -= ddy;
+ rx -= rdx;
+ line -= width;
+ fillLine<clip, hDir>(line, width, lx, rx, d, ddx);
+ } while (--y);
+ }
+}
+
+template <FillClip clip>
+void drawTriangle(qint32 *bits, int width, int height, const QPoint *center,
+ const QPoint *v1, const QPoint *v2, qint32 value)
+{
+ const int y1 = clip == Clip ? qBound(0, v1->y() >> 8, height) : v1->y() >> 8;
+ const int y2 = clip == Clip ? qBound(0, v2->y() >> 8, height) : v2->y() >> 8;
+ const int yC = clip == Clip ? qBound(0, center->y() >> 8, height) : center->y() >> 8;
+
+ const int v1Frac = clip == Clip ? (y1 << 8) + 0xff - v1->y() : ~v2->y() & 0xff;
+ const int v2Frac = clip == Clip ? (y2 << 8) + 0xff - v2->y() : ~v1->y() & 0xff;
+ const int centerFrac = clip == Clip ? (yC << 8) + 0xff - center->y() : ~center->y() & 0xff;
+
+ int dx1 = 0, x1 = 0, dx2 = 0, x2 = 0;
+ qint32 dd1, d1, dd2, d2;
+ if (v1->y() != center->y()) {
+ dx1 = ((v1->x() - center->x()) << 8) / (v1->y() - center->y());
+ x1 = center->x() + centerFrac * (v1->x() - center->x()) / (v1->y() - center->y());
+ }
+ if (v2->y() != center->y()) {
+ dx2 = ((v2->x() - center->x()) << 8) / (v2->y() - center->y());
+ x2 = center->x() + centerFrac * (v2->x() - center->x()) / (v2->y() - center->y());
+ }
+
+ const qint32 div = (v2->x() - center->x()) * (v1->y() - center->y())
+ - (v2->y() - center->y()) * (v1->x() - center->x());
+ const qint32 dd = div ? qint32((qint64(value * (v1->y() - v2->y())) << 8) / div) : 0;
+
+ if (y2 < yC) {
+ if (y1 < yC) {
+ // Center at the bottom.
+ if (y2 < y1) {
+ // y2 < y1 < yC
+ // Long right edge.
+ d1 = centerFrac * value / (v1->y() - center->y());
+ dd1 = ((value << 8) / (v1->y() - center->y()));
+ fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y1, yC, x1, dx1,
+ x2, dx2, d1, dd1, dd);
+ dx1 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ x1 = v1->x() + v1Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y2, y1, x1, dx1,
+ x2, dx2, value, 0, dd);
+ } else {
+ // y1 <= y2 < yC
+ // Long left edge.
+ d2 = centerFrac * value / (v2->y() - center->y());
+ dd2 = ((value << 8) / (v2->y() - center->y()));
+ fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y2, yC, x1, dx1,
+ x2, dx2, d2, dd2, dd);
+ if (y1 != y2) {
+ dx2 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ x2 = v2->x() + v2Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y1, y2, x1, dx1,
+ x2, dx2, value, 0, dd);
+ }
+ }
+ } else {
+ // y2 < yC <= y1
+ // Center to the right.
+ int dx = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ int xUp, xDn;
+ xUp = xDn = v2->x() + (clip == Clip ? (yC << 8) + 0xff - v2->y()
+ : (center->y() | 0xff) - v2->y())
+ * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, BottomUp, LeftToRight>(bits, width, height, y2, yC, xUp, dx,
+ x2, dx2, value, 0, dd);
+ if (yC != y1)
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, yC, y1, xDn, dx,
+ x1, dx1, value, 0, dd);
+ }
+ } else {
+ if (y1 < yC) {
+ // y1 < yC <= y2
+ // Center to the left.
+ int dx = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ int xUp, xDn;
+ xUp = xDn = v1->x() + (clip == Clip ? (yC << 8) + 0xff - v1->y()
+ : (center->y() | 0xff) - v1->y())
+ * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, BottomUp, RightToLeft>(bits, width, height, y1, yC, x1, dx1,
+ xUp, dx, value, 0, dd);
+ if (yC != y2)
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yC, y2, x2, dx2,
+ xDn, dx, value, 0, dd);
+ } else {
+ // Center at the top.
+ if (y2 < y1) {
+ // yC <= y2 < y1
+ // Long right edge.
+ if (yC != y2) {
+ d2 = centerFrac * value / (v2->y() - center->y());
+ dd2 = ((value << 8) / (v2->y() - center->y()));
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, yC, y2, x2, dx2,
+ x1, dx1, d2, dd2, dd);
+ }
+ dx2 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ x2 = v2->x() + v2Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, y2, y1, x2, dx2,
+ x1, dx1, value, 0, dd);
+ } else {
+ // Long left edge.
+ // yC <= y1 <= y2
+ if (yC != y1) {
+ d1 = centerFrac * value / (v1->y() - center->y());
+ dd1 = ((value << 8) / (v1->y() - center->y()));
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yC, y1, x2, dx2,
+ x1, dx1, d1, dd1, dd);
+ }
+ if (y1 != y2) {
+ dx1 = ((v1->x() - v2->x()) << 8) / (v1->y() - v2->y());
+ x1 = v1->x() + v1Frac * (v1->x() - v2->x()) / (v1->y() - v2->y());
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, y1, y2, x2, dx2,
+ x1, dx1, value, 0, dd);
+ }
+ }
+ }
+ }
+}
+
+template <FillClip clip>
+void drawRectangle(qint32 *bits, int width, int height,
+ const QPoint *int1, const QPoint *center1, const QPoint *ext1,
+ const QPoint *int2, const QPoint *center2, const QPoint *ext2,
+ qint32 extValue)
+{
+ if (center1->y() > center2->y()) {
+ qSwap(center1, center2);
+ qSwap(int1, ext2);
+ qSwap(ext1, int2);
+ extValue = -extValue;
+ }
+
+ Q_ASSERT(ext1->x() - center1->x() == center1->x() - int1->x());
+ Q_ASSERT(ext1->y() - center1->y() == center1->y() - int1->y());
+ Q_ASSERT(ext2->x() - center2->x() == center2->x() - int2->x());
+ Q_ASSERT(ext2->y() - center2->y() == center2->y() - int2->y());
+
+ const int yc1 = clip == Clip ? qBound(0, center1->y() >> 8, height) : center1->y() >> 8;
+ const int yc2 = clip == Clip ? qBound(0, center2->y() >> 8, height) : center2->y() >> 8;
+ const int yi1 = clip == Clip ? qBound(0, int1->y() >> 8, height) : int1->y() >> 8;
+ const int yi2 = clip == Clip ? qBound(0, int2->y() >> 8, height) : int2->y() >> 8;
+ const int ye1 = clip == Clip ? qBound(0, ext1->y() >> 8, height) : ext1->y() >> 8;
+ const int ye2 = clip == Clip ? qBound(0, ext2->y() >> 8, height) : ext2->y() >> 8;
+
+ const int center1Frac = clip == Clip ? (yc1 << 8) + 0xff - center1->y() : ~center1->y() & 0xff;
+ const int center2Frac = clip == Clip ? (yc2 << 8) + 0xff - center2->y() : ~center2->y() & 0xff;
+ const int int1Frac = clip == Clip ? (yi1 << 8) + 0xff - int1->y() : ~int1->y() & 0xff;
+ const int ext1Frac = clip == Clip ? (ye1 << 8) + 0xff - ext1->y() : ~ext1->y() & 0xff;
+
+ int dxC = 0, dxE = 0; // cap slope, edge slope
+ qint32 ddC = 0;
+ if (ext1->y() != int1->y()) {
+ dxC = ((ext1->x() - int1->x()) << 8) / (ext1->y() - int1->y());
+ ddC = (extValue << 9) / (ext1->y() - int1->y());
+ }
+ if (ext1->y() != ext2->y())
+ dxE = ((ext1->x() - ext2->x()) << 8) / (ext1->y() - ext2->y());
+
+ const qint32 div = (ext1->x() - int1->x()) * (ext2->y() - int1->y())
+ - (ext1->y() - int1->y()) * (ext2->x() - int1->x());
+ const qint32 dd = div ? qint32((qint64(extValue * (ext2->y() - ext1->y())) << 9) / div) : 0;
+
+ int xe1, xe2, xc1, xc2;
+ qint32 d;
+
+ qint32 intValue = -extValue;
+
+ if (center2->x() < center1->x()) {
+ // Leaning to the right. '/'
+ if (int1->y() < ext2->y()) {
+ // Mostly vertical.
+ Q_ASSERT(ext1->y() != ext2->y());
+ xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ if (ye1 != yi1) {
+ xc2 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc2 += (ye1 - yc1) * dxC;
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, yi1, xe1, dxE,
+ xc2, dxC, extValue, 0, dd);
+ }
+ if (yi1 != ye2)
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, yi1, ye2, xe1, dxE,
+ xe2, dxE, extValue, 0, dd);
+ if (ye2 != yi2) {
+ xc1 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc1 += (ye2 - yc2) * dxC;
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, ye2, yi2, xc1, dxC,
+ xe2, dxE, intValue, 0, dd);
+ }
+ } else {
+ // Mostly horizontal.
+ Q_ASSERT(ext1->y() != int1->y());
+ xc1 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc2 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc1 += (ye2 - yc2) * dxC;
+ xc2 += (ye1 - yc1) * dxC;
+ if (ye1 != ye2) {
+ xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, ye2, xe1, dxE,
+ xc2, dxC, extValue, 0, dd);
+ }
+ if (ye2 != yi1) {
+ d = (clip == Clip ? (ye2 << 8) + 0xff - center2->y()
+ : (ext2->y() | 0xff) - center2->y())
+ * 2 * extValue / (ext1->y() - int1->y());
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye2, yi1, xc1, dxC,
+ xc2, dxC, d, ddC, dd);
+ }
+ if (yi1 != yi2) {
+ xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, yi2, xc1, dxC,
+ xe2, dxE, intValue, 0, dd);
+ }
+ }
+ } else {
+ // Leaning to the left. '\'
+ if (ext1->y() < int2->y()) {
+ // Mostly vertical.
+ Q_ASSERT(ext1->y() != ext2->y());
+ xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ if (yi1 != ye1) {
+ xc1 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc1 += (yi1 - yc1) * dxC;
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, ye1, xc1, dxC,
+ xe2, dxE, intValue, 0, dd);
+ }
+ if (ye1 != yi2)
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, ye1, yi2, xe1, dxE,
+ xe2, dxE, intValue, 0, dd);
+ if (yi2 != ye2) {
+ xc2 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc2 += (yi2 - yc2) * dxC;
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, yi2, ye2, xe1, dxE,
+ xc2, dxC, extValue, 0, dd);
+ }
+ } else {
+ // Mostly horizontal.
+ Q_ASSERT(ext1->y() != int1->y());
+ xc1 = center1->x() + center1Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc2 = center2->x() + center2Frac * (ext1->x() - int1->x()) / (ext1->y() - int1->y());
+ xc1 += (yi1 - yc1) * dxC;
+ xc2 += (yi2 - yc2) * dxC;
+ if (yi1 != yi2) {
+ xe2 = int1->x() + int1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi1, yi2, xc1, dxC,
+ xe2, dxE, intValue, 0, dd);
+ }
+ if (yi2 != ye1) {
+ d = (clip == Clip ? (yi2 << 8) + 0xff - center2->y()
+ : (int2->y() | 0xff) - center2->y())
+ * 2 * extValue / (ext1->y() - int1->y());
+ fillLines<clip, TopDown, RightToLeft>(bits, width, height, yi2, ye1, xc1, dxC,
+ xc2, dxC, d, ddC, dd);
+ }
+ if (ye1 != ye2) {
+ xe1 = ext1->x() + ext1Frac * (ext1->x() - ext2->x()) / (ext1->y() - ext2->y());
+ fillLines<clip, TopDown, LeftToRight>(bits, width, height, ye1, ye2, xe1, dxE,
+ xc2, dxC, extValue, 0, dd);
+ }
+ }
+ }
+}
+
+static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vertices,
+ const quint32 *indices, int indexCount, qint32 value)
+{
+ Q_ASSERT(indexCount != 0);
+ Q_ASSERT(height <= 128);
+ QVarLengthArray<quint8, 16> scans[128];
+ int first = 0;
+ for (int i = 1; i < indexCount; ++i) {
+ quint32 idx1 = indices[i - 1];
+ quint32 idx2 = indices[i];
+ Q_ASSERT(idx1 != quint32(-1));
+ if (idx2 == quint32(-1)) {
+ idx2 = indices[first];
+ Q_ASSERT(idx2 != quint32(-1));
+ first = ++i;
+ }
+ const QPoint *v1 = &vertices[idx1];
+ const QPoint *v2 = &vertices[idx2];
+ if (v2->y() < v1->y())
+ qSwap(v1, v2);
+ int fromY = qMax(0, v1->y() >> 8);
+ int toY = qMin(height, v2->y() >> 8);
+ if (fromY >= toY)
+ continue;
+ int dx = ((v2->x() - v1->x()) << 8) / (v2->y() - v1->y());
+ int x = v1->x() + ((fromY << 8) + 0xff - v1->y()) * (v2->x() - v1->x()) / (v2->y() - v1->y());
+ for (int y = fromY; y < toY; ++y) {
+ quint32 c = quint32(x >> 8);
+ if (c < quint32(width))
+ scans[y].append(quint8(c));
+ x += dx;
+ }
+ }
+ for (int i = 0; i < height; ++i) {
+ quint8 *scanline = scans[i].data();
+ int size = scans[i].size();
+ for (int j = 1; j < size; ++j) {
+ int k = j;
+ quint8 value = scanline[k];
+ for (; k != 0 && value < scanline[k - 1]; --k)
+ scanline[k] = scanline[k - 1];
+ scanline[k] = value;
+ }
+ qint32 *line = bits + i * width;
+ int j = 0;
+ for (; j + 1 < size; j += 2) {
+ for (quint8 x = scanline[j]; x < scanline[j + 1]; ++x)
+ line[x] = value;
+ }
+ if (j < size) {
+ for (int x = scanline[j]; x < width; ++x)
+ line[x] = value;
+ }
+ }
+}
+
+static QImage makeDistanceField(int imgSize, const QPainterPath &path, int dfScale, int offs)
+{
+ QImage image(imgSize, imgSize, QImage::Format_Indexed8);
+
+ if (path.isEmpty()) {
+ image.fill(0);
+ return image;
+ }
+
+ QTransform transform;
+ transform.translate(offs, offs);
+ transform.scale(qreal(1) / dfScale, qreal(1) / dfScale);
+
+ QDataBuffer<quint32> pathIndices(0);
+ QDataBuffer<QPoint> pathVertices(0);
+ qSimplifyPath(path, pathVertices, pathIndices, transform);
+
+ const qint32 interiorColor = -0x7f80; // 8:8 signed format, -127.5
+ const qint32 exteriorColor = 0x7f80; // 8:8 signed format, 127.5
+
+ QScopedArrayPointer<qint32> bits(new qint32[imgSize * imgSize]);
+ for (int i = 0; i < imgSize * imgSize; ++i)
+ bits[i] = exteriorColor;
+
+ const qreal angleStep = qreal(15 * 3.141592653589793238 / 180);
+ const QPoint rotation(qRound(cos(angleStep) * 0x4000),
+ qRound(sin(angleStep) * 0x4000)); // 2:14 signed
+
+ const quint32 *indices = pathIndices.data();
+ QVarLengthArray<QPoint> normals;
+ QVarLengthArray<QPoint> vertices;
+ QVarLengthArray<bool> isConvex;
+ QVarLengthArray<bool> needsClipping;
+
+ drawPolygons(bits.data(), imgSize, imgSize, pathVertices.data(), indices, pathIndices.size(),
+ interiorColor);
+
+ int index = 0;
+
+ while (index < pathIndices.size()) {
+ normals.clear();
+ vertices.clear();
+ needsClipping.clear();
+
+ // Find end of polygon.
+ int end = index;
+ while (indices[end] != quint32(-1))
+ ++end;
+
+ // Calculate vertex normals.
+ for (int next = index, prev = end - 1; next < end; prev = next++) {
+ quint32 fromVertexIndex = indices[prev];
+ quint32 toVertexIndex = indices[next];
+
+ const QPoint &from = pathVertices.at(fromVertexIndex);
+ const QPoint &to = pathVertices.at(toVertexIndex);
+
+ QPoint n(to.y() - from.y(), from.x() - to.x());
+ if (n.x() == 0 && n.y() == 0)
+ continue;
+ int scale = qRound((offs << 16) / sqrt(qreal(n.x() * n.x() + n.y() * n.y()))); // 8:16
+ n.rx() = n.x() * scale >> 8;
+ n.ry() = n.y() * scale >> 8;
+ normals.append(n);
+ QPoint v(to.x() + 0x7f, to.y() + 0x7f);
+ vertices.append(v);
+ needsClipping.append((to.x() < offs << 8) || (to.x() >= (imgSize - offs) << 8)
+ || (to.y() < offs << 8) || (to.y() >= (imgSize - offs) << 8));
+ }
+
+ isConvex.resize(normals.count());
+ for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {
+ isConvex[prev] = normals.at(prev).x() * normals.at(next).y()
+ - normals.at(prev).y() * normals.at(next).x() < 0;
+ }
+
+ // Draw quads.
+ for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {
+ QPoint n = normals.at(next);
+ QPoint intPrev = vertices.at(prev);
+ QPoint extPrev = vertices.at(prev);
+ QPoint intNext = vertices.at(next);
+ QPoint extNext = vertices.at(next);
+
+ extPrev.rx() -= n.x();
+ extPrev.ry() -= n.y();
+ intPrev.rx() += n.x();
+ intPrev.ry() += n.y();
+ extNext.rx() -= n.x();
+ extNext.ry() -= n.y();
+ intNext.rx() += n.x();
+ intNext.ry() += n.y();
+
+ if (needsClipping[prev] || needsClipping[next]) {
+ drawRectangle<Clip>(bits.data(), imgSize, imgSize,
+ &intPrev, &vertices.at(prev), &extPrev,
+ &intNext, &vertices.at(next), &extNext,
+ exteriorColor);
+ } else {
+ drawRectangle<NoClip>(bits.data(), imgSize, imgSize,
+ &intPrev, &vertices.at(prev), &extPrev,
+ &intNext, &vertices.at(next), &extNext,
+ exteriorColor);
+ }
+
+ if (isConvex.at(prev)) {
+ QPoint p = extPrev;
+ if (needsClipping[prev]) {
+ for (;;) {
+ QPoint rn((n.x() * rotation.x() - n.y() * rotation.y()) >> 14,
+ (n.y() * rotation.x() + n.x() * rotation.y()) >> 14);
+ n = rn;
+ if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() <= 0) {
+ p.rx() = vertices.at(prev).x() - normals.at(prev).x();
+ p.ry() = vertices.at(prev).y() - normals.at(prev).y();
+ drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &extPrev, &p, exteriorColor);
+ break;
+ }
+
+ p.rx() = vertices.at(prev).x() - n.x();
+ p.ry() = vertices.at(prev).y() - n.y();
+ drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &extPrev, &p, exteriorColor);
+ extPrev = p;
+ }
+ } else {
+ for (;;) {
+ QPoint rn((n.x() * rotation.x() - n.y() * rotation.y()) >> 14,
+ (n.y() * rotation.x() + n.x() * rotation.y()) >> 14);
+ n = rn;
+ if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() <= 0) {
+ p.rx() = vertices.at(prev).x() - normals.at(prev).x();
+ p.ry() = vertices.at(prev).y() - normals.at(prev).y();
+ drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &extPrev, &p, exteriorColor);
+ break;
+ }
+
+ p.rx() = vertices.at(prev).x() - n.x();
+ p.ry() = vertices.at(prev).y() - n.y();
+ drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &extPrev, &p, exteriorColor);
+ extPrev = p;
+ }
+ }
+ } else {
+ QPoint p = intPrev;
+ if (needsClipping[prev]) {
+ for (;;) {
+ QPoint rn((n.x() * rotation.x() + n.y() * rotation.y()) >> 14,
+ (n.y() * rotation.x() - n.x() * rotation.y()) >> 14);
+ n = rn;
+ if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() >= 0) {
+ p.rx() = vertices.at(prev).x() + normals.at(prev).x();
+ p.ry() = vertices.at(prev).y() + normals.at(prev).y();
+ drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &p, &intPrev, interiorColor);
+ break;
+ }
+
+ p.rx() = vertices.at(prev).x() + n.x();
+ p.ry() = vertices.at(prev).y() + n.y();
+ drawTriangle<Clip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &p, &intPrev, interiorColor);
+ intPrev = p;
+ }
+ } else {
+ for (;;) {
+ QPoint rn((n.x() * rotation.x() + n.y() * rotation.y()) >> 14,
+ (n.y() * rotation.x() - n.x() * rotation.y()) >> 14);
+ n = rn;
+ if (n.x() * normals.at(prev).y() - n.y() * normals.at(prev).x() >= 0) {
+ p.rx() = vertices.at(prev).x() + normals.at(prev).x();
+ p.ry() = vertices.at(prev).y() + normals.at(prev).y();
+ drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &p, &intPrev, interiorColor);
+ break;
+ }
+
+ p.rx() = vertices.at(prev).x() + n.x();
+ p.ry() = vertices.at(prev).y() + n.y();
+ drawTriangle<NoClip>(bits.data(), imgSize, imgSize, &vertices.at(prev),
+ &p, &intPrev, interiorColor);
+ intPrev = p;
+ }
+ }
+ }
+ }
+
+ index = end + 1;
+ }
+
+ const qint32 *inLine = bits.data();
+ uchar *outLine = image.bits();
+ int padding = image.bytesPerLine() - image.width();
+ for (int y = 0; y < imgSize; ++y) {
+ for (int x = 0; x < imgSize; ++x, ++inLine, ++outLine)
+ *outLine = uchar((0x7f80 - *inLine) >> 8);
+ outLine += padding;
+ }
+
+ return image;
+}
+
+bool qt_fontHasNarrowOutlines(const QRawFont &f)
+{
+ QRawFont font = f;
+ font.setPixelSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE);
+ Q_ASSERT(font.isValid());
+
+ QVector<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("O"));
+ if (glyphIndices.size() < 1)
+ return false;
+
+ QImage im = font.alphaMapForGlyph(glyphIndices.at(0), QRawFont::PixelAntialiasing);
+ if (im.isNull())
+ return false;
+
+ int minHThick = 999;
+ int minVThick = 999;
+
+ int thick = 0;
+ bool in = false;
+ int y = (im.height() + 1) / 2;
+ for (int x = 0; x < im.width(); ++x) {
+ int a = qAlpha(im.pixel(x, y));
+ if (a > 127) {
+ in = true;
+ ++thick;
+ } else if (in) {
+ in = false;
+ minHThick = qMin(minHThick, thick);
+ thick = 0;
+ }
+ }
+
+ thick = 0;
+ in = false;
+ int x = (im.width() + 1) / 2;
+ for (int y = 0; y < im.height(); ++y) {
+ int a = qAlpha(im.pixel(x, y));
+ if (a > 127) {
+ in = true;
+ ++thick;
+ } else if (in) {
+ in = false;
+ minVThick = qMin(minVThick, thick);
+ thick = 0;
+ }
+ }
+
+ return minHThick == 1 || minVThick == 1;
+}
+
+QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution)
+{
+ QRawFont renderFont = font;
+ renderFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(doubleResolution) * QT_DISTANCEFIELD_SCALE(doubleResolution));
+
+ QPainterPath path = renderFont.pathForGlyph(glyph);
+ path.translate(-path.boundingRect().topLeft());
+ path.setFillRule(Qt::WindingFill);
+
+ QImage im = makeDistanceField(QT_DISTANCEFIELD_TILESIZE(doubleResolution),
+ path,
+ QT_DISTANCEFIELD_SCALE(doubleResolution),
+ QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution));
+ return im;
+}
+
+QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(QSGContext *c)
+ : sgCtx(c)
+ , m_threshold_func(defaultThresholdFunc)
+ , m_antialiasingSpread_func(defaultAntialiasingSpreadFunc)
+{
+#ifndef QT_OPENGL_ES
+ m_defaultAntialiasingMode = QSGGlyphNode::HighQualitySubPixelAntialiasing;
+#else
+ m_defaultAntialiasingMode = QSGGlyphNode::GrayAntialiasing;
+#endif
+}
+
+QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
+{
+ qDeleteAll(m_caches.values());
+}
+
+QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCacheManager::cache(const QRawFont &font)
+{
+ QRawFontPrivate *fontD = QRawFontPrivate::get(font);
+ QHash<QFontEngine *, QSGDistanceFieldGlyphCache *>::iterator cache = m_caches.find(fontD->fontEngine);
+ if (cache == m_caches.end())
+ cache = m_caches.insert(fontD->fontEngine, sgCtx->createDistanceFieldGlyphCache(font));
+ return cache.value();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgdistancefieldutil_p.h b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
new file mode 100644
index 0000000000..bc28a4d9e1
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgdistancefieldutil_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGDISTANCEFIELDUTIL_H
+#define QSGDISTANCEFIELDUTIL_H
+
+#include <qrawfont.h>
+#include <private/qfontengine_p.h>
+#include <private/qsgadaptationlayer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE 54
+#define QT_DISTANCEFIELD_DEFAULT_TILESIZE 64
+#define QT_DISTANCEFIELD_DEFAULT_SCALE 16
+#define QT_DISTANCEFIELD_DEFAULT_RADIUS 80
+#define QT_DISTANCEFIELD_HIGHGLYPHCOUNT 2000
+
+#define QT_DISTANCEFIELD_BASEFONTSIZE(NarrowOutlineFont) \
+ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE * 2 : \
+ QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE)
+#define QT_DISTANCEFIELD_TILESIZE(NarrowOutlineFont) \
+ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_TILESIZE * 2 : \
+ QT_DISTANCEFIELD_DEFAULT_TILESIZE)
+#define QT_DISTANCEFIELD_SCALE(NarrowOutlineFont) \
+ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_SCALE / 2 : \
+ QT_DISTANCEFIELD_DEFAULT_SCALE)
+#define QT_DISTANCEFIELD_RADIUS(NarrowOutlineFont) \
+ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_RADIUS / 2 : \
+ QT_DISTANCEFIELD_DEFAULT_RADIUS)
+
+
+typedef float (*ThresholdFunc)(float glyphScale);
+typedef float (*AntialiasingSpreadFunc)(float glyphScale);
+
+bool qt_fontHasNarrowOutlines(const QRawFont &f);
+QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution);
+
+
+class QOpenGLShaderProgram;
+class QSGDistanceFieldGlyphCache;
+class QSGContext;
+
+class Q_QUICK_EXPORT QSGDistanceFieldGlyphCacheManager
+{
+public:
+ QSGDistanceFieldGlyphCacheManager(QSGContext *c);
+ ~QSGDistanceFieldGlyphCacheManager();
+
+ QSGDistanceFieldGlyphCache *cache(const QRawFont &font);
+
+ QSGGlyphNode::AntialiasingMode defaultAntialiasingMode() const { return m_defaultAntialiasingMode; }
+ void setDefaultAntialiasingMode(QSGGlyphNode::AntialiasingMode mode) { m_defaultAntialiasingMode = mode; }
+
+ ThresholdFunc thresholdFunc() const { return m_threshold_func; }
+ void setThresholdFunc(ThresholdFunc func) { m_threshold_func = func; }
+
+ AntialiasingSpreadFunc antialiasingSpreadFunc() const { return m_antialiasingSpread_func; }
+ void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; }
+
+private:
+ QHash<QFontEngine *, QSGDistanceFieldGlyphCache *> m_caches;
+
+ QSGContext *sgCtx;
+
+ QSGGlyphNode::AntialiasingMode m_defaultAntialiasingMode;
+ ThresholdFunc m_threshold_func;
+ AntialiasingSpreadFunc m_antialiasingSpread_func;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGDISTANCEFIELDUTIL_H
diff --git a/src/quick/scenegraph/util/qsgengine.cpp b/src/quick/scenegraph/util/qsgengine.cpp
new file mode 100644
index 0000000000..b8c93bab8b
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgengine.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgengine.h"
+
+#include <QtQuick/qquickcanvas.h>
+
+#include <private/qobject_p.h>
+#include <QtGui/QColor>
+
+QT_BEGIN_NAMESPACE
+
+class QSGEnginePrivate : public QObjectPrivate
+{
+public:
+ QSGEnginePrivate()
+ : canvas(0)
+ {
+ }
+
+ QQuickCanvas *canvas;
+};
+
+/*!
+ \class QSGEngine
+ \deprecated
+ */
+
+QSGEngine::QSGEngine(QObject *parent) :
+ QObject(*(new QSGEnginePrivate), parent)
+{
+}
+
+
+QSGEngine::~QSGEngine()
+{
+}
+
+
+void QSGEngine::setCanvas(QQuickCanvas *canvas)
+{
+ d_func()->canvas = canvas;
+ connect(canvas, SIGNAL(afterRendering()), this, SIGNAL(afterRendering()));
+ connect(canvas, SIGNAL(beforeRendering()), this, SIGNAL(beforeRendering()));
+}
+
+void QSGEngine::setClearBeforeRendering(bool enabled)
+{
+ d_func()->canvas->setClearBeforeRendering(enabled);
+}
+
+bool QSGEngine::clearBeforeRendering() const
+{
+ return d_func()->canvas->clearBeforeRendering();
+}
+
+QSGTexture *QSGEngine::createTextureFromImage(const QImage &image) const
+{
+ return d_func()->canvas->createTextureFromImage(image);
+}
+
+QSGTexture *QSGEngine::createTextureFromId(uint id, const QSize &size, TextureOptions options) const
+{
+ return d_func()->canvas->createTextureFromId(id, size, QQuickCanvas::CreateTextureOptions((int) options));
+}
+
+void QSGEngine::setClearColor(const QColor &color)
+{
+ d_func()->canvas->setClearColor(color);
+}
+
+QColor QSGEngine::clearColor() const
+{
+ return d_func()->canvas->clearColor();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgengine.h b/src/quick/scenegraph/util/qsgengine.h
new file mode 100644
index 0000000000..6b7ceb939f
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgengine.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGENGINE_H
+#define QSGENGINE_H
+
+#include <QObject>
+
+#include <QtQuick/qsgtexture.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGEnginePrivate;
+
+class QQuickCanvas;
+
+class Q_QUICK_EXPORT QSGEngine : public QObject
+{
+ Q_OBJECT
+
+ Q_DECLARE_PRIVATE(QSGEngine)
+
+public:
+
+ enum TextureOption {
+ TextureHasAlphaChannel = 0x0001,
+ TextureHasMipmaps = 0x0002,
+ TextureOwnsGLTexture = 0x0004
+ };
+ Q_DECLARE_FLAGS(TextureOptions, TextureOption)
+
+ QSGTexture *createTextureFromImage(const QImage &image) const;
+ QSGTexture *createTextureFromId(uint id, const QSize &size, TextureOptions options = TextureOption(0)) const;
+
+ void setClearBeforeRendering(bool enabled);
+ bool clearBeforeRendering() const;
+
+ void setClearColor(const QColor &color);
+ QColor clearColor() const;
+
+Q_SIGNALS:
+ void beforeRendering();
+ void afterRendering();
+
+private:
+ QSGEngine(QObject *parent = 0);
+ ~QSGEngine();
+
+ friend class QSGContext;
+ friend class QSGContextPrivate;
+ friend class QQuickCanvasPrivate;
+ void setCanvas(QQuickCanvas *canvas);
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGENGINE_H
diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
new file mode 100644
index 0000000000..cf5c7869ea
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgflatcolormaterial.h"
+
+#include <qopenglshaderprogram.h>
+
+QT_BEGIN_NAMESPACE
+
+class FlatColorMaterialShader : public QSGMaterialShader
+{
+public:
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+
+ static QSGMaterialType type;
+
+private:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ int m_matrix_id;
+ int m_color_id;
+};
+
+QSGMaterialType FlatColorMaterialShader::type;
+
+void FlatColorMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+
+ QSGFlatColorMaterial *oldMaterial = static_cast<QSGFlatColorMaterial *>(oldEffect);
+ QSGFlatColorMaterial *newMaterial = static_cast<QSGFlatColorMaterial *>(newEffect);
+
+ const QColor &c = newMaterial->color();
+
+ if (oldMaterial == 0 || c != oldMaterial->color() || state.isOpacityDirty()) {
+ float opacity = state.opacity();
+ QVector4D v(c.redF() * c.alphaF() * opacity,
+ c.greenF() * c.alphaF() * opacity,
+ c.blueF() * c.alphaF() * opacity,
+ c.alphaF() * opacity);
+ program()->setUniformValue(m_color_id, v);
+ }
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+}
+
+char const *const *FlatColorMaterialShader::attributeNames() const
+{
+ static char const *const attr[] = { "vCoord", 0 };
+ return attr;
+}
+
+void FlatColorMaterialShader::initialize()
+{
+ m_matrix_id = program()->uniformLocation("matrix");
+ m_color_id = program()->uniformLocation("color");
+}
+
+const char *FlatColorMaterialShader::vertexShader() const {
+ return
+ "attribute highp vec4 vCoord; \n"
+ "uniform highp mat4 matrix; \n"
+ "void main() { \n"
+ " gl_Position = matrix * vCoord; \n"
+ "}";
+}
+
+const char *FlatColorMaterialShader::fragmentShader() const {
+ return
+ "uniform lowp vec4 color; \n"
+ "void main() { \n"
+ " gl_FragColor = color; \n"
+ "}";
+}
+
+
+
+/*!
+ \class QSGFlatColorMaterial
+ \brief The QSGFlatColorMaterial class provides a convenient way of rendering
+ solid colored geometry in the scene graph.
+
+ \inmodule QtQuick
+
+ The flat color material will fill every pixel in a geometry using
+ a solid color. The color can contain transparency.
+
+ The geometry to be rendered with a flat color material requires
+ vertices in attribute location 0 in the QSGGeometry object to render
+ correctly. The QSGGeometry::defaultAttributes_Point2D() returns an attribute
+ set compatible with this material.
+
+ The flat color material respects both current opacity and current matrix
+ when updating it's rendering state.
+ */
+
+
+/*!
+ Constructs a new flat color material.
+
+ The default color is white.
+ */
+
+QSGFlatColorMaterial::QSGFlatColorMaterial() : m_color(QColor(255, 255, 255))
+{
+}
+
+
+
+/*!
+ \fn QColor QSGFlatColorMaterial::color() const
+
+ Returns this flat color material's color.
+
+ The default color is white.
+ */
+
+
+
+/*!
+ Sets this flat color material's color to \a color.
+ */
+
+void QSGFlatColorMaterial::setColor(const QColor &color)
+{
+ m_color = color;
+ setFlag(Blending, m_color.alpha() != 0xff);
+}
+
+
+
+/*!
+ \internal
+ */
+
+QSGMaterialType *QSGFlatColorMaterial::type() const
+{
+ return &FlatColorMaterialShader::type;
+}
+
+
+
+/*!
+ \internal
+ */
+
+QSGMaterialShader *QSGFlatColorMaterial::createShader() const
+{
+ return new FlatColorMaterialShader;
+}
+
+
+int QSGFlatColorMaterial::compare(const QSGMaterial *other) const
+{
+ const QSGFlatColorMaterial *flat = static_cast<const QSGFlatColorMaterial *>(other);
+ return m_color.rgba() - flat->color().rgba();
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.h b/src/quick/scenegraph/util/qsgflatcolormaterial.h
new file mode 100644
index 0000000000..d788901b8a
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgflatcolormaterial.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FLATCOLORMATERIAL_H
+#define FLATCOLORMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+#include <qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGFlatColorMaterial : public QSGMaterial
+{
+public:
+ QSGFlatColorMaterial();
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+
+ void setColor(const QColor &color);
+ const QColor &color() const { return m_color; }
+
+ int compare(const QSGMaterial *other) const;
+
+private:
+ QColor m_color;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // FLATCOLORMATERIAL_H
diff --git a/src/quick/scenegraph/util/qsgpainternode.cpp b/src/quick/scenegraph/util/qsgpainternode.cpp
new file mode 100644
index 0000000000..640aab967e
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgpainternode.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgpainternode_p.h"
+
+#include <QtQuick/private/qquickpainteditem_p.h>
+
+#include <QtQuick/private/qsgcontext_p.h>
+#include <private/qopenglextensions_p.h>
+#include <qopenglframebufferobject.h>
+#include <qopenglfunctions.h>
+#include <qopenglpaintdevice.h>
+#include <qmath.h>
+#include <qpainter.h>
+
+QT_BEGIN_NAMESPACE
+
+#define QT_MINIMUM_DYNAMIC_FBO_SIZE 64
+
+static inline int qt_next_power_of_two(int v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ ++v;
+ return v;
+}
+
+QSGPainterTexture::QSGPainterTexture()
+ : QSGPlainTexture()
+{
+
+}
+
+void QSGPainterTexture::bind()
+{
+ if (m_dirty_rect.isNull()) {
+ QSGPlainTexture::bind();
+ return;
+ }
+
+ bool oldMipmapsGenerated = m_mipmaps_generated;
+ m_mipmaps_generated = true;
+ QSGPlainTexture::bind();
+ m_mipmaps_generated = oldMipmapsGenerated;
+
+ QImage subImage = m_image.copy(m_dirty_rect);
+
+ int w = m_dirty_rect.width();
+ int h = m_dirty_rect.height();
+
+#ifdef QT_OPENGL_ES
+ glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h,
+ GL_RGBA, GL_UNSIGNED_BYTE, subImage.constBits());
+#else
+ glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h,
+ GL_BGRA, GL_UNSIGNED_BYTE, subImage.constBits());
+#endif
+
+ if (m_has_mipmaps && !m_mipmaps_generated) {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ m_mipmaps_generated = true;
+ }
+
+ m_dirty_texture = false;
+ m_dirty_bind_options = false;
+
+ m_dirty_rect = QRect();
+}
+
+QSGPainterNode::QSGPainterNode(QQuickPaintedItem *item)
+ : QSGGeometryNode()
+ , m_preferredRenderTarget(QQuickPaintedItem::Image)
+ , m_actualRenderTarget(QQuickPaintedItem::Image)
+ , m_item(item)
+ , m_fbo(0)
+ , m_multisampledFbo(0)
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+ , m_texture(0)
+ , m_gl_device(0)
+ , m_size(1, 1)
+ , m_dirtyContents(false)
+ , m_opaquePainting(false)
+ , m_linear_filtering(false)
+ , m_mipmapping(false)
+ , 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<QQuickPaintedItemPrivate *>(QObjectPrivate::get(item))->sceneGraphContext();
+
+ setMaterial(&m_materialO);
+ setOpaqueMaterial(&m_material);
+ setGeometry(&m_geometry);
+}
+
+QSGPainterNode::~QSGPainterNode()
+{
+ delete m_texture;
+ delete m_fbo;
+ delete m_multisampledFbo;
+ delete m_gl_device;
+}
+
+void QSGPainterNode::paint()
+{
+ QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect;
+
+ QPainter painter;
+ if (m_actualRenderTarget == QQuickPaintedItem::Image)
+ painter.begin(&m_image);
+ else {
+ if (!m_gl_device) {
+ m_gl_device = new QOpenGLPaintDevice(m_fboSize);
+ m_gl_device->setPaintFlipped(true);
+ }
+
+ if (m_multisampledFbo)
+ m_multisampledFbo->bind();
+ else
+ m_fbo->bind();
+
+ painter.begin(m_gl_device);
+ }
+
+ if (m_smoothPainting) {
+ painter.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing
+ | 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)));
+
+ if (!m_dirtyRect.isNull())
+ painter.setClipRect(sclip);
+
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(sclip, m_fillColor);
+ painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+
+ m_item->paint(&painter);
+ painter.end();
+
+ if (m_actualRenderTarget == QQuickPaintedItem::Image) {
+ m_texture->setImage(m_image);
+ m_texture->setDirtyRect(dirtyRect);
+ } else if (m_multisampledFbo) {
+ QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect);
+ }
+
+ if (m_multisampledFbo)
+ m_multisampledFbo->release();
+ else if (m_fbo)
+ m_fbo->release();
+
+ m_dirtyRect = QRect();
+}
+
+void QSGPainterNode::update()
+{
+ if (m_dirtyRenderTarget)
+ updateRenderTarget();
+ if (m_dirtyGeometry)
+ updateGeometry();
+ if (m_dirtyTexture)
+ updateTexture();
+
+ if (m_dirtyContents)
+ paint();
+
+ m_dirtyGeometry = false;
+ m_dirtyRenderTarget = false;
+ m_dirtyTexture = false;
+ m_dirtyContents = false;
+}
+
+void QSGPainterNode::updateTexture()
+{
+ m_texture->setHasMipmaps(m_mipmapping);
+ m_texture->setHasAlphaChannel(!m_opaquePainting);
+ m_material.setTexture(m_texture);
+ m_materialO.setTexture(m_texture);
+
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::updateGeometry()
+{
+ QRectF source;
+ if (m_actualRenderTarget == QQuickPaintedItem::Image)
+ source = QRectF(0, 0, 1, 1);
+ else
+ source = QRectF(0, 0, qreal(m_size.width()) / m_fboSize.width(), qreal(m_size.height()) / m_fboSize.height());
+ QRectF dest(0, 0, m_size.width(), m_size.height());
+ if (m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject)
+ dest = QRectF(QPointF(0, m_size.height()), QPointF(m_size.width(), 0));
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry,
+ dest,
+ source);
+ markDirty(DirtyGeometry);
+}
+
+void QSGPainterNode::updateRenderTarget()
+{
+ if (!m_extensionsChecked) {
+ QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
+ m_multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample")
+ && extensions.contains("GL_EXT_framebuffer_blit");
+ m_extensionsChecked = true;
+ }
+
+ m_dirtyContents = true;
+
+ QQuickPaintedItem::RenderTarget oldTarget = m_actualRenderTarget;
+ if (m_preferredRenderTarget == QQuickPaintedItem::Image) {
+ m_actualRenderTarget = QQuickPaintedItem::Image;
+ } else {
+ if (!m_multisamplingSupported && m_smoothPainting)
+ m_actualRenderTarget = QQuickPaintedItem::Image;
+ else
+ m_actualRenderTarget = m_preferredRenderTarget;
+ }
+ if (oldTarget != m_actualRenderTarget) {
+ m_image = QImage();
+ delete m_fbo;
+ delete m_multisampledFbo;
+ m_fbo = m_multisampledFbo = 0;
+ }
+
+ if (m_actualRenderTarget == QQuickPaintedItem::FramebufferObject ||
+ m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject) {
+ const QOpenGLContext *ctx = m_context->glContext();
+ if (m_fbo && !m_dirtyGeometry && (!ctx->format().samples() || !m_multisamplingSupported))
+ return;
+
+ if (m_fboSize.isEmpty())
+ updateFBOSize();
+
+ delete m_fbo;
+ delete m_multisampledFbo;
+ m_fbo = m_multisampledFbo = 0;
+
+ if (m_smoothPainting && ctx->format().samples() && m_multisamplingSupported) {
+ {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setSamples(8);
+ m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
+ m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ } else {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ m_fbo = new QOpenGLFramebufferObject(m_fboSize, format);
+ }
+ } else {
+ if (!m_image.isNull() && !m_dirtyGeometry)
+ return;
+
+ m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
+ m_image.fill(Qt::transparent);
+ }
+
+ QSGPainterTexture *texture = new QSGPainterTexture;
+ if (m_actualRenderTarget == QQuickPaintedItem::Image) {
+ texture->setOwnsTexture(true);
+ texture->setTextureSize(m_size);
+ } else {
+ texture->setTextureId(m_fbo->texture());
+ texture->setOwnsTexture(false);
+ texture->setTextureSize(m_fboSize);
+ }
+
+ if (m_texture)
+ delete m_texture;
+
+ texture->setTextureSize(m_size);
+ m_texture = texture;
+}
+
+void QSGPainterNode::updateFBOSize()
+{
+ 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);
+}
+
+void QSGPainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target)
+{
+ if (m_preferredRenderTarget == target)
+ return;
+
+ m_preferredRenderTarget = target;
+
+ m_dirtyRenderTarget = true;
+ m_dirtyGeometry = true;
+ m_dirtyTexture = true;
+}
+
+void QSGPainterNode::setSize(const QSize &size)
+{
+ if (size == m_size)
+ return;
+
+ m_size = size;
+ updateFBOSize();
+
+ if (m_fbo)
+ m_dirtyRenderTarget = m_fbo->size() != m_fboSize || m_dirtyRenderTarget;
+ else
+ m_dirtyRenderTarget = true;
+ m_dirtyGeometry = true;
+ m_dirtyTexture = true;
+}
+
+void QSGPainterNode::setDirty(const QRect &dirtyRect)
+{
+ m_dirtyContents = true;
+ m_dirtyRect = dirtyRect;
+
+ if (m_mipmapping)
+ m_dirtyTexture = true;
+
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::setOpaquePainting(bool opaque)
+{
+ if (opaque == m_opaquePainting)
+ return;
+
+ m_opaquePainting = opaque;
+ m_dirtyTexture = true;
+}
+
+void QSGPainterNode::setLinearFiltering(bool linearFiltering)
+{
+ if (linearFiltering == m_linear_filtering)
+ return;
+
+ m_linear_filtering = linearFiltering;
+
+ m_material.setFiltering(linearFiltering ? QSGTexture::Linear : QSGTexture::Nearest);
+ m_materialO.setFiltering(linearFiltering ? QSGTexture::Linear : QSGTexture::Nearest);
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::setMipmapping(bool mipmapping)
+{
+ if (mipmapping == m_mipmapping)
+ return;
+
+ m_mipmapping = mipmapping;
+ m_material.setMipmapFiltering(mipmapping ? QSGTexture::Linear : QSGTexture::None);
+ m_materialO.setMipmapFiltering(mipmapping ? QSGTexture::Linear : QSGTexture::None);
+ m_dirtyTexture = true;
+}
+
+void QSGPainterNode::setSmoothPainting(bool s)
+{
+ if (s == m_smoothPainting)
+ return;
+
+ m_smoothPainting = s;
+ m_dirtyRenderTarget = true;
+}
+
+void QSGPainterNode::setFillColor(const QColor &c)
+{
+ if (c == m_fillColor)
+ return;
+
+ m_fillColor = c;
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::setContentsScale(qreal s)
+{
+ if (s == m_contentsScale)
+ return;
+
+ m_contentsScale = s;
+ markDirty(DirtyMaterial);
+}
+
+void QSGPainterNode::setFastFBOResizing(bool dynamic)
+{
+ m_fastFBOResizing = dynamic;
+}
+
+QImage QSGPainterNode::toImage() const
+{
+ if (m_actualRenderTarget == QQuickPaintedItem::Image)
+ return m_image;
+ else
+ return m_fbo->toImage();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgpainternode_p.h b/src/quick/scenegraph/util/qsgpainternode_p.h
new file mode 100644
index 0000000000..85f26f6056
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgpainternode_p.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGPAINTERNODE_P_H
+#define QSGPAINTERNODE_P_H
+
+#include <QtQuick/qsgnode.h>
+#include "qsgtexturematerial.h"
+#include "qsgtexture_p.h"
+
+#include <QtQuick/qquickpainteditem.h>
+
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLFramebufferObject;
+class QOpenGLPaintDevice;
+
+class Q_QUICK_EXPORT QSGPainterTexture : public QSGPlainTexture
+{
+public:
+ QSGPainterTexture();
+
+ void setDirtyRect(const QRect &rect) { m_dirty_rect = rect; }
+
+ void bind();
+
+private:
+ QRect m_dirty_rect;
+};
+
+class Q_QUICK_EXPORT QSGPainterNode : public QSGGeometryNode
+{
+public:
+ QSGPainterNode(QQuickPaintedItem *item);
+ virtual ~QSGPainterNode();
+
+ void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target);
+
+ void setSize(const QSize &size);
+ QSize size() const { return m_size; }
+
+ void setDirty(const QRect &dirtyRect = QRect());
+
+ void setOpaquePainting(bool opaque);
+ bool opaquePainting() const { return m_opaquePainting; }
+
+ void setLinearFiltering(bool linearFiltering);
+ bool linearFiltering() const { return m_linear_filtering; }
+
+ void setMipmapping(bool mipmapping);
+ bool mipmapping() const { return m_mipmapping; }
+
+ void setSmoothPainting(bool s);
+ bool smoothPainting() const { return m_smoothPainting; }
+
+ void setFillColor(const QColor &c);
+ QColor fillColor() const { return m_fillColor; }
+
+ 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();
+
+ void paint();
+
+private:
+ void updateTexture();
+ void updateGeometry();
+ void updateRenderTarget();
+ void updateFBOSize();
+
+ QSGContext *m_context;
+
+ QQuickPaintedItem::RenderTarget m_preferredRenderTarget;
+ QQuickPaintedItem::RenderTarget m_actualRenderTarget;
+
+ QQuickPaintedItem *m_item;
+
+ QOpenGLFramebufferObject *m_fbo;
+ QOpenGLFramebufferObject *m_multisampledFbo;
+ QImage m_image;
+
+ QSGOpaqueTextureMaterial m_material;
+ QSGTextureMaterial m_materialO;
+ QSGGeometry m_geometry;
+ QSGPainterTexture *m_texture;
+ QOpenGLPaintDevice *m_gl_device;
+
+ QSize m_size;
+ QSize m_fboSize;
+ bool m_dirtyContents;
+ QRect m_dirtyRect;
+ bool m_opaquePainting;
+ bool m_linear_filtering;
+ bool m_mipmapping;
+ bool m_smoothPainting;
+ bool m_extensionsChecked;
+ bool m_multisamplingSupported;
+ bool m_fastFBOResizing;
+ QColor m_fillColor;
+ qreal m_contentsScale;
+
+ bool m_dirtyGeometry;
+ bool m_dirtyRenderTarget;
+ bool m_dirtyTexture;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // QSGPAINTERNODE_P_H
diff --git a/src/quick/scenegraph/util/qsgsimplematerial.h b/src/quick/scenegraph/util/qsgsimplematerial.h
new file mode 100644
index 0000000000..44beb135f7
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimplematerial.h
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGSIMPLEMATERIAL_H
+#define QSGSIMPLEMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+template <typename State>
+class QSGSimpleMaterialShader : public QSGMaterialShader
+{
+public:
+ void initialize() {
+ QSGMaterialShader::initialize();
+
+ m_id_matrix = program()->uniformLocation(uniformMatrixName());
+ if (m_id_matrix < 0) {
+ qFatal("QSGSimpleMaterialShader does not implement 'uniform highp mat4 %s;' in its vertex shader",
+ uniformMatrixName());
+ }
+
+ const char *opacity = uniformOpacityName();
+ if (opacity) {
+ m_id_opacity = program()->uniformLocation(uniformOpacityName());
+ if (m_id_opacity < 0) {
+ qFatal("QSGSimpleMaterialShader does not implement 'uniform lowp float %s' in its fragment shader",
+ uniformOpacityName());
+ }
+ } else {
+ m_id_opacity = -1;
+ }
+
+ resolveUniforms();
+ }
+
+ const char *uniformMatrixName() const { return "qt_Matrix"; }
+ const char *uniformOpacityName() const { return "qt_Opacity"; }
+
+ void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
+
+ virtual void updateState(const State *newState, const State *oldState) = 0;
+
+ virtual void resolveUniforms() {}
+
+ virtual QList<QByteArray> attributes() const = 0;
+
+ char const *const *attributeNames() const
+ {
+ if (m_attribute_pointers.size())
+ return m_attribute_pointers.constData();
+
+ QList<QByteArray> names = attributes();
+
+ // Calculate the total number of bytes needed, so we don't get rellocs and
+ // bad pointers while copying over the individual names.
+ // Add an extra byte pr entry for the '\0' char.
+ int total = 0;
+ for (int i=0; i<names.size(); ++i)
+ total += names.at(i).size() + 1;
+ m_attribute_name_data.reserve(total);
+
+ // Copy over the names
+ for (int i=0; i<names.size(); ++i) {
+ m_attribute_pointers << m_attribute_name_data.constData() + m_attribute_name_data.size();
+ m_attribute_name_data.append(names.at(i));
+ m_attribute_name_data.append('\0');
+ }
+
+ // Append the "null" terminator
+ m_attribute_pointers << 0;
+
+ return m_attribute_pointers.constData();
+ }
+
+private:
+ int m_id_matrix;
+ int m_id_opacity;
+
+ mutable QByteArray m_attribute_name_data;
+ mutable QVector<const char *> m_attribute_pointers;
+};
+
+#define QSG_DECLARE_SIMPLE_SHADER(Shader, State) \
+static QSGMaterialShader *createShader() \
+{ \
+ return new Shader; \
+} \
+public: \
+static QSGSimpleMaterial<State> *createMaterial() \
+{ \
+ return new QSGSimpleMaterial<State>(createShader); \
+}
+
+
+typedef QSGMaterialShader *(*PtrShaderCreateFunc)();
+
+
+template <typename State>
+class QSGSimpleMaterial : public QSGMaterial
+{
+
+public:
+ QSGSimpleMaterial(const State &state, PtrShaderCreateFunc func)
+ : m_state(state)
+ , m_func(func)
+ {
+ }
+
+ QSGSimpleMaterial(PtrShaderCreateFunc func)
+ : m_func(func)
+ {
+ }
+
+ QSGMaterialShader *createShader() const { return m_func(); }
+ QSGMaterialType *type() const { return &m_type; }
+
+ State *state() { return &m_state; }
+ const State *state() const { return &m_state; }
+
+private:
+ static QSGMaterialType m_type;
+ State m_state;
+ PtrShaderCreateFunc m_func;
+};
+
+#define QSG_DECLARE_SIMPLE_COMPARABLE_SHADER(Shader, State) \
+static QSGMaterialShader *createShader() \
+{ \
+ return new Shader; \
+} \
+public: \
+static QSGSimpleMaterialComparableMaterial<State> *createMaterial() \
+{ \
+ return new QSGSimpleMaterialComparableMaterial<State>(createShader); \
+}
+
+template <typename State>
+class QSGSimpleMaterialComparableMaterial : public QSGSimpleMaterial<State>
+{
+
+public:
+ QSGSimpleMaterialComparableMaterial(const State &state, PtrShaderCreateFunc func)
+ : QSGSimpleMaterial<State>(state, func) {}
+
+ QSGSimpleMaterialComparableMaterial(PtrShaderCreateFunc func)
+ : QSGSimpleMaterial<State>(func) {}
+
+ int compare(const QSGMaterial *other) const {
+ return QSGSimpleMaterialComparableMaterial<State>::state()->compare(static_cast<const QSGSimpleMaterialComparableMaterial<State> *>(other)->state());
+ }
+};
+
+
+template <typename State>
+QSGMaterialType QSGSimpleMaterial<State>::m_type;
+
+
+template <typename State>
+Q_INLINE_TEMPLATE void QSGSimpleMaterialShader<State>::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
+{
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_id_matrix, state.combinedMatrix());
+ if (state.isOpacityDirty() && m_id_opacity >= 0)
+ program()->setUniformValue(m_id_opacity, state.opacity());
+
+ State *ns = static_cast<QSGSimpleMaterial<State> *>(newMaterial)->state();
+ State *old = 0;
+ if (oldMaterial)
+ old = static_cast<QSGSimpleMaterial<State> *>(oldMaterial)->state();
+ updateState(ns, old);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/quick/scenegraph/util/qsgsimplerectnode.cpp b/src/quick/scenegraph/util/qsgsimplerectnode.cpp
new file mode 100644
index 0000000000..c3dc5354ca
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimplerectnode.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgsimplerectnode.h"
+#include "qsgflatcolormaterial.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSGSimpleRectNode
+
+ \brief The QSGSimpleRectNode class is a convenience class for drawing
+ solid filled rectangles using scenegraph.
+
+ */
+
+
+
+/*!
+ Constructs a QSGSimpleRectNode instance which is spanning \a rect with
+ the color \a color.
+ */
+QSGSimpleRectNode::QSGSimpleRectNode(const QRectF &rect, const QColor &color)
+ : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
+{
+ QSGGeometry::updateRectGeometry(&m_geometry, rect);
+ m_material.setColor(color);
+ setMaterial(&m_material);
+ setGeometry(&m_geometry);
+}
+
+
+
+/*!
+ Constructs a QSGSimpleRectNode instance with an empty rectangle and
+ white color.
+ */
+QSGSimpleRectNode::QSGSimpleRectNode()
+ : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
+{
+ QSGGeometry::updateRectGeometry(&m_geometry, QRectF());
+ setMaterial(&m_material);
+ setGeometry(&m_geometry);
+}
+
+
+
+/*!
+ Sets the rectangle of this rect node to \a rect.
+ */
+void QSGSimpleRectNode::setRect(const QRectF &rect)
+{
+ QSGGeometry::updateRectGeometry(&m_geometry, rect);
+ markDirty(QSGNode::DirtyGeometry);
+}
+
+
+
+/*!
+ Returns the rectangle that this rect node covers.
+ */
+QRectF QSGSimpleRectNode::rect() const
+{
+ const QSGGeometry::Point2D *pts = m_geometry.vertexDataAsPoint2D();
+ return QRectF(pts[0].x,
+ pts[0].y,
+ pts[3].x - pts[0].x,
+ pts[3].y - pts[0].y);
+}
+
+
+/*!
+ Sets the color of this rectangle to \a color. The default
+ color will be white.
+ */
+void QSGSimpleRectNode::setColor(const QColor &color)
+{
+ if (color != m_material.color()) {
+ m_material.setColor(color);
+ markDirty(QSGNode::DirtyMaterial);
+ }
+}
+
+
+
+/*!
+ Returns the color of this rectangle.
+ */
+QColor QSGSimpleRectNode::color() const
+{
+ return m_material.color();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgsimplerectnode.h b/src/quick/scenegraph/util/qsgsimplerectnode.h
new file mode 100644
index 0000000000..6519290cfe
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimplerectnode.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SOLIDRECTNODE_H
+#define SOLIDRECTNODE_H
+
+#include <QtQuick/qsgnode.h>
+#include "qsgflatcolormaterial.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGSimpleRectNode : public QSGGeometryNode
+{
+public:
+ QSGSimpleRectNode(const QRectF &rect, const QColor &color);
+ QSGSimpleRectNode();
+
+ void setRect(const QRectF &rect);
+ inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
+ QRectF rect() const;
+
+ void setColor(const QColor &color);
+ QColor color() const;
+
+private:
+ QSGFlatColorMaterial m_material;
+ QSGGeometry m_geometry;
+ void *reserved;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SOLIDRECTNODE_H
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
new file mode 100644
index 0000000000..00b240e435
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qsgsimpletexturenode.h"
+
+QT_BEGIN_NAMESPACE
+
+static void qsgsimpletexturenode_update(QSGGeometry *g,
+ QSGTexture *texture,
+ const QRectF &rect)
+{
+ if (!texture)
+ return;
+
+ QSize ts = texture->textureSize();
+ QRectF sourceRect(0, 0, ts.width(), ts.height());
+ QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect));
+}
+
+/*!
+ \class QSGSimpleTextureNode
+ \brief The QSGSimpleTextureNode class is provided for convenience to easily draw
+ textured content using the QML scene graph.
+
+ \inmodule QtQuick
+
+ \warning The simple texture node class must have a texture before being
+ added to the scene graph to be rendered.
+*/
+
+/*!
+ Constructs a new simple texture node
+ */
+QSGSimpleTextureNode::QSGSimpleTextureNode()
+ : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+{
+ setGeometry(&m_geometry);
+ setMaterial(&m_material);
+ setOpaqueMaterial(&m_opaque_material);
+}
+
+/*!
+ Sets the filtering to be used for this texture node to \a filtering.
+
+ For smooth scaling, use QSGTexture::Linear; for normal scaling, use
+ QSGTexture::Nearest.
+ */
+void QSGSimpleTextureNode::setFiltering(QSGTexture::Filtering filtering)
+{
+ if (m_material.filtering() == filtering)
+ return;
+
+ m_material.setFiltering(filtering);
+ m_opaque_material.setFiltering(filtering);
+ markDirty(DirtyMaterial);
+}
+
+
+/*!
+ Returns the filtering currently set on this texture node
+ */
+QSGTexture::Filtering QSGSimpleTextureNode::filtering() const
+{
+ return m_material.filtering();
+}
+
+
+/*!
+ Sets the target rect of this texture node to \a r
+ */
+void QSGSimpleTextureNode::setRect(const QRectF &r)
+{
+ if (m_rect == r)
+ return;
+ m_rect = r;
+ qsgsimpletexturenode_update(&m_geometry, texture(), m_rect);
+ markDirty(DirtyGeometry);
+}
+
+
+/*!
+ Returns the target rect of this texture node.
+ */
+QRectF QSGSimpleTextureNode::rect() const
+{
+ return m_rect;
+}
+
+/*!
+ Sets the texture of this texture node to \a texture.
+
+ \warning A texture node must have a texture before being added
+ to the scenegraph to be rendered.
+ */
+void QSGSimpleTextureNode::setTexture(QSGTexture *texture)
+{
+ if (m_material.texture() == texture)
+ return;
+ m_material.setTexture(texture);
+ m_opaque_material.setTexture(texture);
+ qsgsimpletexturenode_update(&m_geometry, texture, m_rect);
+ markDirty(DirtyMaterial);
+}
+
+
+
+/*!
+ Returns the texture for this texture node
+ */
+QSGTexture *QSGSimpleTextureNode::texture() const
+{
+ return m_material.texture();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.h b/src/quick/scenegraph/util/qsgsimpletexturenode.h
new file mode 100644
index 0000000000..605cae11e4
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGSIMPLETEXTURENODE_H
+#define QSGSIMPLETEXTURENODE_H
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsggeometry.h>
+#include "qsgtexturematerial.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGSimpleTextureNode : public QSGGeometryNode
+{
+public:
+ QSGSimpleTextureNode();
+
+ void setRect(const QRectF &rect);
+ inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
+ QRectF rect() const;
+
+ void setTexture(QSGTexture *texture);
+ QSGTexture *texture() const;
+
+ void setFiltering(QSGTexture::Filtering filtering);
+ QSGTexture::Filtering filtering() const;
+
+private:
+ QSGGeometry m_geometry;
+ QSGOpaqueTextureMaterial m_opaque_material;
+ QSGTextureMaterial m_material;
+
+ QRectF m_rect;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGSIMPLETEXTURENODE_H
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
new file mode 100644
index 0000000000..0abbc8dae1
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -0,0 +1,541 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define GL_GLEXT_PROTOTYPES
+
+#include "qsgtexture_p.h"
+#include <qopenglfunctions.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <qthread.h>
+#include <private/qdeclarativedebugtrace_p.h>
+
+#if !defined(QT_NO_DEBUG) && (defined(Q_OS_LINUX) || defined(Q_OS_MAC))
+#include <execinfo.h>
+#include <QHash>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+inline static bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+
+QSGTexturePrivate::QSGTexturePrivate()
+ : wrapChanged(false)
+ , filteringChanged(false)
+ , horizontalWrap(QSGTexture::ClampToEdge)
+ , verticalWrap(QSGTexture::ClampToEdge)
+ , mipmapMode(QSGTexture::None)
+ , filterMode(QSGTexture::Nearest)
+{
+}
+
+#ifndef QT_NO_DEBUG
+
+static int qt_debug_texture_count = 0;
+
+#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
+DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE)
+
+#define BACKTRACE_SIZE 20
+class SGTextureTraceItem
+{
+public:
+ void *backTrace[BACKTRACE_SIZE];
+ size_t backTraceSize;
+};
+
+static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures;
+#endif
+
+inline static void qt_debug_print_texture_count()
+{
+ qDebug("Number of leaked textures: %i", qt_debug_texture_count);
+ qt_debug_texture_count = -1;
+
+#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
+ if (qmlDebugLeakBacktrace()) {
+ while (!qt_debug_allocated_textures.isEmpty()) {
+ QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin();
+ QSGTexture* texture = it.key();
+ SGTextureTraceItem* item = it.value();
+
+ qt_debug_allocated_textures.erase(it);
+
+ qDebug() << "------";
+ qDebug() << "Leaked" << texture << "backtrace:";
+
+ char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize);
+
+ if (symbols) {
+ for (int i=0; i<(int) item->backTraceSize; i++)
+ qDebug("Backtrace <%02d>: %s", i, symbols[i]);
+ free(symbols);
+ }
+
+ qDebug() << "------";
+
+ delete item;
+ }
+ }
+#endif
+}
+
+inline static void qt_debug_add_texture(QSGTexture* texture)
+{
+#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
+ if (qmlDebugLeakBacktrace()) {
+ SGTextureTraceItem* item = new SGTextureTraceItem;
+ item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE);
+ qt_debug_allocated_textures.insert(texture, item);
+ }
+#else
+ Q_UNUSED(texture);
+#endif // Q_OS_LINUX
+
+ ++qt_debug_texture_count;
+
+ static bool atexit_registered = false;
+ if (!atexit_registered) {
+ atexit(qt_debug_print_texture_count);
+ atexit_registered = true;
+ }
+}
+
+static void qt_debug_remove_texture(QSGTexture* texture)
+{
+#if defined(Q_OS_LINUX) || defined (Q_OS_MAC)
+ if (qmlDebugLeakBacktrace()) {
+ SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0);
+ if (item) {
+ qt_debug_allocated_textures.remove(texture);
+ delete item;
+ }
+ }
+#else
+ Q_UNUSED(texture)
+#endif
+
+ --qt_debug_texture_count;
+
+ if (qt_debug_texture_count < 0)
+ qDebug("Material destroyed after qt_debug_print_texture_count() was called.");
+}
+
+#endif // QT_NO_DEBUG
+
+
+QSGTexture::QSGTexture()
+ : QObject(*(new QSGTexturePrivate))
+{
+#ifndef QT_NO_DEBUG
+ qt_debug_add_texture(this);
+#endif
+}
+
+QSGTexture::~QSGTexture()
+{
+#ifndef QT_NO_DEBUG
+ qt_debug_remove_texture(this);
+#endif
+}
+
+
+/*!
+ \fn void QSGTexture::bind()
+
+ Call this function to bind this texture to the current texture
+ target.
+
+ Binding a texture may also include uploading the texture data from
+ a previously set QImage.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+/*!
+ This function returns a copy of the current texture which is removed
+ from its atlas.
+
+ The current texture remains unchanged, so texture coordinates do not
+ need to be updated.
+
+ Removing a texture from an atlas is primarily useful when passing
+ it to a shader that operates on the texture coordinates 0-1 instead
+ of the texture subrect inside the atlas.
+
+ If the texture is not part of a texture atlas, this function returns 0.
+
+ Implementations of this function are recommended to return the same instance
+ for multiple calls to limit memory usage.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+QSGTexture *QSGTexture::removedFromAtlas() const
+{
+ Q_ASSERT_X(!isAtlasTexture(), "QSGTexture::removedFromAtlas()", "Called on a non-atlas texture");
+ return 0;
+}
+
+/*!
+ Returns weither this texture is part of an atlas or not.
+
+ The default implementation returns false.
+ */
+bool QSGTexture::isAtlasTexture() const
+{
+ return false;
+}
+
+/*!
+ \fn int QSGTexture::textureId() const
+
+ Returns the OpenGL texture id for this texture.
+
+ The default value is 0, indicating that it is an invalid texture id.
+
+ The function should at all times return the correct texture id.
+
+ \warning This function can only be called from the rendering thread.
+ */
+
+
+
+/*!
+ Returns the rectangle inside textureSize() that this texture
+ represents in normalized coordinates.
+
+ The default implementation returns a rect at position (0, 0) with
+ width and height of 1.
+ */
+QRectF QSGTexture::textureSubRect() const
+{
+ return QRectF(0, 0, 1, 1);
+}
+
+/*!
+ \fn bool QSGTexture::hasMipmaps() const
+
+ Returns true if the texture data contains mipmap levels.
+ */
+
+
+/*!
+ Sets the mipmap sampling mode to be used for the upcoming bind() call to \a filter.
+
+ Setting the mipmap filtering has no effect it the texture does not have mipmaps.
+
+ \sa hasMipmaps()
+ */
+void QSGTexture::setMipmapFiltering(Filtering filter)
+{
+ Q_D(QSGTexture);
+ if (d->mipmapMode != (uint) filter) {
+ d->mipmapMode = filter;
+ d->filteringChanged = true;
+ }
+}
+
+/*!
+ Returns whether mipmapping should be used when sampling from this texture.
+ */
+QSGTexture::Filtering QSGTexture::mipmapFiltering() const
+{
+ return (QSGTexture::Filtering) d_func()->mipmapMode;
+}
+
+
+/*!
+ Sets the sampling mode to be used for the upcoming bind() call to \a filter.
+ */
+void QSGTexture::setFiltering(QSGTexture::Filtering filter)
+{
+ Q_D(QSGTexture);
+ if (d->filterMode != (uint) filter) {
+ d->filterMode = filter;
+ d->filteringChanged = true;
+ }
+}
+
+QSGTexture::Filtering QSGTexture::filtering() const
+{
+ return (QSGTexture::Filtering) d_func()->filterMode;
+}
+
+
+
+/*!
+ Sets the horizontal wrap mode to be used for the upcoming bind() call to \a hwrap
+ */
+
+void QSGTexture::setHorizontalWrapMode(WrapMode hwrap)
+{
+ Q_D(QSGTexture);
+ if ((uint) hwrap != d->horizontalWrap) {
+ d->horizontalWrap = hwrap;
+ d->wrapChanged = true;
+ }
+}
+
+QSGTexture::WrapMode QSGTexture::horizontalWrapMode() const
+{
+ return (QSGTexture::WrapMode) d_func()->horizontalWrap;
+}
+
+
+
+void QSGTexture::setVerticalWrapMode(WrapMode vwrap)
+{
+ Q_D(QSGTexture);
+ if ((uint) vwrap != d->verticalWrap) {
+ d->verticalWrap = vwrap;
+ d->wrapChanged = true;
+ }
+}
+
+QSGTexture::WrapMode QSGTexture::verticalWrapMode() const
+{
+ return (QSGTexture::WrapMode) d_func()->verticalWrap;
+}
+
+
+/*!
+ Update the texture state to match the filtering, mipmap and wrap options
+ currently set.
+
+ If \a force is true, all properties will be updated regardless of weither
+ they have changed or not.
+ */
+void QSGTexture::updateBindOptions(bool force)
+{
+ Q_D(QSGTexture);
+ if (force || d->filteringChanged) {
+ bool linear = d->filterMode == Linear;
+ GLint minFilter = linear ? GL_LINEAR : GL_NEAREST;
+ GLint magFilter = linear ? GL_LINEAR : GL_NEAREST;
+
+ if (hasMipmaps()) {
+ if (d->mipmapMode == Nearest)
+ minFilter = linear ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST;
+ else if (d->mipmapMode == Linear)
+ minFilter = linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_LINEAR;
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
+ d->filteringChanged = false;
+ }
+
+ if (force || d->wrapChanged) {
+#if !defined(QT_NO_DEBUG) && defined(QT_OPENGL_ES_2)
+ if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat) {
+ bool npotSupported = QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+ QSize size = textureSize();
+ bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
+ if (!npotSupported && isNpot)
+ qWarning("Scene Graph: This system does not support the REPEAT wrap mode for non-power-of-two textures.");
+ }
+#endif
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, d->horizontalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, d->verticalWrap == Repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
+ d->wrapChanged = false;
+ }
+}
+
+QSGPlainTexture::QSGPlainTexture()
+ : QSGTexture()
+ , m_texture_id(0)
+ , m_has_alpha(false)
+ , m_has_mipmaps(false)
+ , m_dirty_bind_options(false)
+ , m_owns_texture(true)
+ , m_mipmaps_generated(false)
+{
+}
+
+
+QSGPlainTexture::~QSGPlainTexture()
+{
+ if (m_texture_id && m_owns_texture)
+ glDeleteTextures(1, &m_texture_id);
+}
+
+#ifdef QT_OPENGL_ES
+static void swizzleBGRAToRGBA(QImage *image)
+{
+ const int width = image->width();
+ const int height = image->height();
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) image->scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
+ }
+}
+#endif
+
+void QSGPlainTexture::setImage(const QImage &image)
+{
+ m_image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+#ifdef QT_OPENGL_ES
+ swizzleBGRAToRGBA(&m_image);
+#endif
+
+ m_texture_size = image.size();
+ m_has_alpha = image.hasAlphaChannel();
+ m_dirty_texture = true;
+ m_dirty_bind_options = true;
+ }
+
+int QSGPlainTexture::textureId() const
+{
+ if (m_dirty_texture) {
+ if (m_image.isNull()) {
+ // The actual texture and id will be updated/deleted in a later bind()
+ // or ~QSGPlainTexture so just keep it minimal here.
+ return 0;
+ } else {
+ // Generate a texture id for use later and return it.
+ glGenTextures(1, &const_cast<QSGPlainTexture *>(this)->m_texture_id);
+ return m_texture_id;
+ }
+ }
+ return m_texture_id;
+}
+
+void QSGPlainTexture::setTextureId(int id)
+{
+ if (m_texture_id && m_owns_texture)
+ glDeleteTextures(1, &m_texture_id);
+
+ m_texture_id = id;
+ m_dirty_texture = false;
+ m_dirty_bind_options = true;
+ m_image = QImage();
+ m_mipmaps_generated = false;
+}
+
+void QSGPlainTexture::setHasMipmaps(bool mm)
+{
+ m_has_mipmaps = mm;
+ m_mipmaps_generated = false;
+}
+
+
+void QSGPlainTexture::bind()
+{
+ if (!m_dirty_texture) {
+ glBindTexture(GL_TEXTURE_2D, m_texture_id);
+ if (m_has_mipmaps && !m_mipmaps_generated) {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ m_mipmaps_generated = true;
+ }
+ updateBindOptions(m_dirty_bind_options);
+ m_dirty_bind_options = false;
+ return;
+ }
+
+ m_dirty_texture = false;
+
+
+ if (m_image.isNull()) {
+ if (m_texture_id && m_owns_texture)
+ glDeleteTextures(1, &m_texture_id);
+ m_texture_id = 0;
+ m_texture_size = QSize();
+ m_has_mipmaps = false;
+ m_has_alpha = false;
+ return;
+ }
+
+ if (m_texture_id == 0)
+ glGenTextures(1, &m_texture_id);
+ glBindTexture(GL_TEXTURE_2D, m_texture_id);
+
+ // ### TODO: check for out-of-memory situations...
+ int w = m_image.width();
+ int h = m_image.height();
+
+#ifdef QT_OPENGL_ES
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_image.constBits());
+#else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, m_image.constBits());
+#endif
+
+ if (m_has_mipmaps) {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ m_mipmaps_generated = true;
+ }
+
+ m_texture_size = QSize(w, h);
+ m_texture_rect = QRectF(0, 0, 1, 1);
+
+ updateBindOptions(m_dirty_bind_options);
+ m_dirty_bind_options = false;
+}
+
+
+/*!
+ \class QSGDynamicTexture
+ \brief The QSGDynamicTexture class serves as a baseclass for dynamically changing textures,
+ such as content that is rendered to FBO's.
+
+ To update the content of the texture, call updateTexture() explicitly. Simply calling bind()
+ will not update the texture.
+ */
+
+
+/*!
+ \fn bool QSGDynamicTexture::updateTexture()
+
+ Call this function to explicitely update the dynamic texture. Calling bind() will bind
+ the content that was previously updated.
+
+ The function returns true if the texture was changed as a resul of the update; otherwise
+ returns false.
+ */
+
+
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgtexture.h b/src/quick/scenegraph/util/qsgtexture.h
new file mode 100644
index 0000000000..6fdab9f401
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexture.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGTEXTURE_H
+#define QSGTEXTURE_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <QObject>
+#include <QImage>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGTexturePrivate;
+class Q_QUICK_EXPORT QSGTexture : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGTexture)
+
+public:
+ QSGTexture();
+ ~QSGTexture();
+
+ enum WrapMode {
+ Repeat,
+ ClampToEdge
+ };
+
+ enum Filtering {
+ None,
+ Nearest,
+ Linear
+ };
+
+ virtual int textureId() const = 0;
+ virtual QSize textureSize() const = 0;
+ virtual bool hasAlphaChannel() const = 0;
+ virtual bool hasMipmaps() const = 0;
+
+ virtual QRectF textureSubRect() const;
+
+ virtual bool isAtlasTexture() const;
+
+ virtual QSGTexture *removedFromAtlas() const;
+
+ virtual void bind() = 0;
+ void updateBindOptions(bool force = false);
+
+ void setMipmapFiltering(Filtering filter);
+ QSGTexture::Filtering mipmapFiltering() const;
+
+ void setFiltering(Filtering filter);
+ QSGTexture::Filtering filtering() const;
+
+ void setHorizontalWrapMode(WrapMode hwrap);
+ QSGTexture::WrapMode horizontalWrapMode() const;
+
+ void setVerticalWrapMode(WrapMode vwrap);
+ QSGTexture::WrapMode verticalWrapMode() const;
+
+ inline QRectF convertToNormalizedSourceRect(const QRectF &rect) const;
+
+protected:
+ QSGTexture(QSGTexturePrivate &dd);
+};
+
+QRectF QSGTexture::convertToNormalizedSourceRect(const QRectF &rect) const
+{
+ QSize s = textureSize();
+ QRectF r = textureSubRect();
+
+ qreal sx = r.width() / s.width();
+ qreal sy = r.height() / s.height();
+
+ return QRectF(r.x() + rect.x() * sx,
+ r.y() + rect.y() * sy,
+ rect.width() * sx,
+ rect.height() * sy);
+}
+
+
+class Q_QUICK_EXPORT QSGDynamicTexture : public QSGTexture
+{
+ Q_OBJECT
+public:
+ virtual bool updateTexture() = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h
new file mode 100644
index 0000000000..e1d6dd0e32
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexture_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGTEXTURE_P_H
+#define QSGTEXTURE_P_H
+
+#include <QtQuick/qtquickglobal.h>
+#include <private/qobject_p.h>
+
+#include <QtGui/qopengl.h>
+
+#include "qsgtexture.h"
+#include <QtQuick/private/qsgcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGTexturePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSGTexture);
+public:
+ QSGTexturePrivate();
+
+ uint wrapChanged : 1;
+ uint filteringChanged : 1;
+
+ uint horizontalWrap : 1;
+ uint verticalWrap : 1;
+ uint mipmapMode : 2;
+ uint filterMode : 2;
+};
+
+class Q_QUICK_EXPORT QSGPlainTexture : public QSGTexture
+{
+ Q_OBJECT
+public:
+ QSGPlainTexture();
+ virtual ~QSGPlainTexture();
+
+ void setOwnsTexture(bool owns) { m_owns_texture = owns; }
+ bool ownsTexture() const { return m_owns_texture; }
+
+ void setTextureId(int id);
+ int textureId() const;
+ void setTextureSize(const QSize &size) { m_texture_size = size; }
+ QSize textureSize() const { return m_texture_size; }
+
+ void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; }
+ bool hasAlphaChannel() const { return m_has_alpha; }
+
+ void setHasMipmaps(bool mm);
+ bool hasMipmaps() const { return m_has_mipmaps; }
+
+ void setImage(const QImage &image);
+ const QImage &image() { return m_image; }
+
+ virtual void bind();
+
+ static QSGPlainTexture *fromImage(const QImage &image) {
+ QSGPlainTexture *t = new QSGPlainTexture();
+ t->setImage(image);
+ return t;
+ }
+
+protected:
+ QImage m_image;
+
+ GLuint m_texture_id;
+ QSize m_texture_size;
+ QRectF m_texture_rect;
+
+ uint m_has_alpha : 1;
+ uint m_has_mipmaps : 1;
+ uint m_dirty_texture : 1;
+ uint m_dirty_bind_options : 1;
+ uint m_owns_texture : 1;
+ uint m_mipmaps_generated : 1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGTEXTURE_P_H
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp
new file mode 100644
index 0000000000..0bee81993c
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgtexturematerial_p.h"
+
+#include <QtGui/qopenglshaderprogram.h>
+#include <QtGui/qopenglfunctions.h>
+
+QT_BEGIN_NAMESPACE
+
+inline static bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+
+const char qt_scenegraph_texture_material_vertex_code[] =
+ "uniform highp mat4 qt_Matrix; \n"
+ "attribute highp vec4 qt_VertexPosition; \n"
+ "attribute highp vec2 qt_VertexTexCoord; \n"
+ "varying highp vec2 qt_TexCoord; \n"
+ "void main() { \n"
+ " qt_TexCoord = qt_VertexTexCoord; \n"
+ " gl_Position = qt_Matrix * qt_VertexPosition; \n"
+ "}";
+
+const char qt_scenegraph_texture_material_fragment[] =
+ "varying highp vec2 qt_TexCoord; \n"
+ "uniform sampler2D qt_Texture; \n"
+ "void main() { \n"
+ " gl_FragColor = texture2D(qt_Texture, qt_TexCoord);\n"
+ "}";
+
+
+const char *QSGOpaqueTextureMaterialShader::vertexShader() const
+{
+ return qt_scenegraph_texture_material_vertex_code;
+}
+
+const char *QSGOpaqueTextureMaterialShader::fragmentShader() const
+{
+ return qt_scenegraph_texture_material_fragment;
+}
+
+QSGMaterialType QSGOpaqueTextureMaterialShader::type;
+
+char const *const *QSGOpaqueTextureMaterialShader::attributeNames() const
+{
+ static char const *const attr[] = { "qt_VertexPosition", "qt_VertexTexCoord", 0 };
+ return attr;
+}
+
+void QSGOpaqueTextureMaterialShader::initialize()
+{
+ m_matrix_id = program()->uniformLocation("qt_Matrix");
+}
+
+void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+ QSGOpaqueTextureMaterial *tx = static_cast<QSGOpaqueTextureMaterial *>(newEffect);
+ QSGOpaqueTextureMaterial *oldTx = static_cast<QSGOpaqueTextureMaterial *>(oldEffect);
+
+ QSGTexture *t = tx->texture();
+
+ t->setFiltering(tx->filtering());
+#ifdef QT_OPENGL_ES_2
+ bool npotSupported = QOpenGLFunctions(const_cast<QOpenGLContext *>(state.context())).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+ QSize size = t->textureSize();
+ bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
+ if (!npotSupported && isNpot) {
+ t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ t->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ } else
+#endif
+ {
+ t->setHorizontalWrapMode(tx->horizontalWrapMode());
+ t->setVerticalWrapMode(tx->verticalWrapMode());
+ }
+ t->setMipmapFiltering(tx->mipmapFiltering());
+
+ if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId())
+ t->bind();
+ else
+ t->updateBindOptions();
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+}
+
+
+/*!
+ \class QSGOpaqueTextureMaterial
+ \brief The QSGOpaqueTextureMaterial class provides a convenient way of
+ rendering textured geometry in the scene graph.
+
+ The opaque textured material will fill every pixel in a geometry with
+ the supplied texture. The material does not respect the opacity of the
+ QSGMaterialShader::RenderState, so opacity nodes in the parent chain
+ of nodes using this material, have no effect.
+
+ The geometry to be rendered with an opaque texture material requires
+ vertices in attribute location 0 and texture coordinates in attribute
+ location 1. The texture coordinate is a 2-dimensional floating-point
+ tuple. The QSGGeometry::defaultAttributes_TexturedPoint2D returns an
+ attribute set compatible with this material.
+
+ The texture to be rendered is can be set using setTexture(). How the
+ texure should be rendered can be specified using setMipmapFiltering(),
+ setFiltering(), setHorizontalWrapMode() and setVerticalWrapMode().
+ The rendering state is set on the texture instance just before it
+ is bound.
+
+ The opaque textured material respects the current matrix and the alpha
+ channel of the texture. It will disregard the accumulated opacity in
+ the scenegraph.
+
+ A texture material must have a texture set before it is used as
+ a material in the scene graph.
+ */
+
+
+
+/*!
+ Creates a new QSGOpaqueTextureMaterial.
+
+ The default mipmap filtering and filtering mode is set to
+ QSGTexture::Nearest. The default wrap modes is set to
+ QSGTexture::ClampToEdge.
+
+ */
+QSGOpaqueTextureMaterial::QSGOpaqueTextureMaterial()
+ : m_texture(0)
+ , m_filtering(QSGTexture::Nearest)
+ , m_mipmap_filtering(QSGTexture::Nearest)
+ , m_horizontal_wrap(QSGTexture::ClampToEdge)
+ , m_vertical_wrap(QSGTexture::ClampToEdge)
+{
+}
+
+
+/*!
+ \internal
+ */
+QSGMaterialType *QSGOpaqueTextureMaterial::type() const
+{
+ return &QSGOpaqueTextureMaterialShader::type;
+}
+
+/*!
+ \internal
+ */
+QSGMaterialShader *QSGOpaqueTextureMaterial::createShader() const
+{
+ return new QSGOpaqueTextureMaterialShader;
+}
+
+
+
+/*!
+ \fn QSGTexture *QSGOpaqueTextureMaterial::texture() const
+
+ Returns this texture material's texture.
+ */
+
+
+
+/*!
+ Sets the texture of this material to \a texture.
+
+ The material does not take ownership over the texture.
+ */
+
+void QSGOpaqueTextureMaterial::setTexture(QSGTexture *texture)
+{
+ m_texture = texture;
+ setFlag(Blending, m_texture ? m_texture->hasAlphaChannel() : false);
+}
+
+
+
+/*!
+ \fn void QSGOpaqueTextureMaterial::setMipmapFiltering(QSGTexture::Filtering filtering)
+
+ Sets the mipmap mode to \a filtering.
+
+ The mipmap filtering mode is set on the texture instance just before the
+ texture is bound for rendering.
+
+ If the texture does not have mipmapping support, enabling mipmapping has no
+ effect.
+ */
+
+
+
+/*!
+ \fn QSGTexture::Filtering QSGOpaqueTextureMaterial::mipmapFiltering() const
+
+ Returns this material's mipmap filtering mode.
+
+ The default mipmap mode is QSGTexture::Nearest.
+ */
+
+
+
+/*!
+ \fn void QSGOpaqueTextureMaterial::setFiltering(QSGTexture::Filtering filtering)
+
+ Sets the filtering to \a filtering.
+
+ The filtering mode is set on the texture instance just before the texture
+ is bound for rendering.
+ */
+
+
+
+/*!
+ \fn QSGTexture::Filtering filtering() const
+
+ Returns this material's filtering mode.
+
+ The default filtering is QSGTexture::Nearest.
+ */
+
+
+
+/*!
+ \fn void setHorizontalWrapMode(QSGTexture::WrapMode mode)
+
+ Sets the horizontal wrap mode to \a mode.
+
+ The horizontal wrap mode is set on the texture instance just before the texture
+ is bound for rendering.
+ */
+
+
+
+ /*!
+ \fn QSGTexture::WrapMode horizontalWrapMode() const
+
+ Returns this material's horizontal wrap mode.
+
+ The default horizontal wrap mode is QSGTexutre::ClampToEdge
+ */
+
+
+
+/*!
+ \fn void setVerticalWrapMode(QSGTexture::WrapMode mode)
+
+ Sets the vertical wrap mode to \a mode.
+
+ The vertical wrap mode is set on the texture instance just before the texture
+ is bound for rendering.
+ */
+
+
+
+ /*!
+ \fn QSGTexture::WrapMode verticalWrapMode() const
+
+ Returns this material's vertical wrap mode.
+
+ The default vertical wrap mode is QSGTexutre::ClampToEdge
+ */
+
+
+
+/*!
+ \internal
+ */
+
+int QSGOpaqueTextureMaterial::compare(const QSGMaterial *o) const
+{
+ Q_ASSERT(o && type() == o->type());
+ const QSGOpaqueTextureMaterial *other = static_cast<const QSGOpaqueTextureMaterial *>(o);
+ if (int diff = m_texture->textureId() - other->texture()->textureId())
+ return diff;
+ return int(m_filtering) - int(other->m_filtering);
+}
+
+
+
+/*!
+ \class QSGTextureMaterial
+ \brief The QSGTextureMaterial class provides a convenient way of
+ rendering textured geometry in the scene graph.
+
+ The textured material will fill every pixel in a geometry with
+ the supplied texture.
+
+ The geometry to be rendered with a texture material requires
+ vertices in attribute location 0 and texture coordinates in attribute
+ location 1. The texture coordinate is a 2-dimensional floating-point
+ tuple. The QSGGeometry::defaultAttributes_TexturedPoint2D returns an
+ attribute set compatible with this material.
+
+ The texture to be rendered is set using setTexture(). How the
+ texure should be rendered can be specified using setMipmapFiltering(),
+ setFiltering(), setHorizontalWrapMode() and setVerticalWrapMode().
+ The rendering state is set on the texture instance just before it
+ is bound.
+
+ The textured material respects the current matrix and the alpha
+ channel of the texture. It will also respect the accumulated opacity
+ in the scenegraph.
+
+ A texture material must have a texture set before it is used as
+ a material in the scene graph.
+ */
+
+static const char qt_scenegraph_texture_material_opacity_fragment[] =
+ "varying highp vec2 qt_TexCoord; \n"
+ "uniform sampler2D qt_Texture; \n"
+ "uniform lowp float opacity; \n"
+ "void main() { \n"
+ " gl_FragColor = texture2D(qt_Texture, qt_TexCoord) * opacity; \n"
+ "}";
+
+class QSGTextureMaterialShader : public QSGOpaqueTextureMaterialShader
+{
+public:
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual void initialize();
+
+ static QSGMaterialType type;
+
+protected:
+ virtual const char *fragmentShader() const { return qt_scenegraph_texture_material_opacity_fragment; }
+
+ int m_opacity_id;
+};
+QSGMaterialType QSGTextureMaterialShader::type;
+
+
+
+/*!
+ \internal
+ */
+
+QSGMaterialType *QSGTextureMaterial::type() const
+{
+ return &QSGTextureMaterialShader::type;
+}
+
+
+
+/*!
+ \internal
+ */
+
+QSGMaterialShader *QSGTextureMaterial::createShader() const
+{
+ return new QSGTextureMaterialShader;
+}
+
+void QSGTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+ if (state.isOpacityDirty())
+ program()->setUniformValue(m_opacity_id, state.opacity());
+
+ QSGOpaqueTextureMaterialShader::updateState(state, newEffect, oldEffect);
+}
+
+void QSGTextureMaterialShader::initialize()
+{
+ QSGOpaqueTextureMaterialShader::initialize();
+ m_opacity_id = program()->uniformLocation("opacity");
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.h b/src/quick/scenegraph/util/qsgtexturematerial.h
new file mode 100644
index 0000000000..b2b3ce6374
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexturematerial.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTUREMATERIAL_H
+#define TEXTUREMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+#include <QtQuick/qsgtexture.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGOpaqueTextureMaterial : public QSGMaterial
+{
+public:
+ QSGOpaqueTextureMaterial();
+
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+ virtual int compare(const QSGMaterial *other) const;
+
+ void setTexture(QSGTexture *texture);
+ QSGTexture *texture() const { return m_texture; }
+
+ void setMipmapFiltering(QSGTexture::Filtering filtering) { m_mipmap_filtering = filtering; }
+ QSGTexture::Filtering mipmapFiltering() const { return (QSGTexture::Filtering) m_mipmap_filtering; }
+
+ void setFiltering(QSGTexture::Filtering filtering) { m_filtering = filtering; }
+ QSGTexture::Filtering filtering() const { return (QSGTexture::Filtering) m_filtering; }
+
+ void setHorizontalWrapMode(QSGTexture::WrapMode mode) { m_horizontal_wrap = mode; }
+ QSGTexture::WrapMode horizontalWrapMode() const { return (QSGTexture::WrapMode) m_horizontal_wrap; }
+
+ void setVerticalWrapMode(QSGTexture::WrapMode mode) { m_vertical_wrap = mode; }
+ QSGTexture::WrapMode verticalWrapMode() const { return (QSGTexture::WrapMode) m_vertical_wrap; }
+
+protected:
+ QSGTexture *m_texture;
+
+ uint m_filtering: 2;
+ uint m_mipmap_filtering: 2;
+ uint m_horizontal_wrap : 1;
+ uint m_vertical_wrap: 1;
+
+ uint m_reserved : 26;
+};
+
+
+class Q_QUICK_EXPORT QSGTextureMaterial : public QSGOpaqueTextureMaterial
+{
+public:
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // TEXTUREMATERIAL_H
diff --git a/src/quick/scenegraph/util/qsgtexturematerial_p.h b/src/quick/scenegraph/util/qsgtexturematerial_p.h
new file mode 100644
index 0000000000..0ab552f4e9
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtexturematerial_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTUREMATERIAL_P_H
+#define TEXTUREMATERIAL_P_H
+
+#include "qsgtexturematerial.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGOpaqueTextureMaterialShader : public QSGMaterialShader
+{
+public:
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+
+ static QSGMaterialType type;
+
+protected:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ int m_matrix_id;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGTEXTUREMATERIAL_P_H
diff --git a/src/quick/scenegraph/util/qsgtextureprovider.cpp b/src/quick/scenegraph/util/qsgtextureprovider.cpp
new file mode 100644
index 0000000000..10faf2e5d4
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtextureprovider.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgtextureprovider_p.h"
+
+#ifndef GL_CLAMP_TO_EDGE
+#define GL_CLAMP_TO_EDGE 0x812F
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSGTextureProvider
+ \brief The QSGTextureProvider class encapsulates texture based entities in QML.
+
+ The QSGTextureProvider lives primarily in the scene graph rendering thread.
+ */
+
+
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgtextureprovider_p.h b/src/quick/scenegraph/util/qsgtextureprovider_p.h
new file mode 100644
index 0000000000..bc4ffec03d
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgtextureprovider_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGTEXTUREPROVIDER_H
+#define QSGTEXTUREPROVIDER_H
+
+#include "qsgtexture.h"
+#include "qobject.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGTextureProvider : public QObject
+{
+ Q_OBJECT
+public:
+ virtual QSGTexture *texture() const = 0;
+
+Q_SIGNALS:
+ void textureChanged();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
new file mode 100644
index 0000000000..8c6996642b
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgvertexcolormaterial.h"
+
+#include <qopenglshaderprogram.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGVertexColorMaterialShader : public QSGMaterialShader
+{
+public:
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual char const *const *attributeNames() const;
+
+ static QSGMaterialType type;
+
+private:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ int m_matrix_id;
+ int m_opacity_id;
+};
+
+QSGMaterialType QSGVertexColorMaterialShader::type;
+
+void QSGVertexColorMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+{
+ if (!(newEffect->flags() & QSGMaterial::Blending) || state.isOpacityDirty())
+ program()->setUniformValue(m_opacity_id, state.opacity());
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+}
+
+char const *const *QSGVertexColorMaterialShader::attributeNames() const
+{
+ static const char *const attr[] = { "vertexCoord", "vertexColor", 0 };
+ return attr;
+}
+
+void QSGVertexColorMaterialShader::initialize()
+{
+ m_matrix_id = program()->uniformLocation("matrix");
+ m_opacity_id = program()->uniformLocation("opacity");
+}
+
+const char *QSGVertexColorMaterialShader::vertexShader() const {
+ return
+ "attribute highp vec4 vertexCoord; \n"
+ "attribute highp vec4 vertexColor; \n"
+ "uniform highp mat4 matrix; \n"
+ "uniform highp float opacity; \n"
+ "varying lowp vec4 color; \n"
+ "void main() { \n"
+ " gl_Position = matrix * vertexCoord; \n"
+ " color = vertexColor * opacity; \n"
+ "}";
+}
+
+const char *QSGVertexColorMaterialShader::fragmentShader() const {
+ return
+ "varying lowp vec4 color; \n"
+ "void main() { \n"
+ " gl_FragColor = color; \n"
+ "}";
+}
+
+
+
+/*!
+ \class QSGVertexColorMaterial
+ \brief The QSGVertexColorMaterial class provides a convenient way of rendering per-vertex
+ colored geometry in the scene graph.
+
+ \inmodule QtQuick
+
+ The vertex color material will give each vertex in a geometry a color. Pixels between
+ vertices will be linearly interpolated. The colors can contain transparency.
+
+ The geometry to be rendered with vertex color must have the following layout. Attribute
+ position 0 must contain vertices. Attribute position 1 must contain colors, a tuple of
+ 4 values with RGBA layout. Both floats in the range of 0 to 1 and unsigned bytes in
+ the range 0 to 255 are valid for the color values. The
+ QSGGeometry::defaultAttributes_ColoredPoint2D() constructs an attribute set
+ compatible with this material.
+
+ The vertex color material respects both current opacity and current matrix when
+ updating it's rendering state.
+ */
+
+
+QSGVertexColorMaterial::QSGVertexColorMaterial()
+{
+ setFlag(Blending, true);
+}
+
+
+/*!
+ int QSGVertexColorMaterial::compare() const
+
+ As the vertex color material has all its state in the vertex attributes,
+ all materials will be equal.
+
+ \internal
+ */
+
+int QSGVertexColorMaterial::compare(const QSGMaterial * /* other */) const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ */
+
+QSGMaterialType *QSGVertexColorMaterial::type() const
+{
+ return &QSGVertexColorMaterialShader::type;
+}
+
+
+
+/*!
+ \internal
+ */
+
+QSGMaterialShader *QSGVertexColorMaterial::createShader() const
+{
+ return new QSGVertexColorMaterialShader;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.h b/src/quick/scenegraph/util/qsgvertexcolormaterial.h
new file mode 100644
index 0000000000..1d3b5a82e0
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VERTEXCOLORMATERIAL_H
+#define VERTEXCOLORMATERIAL_H
+
+#include <QtQuick/qsgmaterial.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_EXPORT QSGVertexColorMaterial : public QSGMaterial
+{
+public:
+ QSGVertexColorMaterial();
+
+ int compare(const QSGMaterial *other) const;
+
+protected:
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // VERTEXCOLORMATERIAL_H