52a3a0c37576673053fc64ae652c337bd1d15953
[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     \qmlclass GridMesh QQuickGridMesh
55     \inqmlmodule QtQuick 2
56     \ingroup qtquick-effects
57     \brief Defines a mesh with vertices arranged in a grid
58
59     GridMesh defines a rectangular mesh consisting of vertices arranged in an
60     evenly spaced grid. It is used to generate \l{QSGGeometry}{geometry}.
61     The grid resolution is specified with the \l resolution property.
62 */
63
64 QQuickGridMesh::QQuickGridMesh(QObject *parent)
65     : QQuickShaderEffectMesh(parent)
66     , m_resolution(1, 1)
67 {
68     connect(this, SIGNAL(resolutionChanged()), this, SIGNAL(geometryChanged()));
69 }
70
71 QSGGeometry *QQuickGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &dstRect)
72 {
73     int vmesh = m_resolution.height();
74     int hmesh = m_resolution.width();
75     int attrCount = attributes.count();
76
77     int positionIndex = attributes.indexOf(qtPositionAttributeName());
78     int texCoordIndex = attributes.indexOf(qtTexCoordAttributeName());
79
80     if (!geometry) {
81         switch (attrCount) {
82         case 0:
83             m_log = QLatin1String("Error: No attributes specified.");
84             return 0;
85         case 1:
86             if (positionIndex != 0) {
87                 m_log = QLatin1String("Error: Missing \'");
88                 m_log += QLatin1String(qtPositionAttributeName());
89                 m_log += QLatin1String("\' attribute.\n");
90                 return 0;
91             }
92             break;
93         case 2:
94             if (positionIndex == -1 || texCoordIndex == -1) {
95                 m_log.clear();
96                 if (positionIndex == -1) {
97                     m_log = QLatin1String("Error: Missing \'");
98                     m_log += QLatin1String(qtPositionAttributeName());
99                     m_log += QLatin1String("\' attribute.\n");
100                 }
101                 if (texCoordIndex == -1) {
102                     m_log += QLatin1String("Error: Missing \'");
103                     m_log += QLatin1String(qtTexCoordAttributeName());
104                     m_log += QLatin1String("\' attribute.\n");
105                 }
106                 return 0;
107             }
108             break;
109         default:
110             m_log = QLatin1String("Error: Too many attributes specified.");
111             return 0;
112         }
113
114         geometry = new QSGGeometry(attrCount == 1
115                                    ? QSGGeometry::defaultAttributes_Point2D()
116                                    : QSGGeometry::defaultAttributes_TexturedPoint2D(),
117                                    (vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2),
118                                    GL_UNSIGNED_SHORT);
119
120     } else {
121         geometry->allocate((vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2));
122     }
123
124     QSGGeometry::Point2D *vdata = static_cast<QSGGeometry::Point2D *>(geometry->vertexData());
125
126     QRectF srcRect(0, 0, 1, 1);
127     for (int iy = 0; iy <= vmesh; ++iy) {
128         float fy = iy / float(vmesh);
129         float y = float(dstRect.top()) + fy * float(dstRect.height());
130         float ty = float(srcRect.top()) + fy * float(srcRect.height());
131         for (int ix = 0; ix <= hmesh; ++ix) {
132             float fx = ix / float(hmesh);
133             for (int ia = 0; ia < attrCount; ++ia) {
134                 if (ia == positionIndex) {
135                     vdata->x = float(dstRect.left()) + fx * float(dstRect.width());
136                     vdata->y = y;
137                     ++vdata;
138                 } else {
139                     vdata->x = float(srcRect.left()) + fx * float(srcRect.width());
140                     vdata->y = ty;
141                     ++vdata;
142                 }
143             }
144         }
145     }
146
147     quint16 *indices = (quint16 *)geometry->indexDataAsUShort();
148     int i = 0;
149     for (int iy = 0; iy < vmesh; ++iy) {
150         *(indices++) = i + hmesh + 1;
151         for (int ix = 0; ix <= hmesh; ++ix, ++i) {
152             *(indices++) = i + hmesh + 1;
153             *(indices++) = i;
154         }
155         *(indices++) = i - 1;
156     }
157
158     return geometry;
159 }
160
161 /*!
162     \qmlproperty size QtQuick2::GridMesh::resolution
163
164     This property holds the grid resolution. The resolution's width and height
165     specify the number of cells or spacings between vertices horizontally and
166     vertically respectively. The minimum and default is 1x1, which corresponds
167     to four vertices in total, one in each corner.
168     For non-linear vertex transformations, you probably want to set the
169     resolution higher.
170
171     \table
172     \row
173     \li \image declarative-gridmesh.png
174     \li \qml
175         import QtQuick 2.0
176
177         ShaderEffect {
178             width: 200
179             height: 200
180             mesh: GridMesh {
181                 resolution: Qt.size(20, 20)
182             }
183             property variant source: Image {
184                 source: "qt-logo.png"
185                 sourceSize { width: 200; height: 200 }
186                 smooth: true
187             }
188             vertexShader: "
189                 uniform highp mat4 qt_Matrix;
190                 attribute highp vec4 qt_Vertex;
191                 attribute highp vec2 qt_MultiTexCoord0;
192                 varying highp vec2 qt_TexCoord0;
193                 uniform highp float width;
194                 void main() {
195                     highp vec4 pos = qt_Vertex;
196                     highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
197                     pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
198                     gl_Position = qt_Matrix * pos;
199                     qt_TexCoord0 = qt_MultiTexCoord0;
200                 }"
201         }
202         \endqml
203     \endtable
204 */
205
206 void QQuickGridMesh::setResolution(const QSize &res)
207 {
208     if (res == m_resolution)
209         return;
210     if (res.width() < 1 || res.height() < 1) {
211         return;
212     }
213     m_resolution = res;
214     emit resolutionChanged();
215 }
216
217 QSize QQuickGridMesh::resolution() const
218 {
219     return m_resolution;
220 }
221
222 QT_END_NAMESPACE