Update to 5.0.0-beta1
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickshadereffectmesh.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickshadereffectmesh_p.h"
43 #include <QtQuick/qsggeometry.h>
44 #include "qquickshadereffect_p.h"
45
46 QT_BEGIN_NAMESPACE
47
48 QQuickShaderEffectMesh::QQuickShaderEffectMesh(QObject *parent)
49     : QObject(parent)
50 {
51 }
52
53 /*!
54     \qmltype GridMesh
55     \instantiates QQuickGridMesh
56     \inqmlmodule QtQuick 2
57     \since QtQuick 2.0
58     \ingroup qtquick-effects
59     \brief Defines a mesh with vertices arranged in a grid
60
61     GridMesh defines a rectangular mesh consisting of vertices arranged in an
62     evenly spaced grid. It is used to generate \l{QSGGeometry}{geometry}.
63     The grid resolution is specified with the \l resolution property.
64 */
65
66 QQuickGridMesh::QQuickGridMesh(QObject *parent)
67     : QQuickShaderEffectMesh(parent)
68     , m_resolution(1, 1)
69 {
70     connect(this, SIGNAL(resolutionChanged()), this, SIGNAL(geometryChanged()));
71 }
72
73 QSGGeometry *QQuickGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &dstRect)
74 {
75     int vmesh = m_resolution.height();
76     int hmesh = m_resolution.width();
77     int attrCount = attributes.count();
78
79     int positionIndex = attributes.indexOf(qtPositionAttributeName());
80     int texCoordIndex = attributes.indexOf(qtTexCoordAttributeName());
81
82     if (!geometry) {
83         switch (attrCount) {
84         case 0:
85             m_log = QLatin1String("Error: No attributes specified.");
86             return 0;
87         case 1:
88             if (positionIndex != 0) {
89                 m_log = QLatin1String("Error: Missing \'");
90                 m_log += QLatin1String(qtPositionAttributeName());
91                 m_log += QLatin1String("\' attribute.\n");
92                 return 0;
93             }
94             break;
95         case 2:
96             if (positionIndex == -1 || texCoordIndex == -1) {
97                 m_log.clear();
98                 if (positionIndex == -1) {
99                     m_log = QLatin1String("Error: Missing \'");
100                     m_log += QLatin1String(qtPositionAttributeName());
101                     m_log += QLatin1String("\' attribute.\n");
102                 }
103                 if (texCoordIndex == -1) {
104                     m_log += QLatin1String("Error: Missing \'");
105                     m_log += QLatin1String(qtTexCoordAttributeName());
106                     m_log += QLatin1String("\' attribute.\n");
107                 }
108                 return 0;
109             }
110             break;
111         default:
112             m_log = QLatin1String("Error: Too many attributes specified.");
113             return 0;
114         }
115
116         geometry = new QSGGeometry(attrCount == 1
117                                    ? QSGGeometry::defaultAttributes_Point2D()
118                                    : QSGGeometry::defaultAttributes_TexturedPoint2D(),
119                                    (vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2),
120                                    GL_UNSIGNED_SHORT);
121
122     } else {
123         geometry->allocate((vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2));
124     }
125
126     QSGGeometry::Point2D *vdata = static_cast<QSGGeometry::Point2D *>(geometry->vertexData());
127
128     QRectF srcRect(0, 0, 1, 1);
129     for (int iy = 0; iy <= vmesh; ++iy) {
130         float fy = iy / float(vmesh);
131         float y = float(dstRect.top()) + fy * float(dstRect.height());
132         float ty = float(srcRect.top()) + fy * float(srcRect.height());
133         for (int ix = 0; ix <= hmesh; ++ix) {
134             float fx = ix / float(hmesh);
135             for (int ia = 0; ia < attrCount; ++ia) {
136                 if (ia == positionIndex) {
137                     vdata->x = float(dstRect.left()) + fx * float(dstRect.width());
138                     vdata->y = y;
139                     ++vdata;
140                 } else {
141                     vdata->x = float(srcRect.left()) + fx * float(srcRect.width());
142                     vdata->y = ty;
143                     ++vdata;
144                 }
145             }
146         }
147     }
148
149     quint16 *indices = (quint16 *)geometry->indexDataAsUShort();
150     int i = 0;
151     for (int iy = 0; iy < vmesh; ++iy) {
152         *(indices++) = i + hmesh + 1;
153         for (int ix = 0; ix <= hmesh; ++ix, ++i) {
154             *(indices++) = i + hmesh + 1;
155             *(indices++) = i;
156         }
157         *(indices++) = i - 1;
158     }
159
160     return geometry;
161 }
162
163 /*!
164     \qmlproperty size QtQuick2::GridMesh::resolution
165
166     This property holds the grid resolution. The resolution's width and height
167     specify the number of cells or spacings between vertices horizontally and
168     vertically respectively. The minimum and default is 1x1, which corresponds
169     to four vertices in total, one in each corner.
170     For non-linear vertex transformations, you probably want to set the
171     resolution higher.
172
173     \table
174     \row
175     \li \image declarative-gridmesh.png
176     \li \qml
177         import QtQuick 2.0
178
179         ShaderEffect {
180             width: 200
181             height: 200
182             mesh: GridMesh {
183                 resolution: Qt.size(20, 20)
184             }
185             property variant source: Image {
186                 source: "qt-logo.png"
187                 sourceSize { width: 200; height: 200 }
188             }
189             vertexShader: "
190                 uniform highp mat4 qt_Matrix;
191                 attribute highp vec4 qt_Vertex;
192                 attribute highp vec2 qt_MultiTexCoord0;
193                 varying highp vec2 qt_TexCoord0;
194                 uniform highp float width;
195                 void main() {
196                     highp vec4 pos = qt_Vertex;
197                     highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
198                     pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
199                     gl_Position = qt_Matrix * pos;
200                     qt_TexCoord0 = qt_MultiTexCoord0;
201                 }"
202         }
203         \endqml
204     \endtable
205 */
206
207 void QQuickGridMesh::setResolution(const QSize &res)
208 {
209     if (res == m_resolution)
210         return;
211     if (res.width() < 1 || res.height() < 1) {
212         return;
213     }
214     m_resolution = res;
215     emit resolutionChanged();
216 }
217
218 QSize QQuickGridMesh::resolution() const
219 {
220     return m_resolution;
221 }
222
223 QT_END_NAMESPACE