893993db6ce459c4f34b59d52ab3429b5cc70361
[profile/ivi/qtdeclarative.git] / src / quick / scenegraph / util / qsgtexturematerial.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qsgtexturematerial_p.h"
43
44 #include <QtGui/qopenglshaderprogram.h>
45 #include <QtGui/qopenglfunctions.h>
46
47 QT_BEGIN_NAMESPACE
48
49 inline static bool isPowerOfTwo(int x)
50 {
51     // Assumption: x >= 1
52     return x == (x & -x);
53 }
54
55 const char qt_scenegraph_texture_material_vertex_code[] =
56     "uniform highp mat4 qt_Matrix;                      \n"
57     "attribute highp vec4 qt_VertexPosition;            \n"
58     "attribute highp vec2 qt_VertexTexCoord;            \n"
59     "varying highp vec2 qt_TexCoord;                    \n"
60     "void main() {                                      \n"
61     "    qt_TexCoord = qt_VertexTexCoord;               \n"
62     "    gl_Position = qt_Matrix * qt_VertexPosition;   \n"
63     "}";
64
65 const char qt_scenegraph_texture_material_fragment[] =
66     "varying highp vec2 qt_TexCoord;                    \n"
67     "uniform sampler2D qt_Texture;                      \n"
68     "void main() {                                      \n"
69     "    gl_FragColor = texture2D(qt_Texture, qt_TexCoord);\n"
70     "}";
71
72
73 const char *QSGOpaqueTextureMaterialShader::vertexShader() const
74 {
75     return qt_scenegraph_texture_material_vertex_code;
76 }
77
78 const char *QSGOpaqueTextureMaterialShader::fragmentShader() const
79 {
80     return qt_scenegraph_texture_material_fragment;
81 }
82
83 QSGMaterialType QSGOpaqueTextureMaterialShader::type;
84
85 char const *const *QSGOpaqueTextureMaterialShader::attributeNames() const
86 {
87     static char const *const attr[] = { "qt_VertexPosition", "qt_VertexTexCoord", 0 };
88     return attr;
89 }
90
91 void QSGOpaqueTextureMaterialShader::initialize()
92 {
93     m_matrix_id = program()->uniformLocation("qt_Matrix");
94 }
95
96 void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
97 {
98     Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
99     QSGOpaqueTextureMaterial *tx = static_cast<QSGOpaqueTextureMaterial *>(newEffect);
100     QSGOpaqueTextureMaterial *oldTx = static_cast<QSGOpaqueTextureMaterial *>(oldEffect);
101
102     QSGTexture *t = tx->texture();
103
104     t->setFiltering(tx->filtering());
105 #ifdef QT_OPENGL_ES_2
106     bool npotSupported = QOpenGLFunctions(const_cast<QOpenGLContext *>(state.context())).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
107     QSize size = t->textureSize();
108     bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
109     if (!npotSupported && isNpot) {
110         t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
111         t->setVerticalWrapMode(QSGTexture::ClampToEdge);
112     } else
113 #endif
114     {
115         t->setHorizontalWrapMode(tx->horizontalWrapMode());
116         t->setVerticalWrapMode(tx->verticalWrapMode());
117     }
118     t->setMipmapFiltering(tx->mipmapFiltering());
119
120     if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId())
121         t->bind();
122     else
123         t->updateBindOptions();
124
125     if (state.isMatrixDirty())
126         program()->setUniformValue(m_matrix_id, state.combinedMatrix());
127 }
128
129
130 /*!
131     \class QSGOpaqueTextureMaterial
132     \brief The QSGOpaqueTextureMaterial class provides a convenient way of
133     rendering textured geometry in the scene graph.
134
135     The opaque textured material will fill every pixel in a geometry with
136     the supplied texture. The material does not respect the opacity of the
137     QSGMaterialShader::RenderState, so opacity nodes in the parent chain
138     of nodes using this material, have no effect.
139
140     The geometry to be rendered with an opaque texture material requires
141     vertices in attribute location 0 and texture coordinates in attribute
142     location 1. The texture coordinate is a 2-dimensional floating-point
143     tuple. The QSGGeometry::defaultAttributes_TexturedPoint2D returns an
144     attribute set compatible with this material.
145
146     The texture to be rendered is can be set using setTexture(). How the
147     texure should be rendered can be specified using setMipmapFiltering(),
148     setFiltering(), setHorizontalWrapMode() and setVerticalWrapMode().
149     The rendering state is set on the texture instance just before it
150     is bound.
151
152     The opaque textured material respects the current matrix and the alpha
153     channel of the texture. It will disregard the accumulated opacity in
154     the scenegraph.
155
156     A texture material must have a texture set before it is used as
157     a material in the scene graph.
158  */
159
160
161
162 /*!
163     Creates a new QSGOpaqueTextureMaterial.
164
165     The default mipmap filtering and filtering mode is set to
166     QSGTexture::Nearest. The default wrap modes is set to
167     QSGTexture::ClampToEdge.
168
169  */
170 QSGOpaqueTextureMaterial::QSGOpaqueTextureMaterial()
171     : m_texture(0)
172     , m_filtering(QSGTexture::Nearest)
173     , m_mipmap_filtering(QSGTexture::Nearest)
174     , m_horizontal_wrap(QSGTexture::ClampToEdge)
175     , m_vertical_wrap(QSGTexture::ClampToEdge)
176 {
177 }
178
179
180 /*!
181     \internal
182  */
183 QSGMaterialType *QSGOpaqueTextureMaterial::type() const
184 {
185     return &QSGOpaqueTextureMaterialShader::type;
186 }
187
188 /*!
189     \internal
190  */
191 QSGMaterialShader *QSGOpaqueTextureMaterial::createShader() const
192 {
193     return new QSGOpaqueTextureMaterialShader;
194 }
195
196
197
198 /*!
199     \fn QSGTexture *QSGOpaqueTextureMaterial::texture() const
200
201     Returns this texture material's texture.
202  */
203
204
205
206 /*!
207     Sets the texture of this material to \a texture.
208
209     The material does not take ownership over the texture.
210  */
211
212 void QSGOpaqueTextureMaterial::setTexture(QSGTexture *texture)
213 {
214     m_texture = texture;
215     setFlag(Blending, m_texture ? m_texture->hasAlphaChannel() : false);
216 }
217
218
219
220 /*!
221     \fn void QSGOpaqueTextureMaterial::setMipmapFiltering(QSGTexture::Filtering filtering)
222
223     Sets the mipmap mode to \a filtering.
224
225     The mipmap filtering mode is set on the texture instance just before the
226     texture is bound for rendering.
227
228     If the texture does not have mipmapping support, enabling mipmapping has no
229     effect.
230  */
231
232
233
234 /*!
235     \fn QSGTexture::Filtering QSGOpaqueTextureMaterial::mipmapFiltering() const
236
237     Returns this material's mipmap filtering mode.
238
239     The default mipmap mode is QSGTexture::Nearest.
240  */
241
242
243
244 /*!
245     \fn void QSGOpaqueTextureMaterial::setFiltering(QSGTexture::Filtering filtering)
246
247     Sets the filtering to \a filtering.
248
249     The filtering mode is set on the texture instance just before the texture
250     is bound for rendering.
251  */
252
253
254
255 /*!
256     \fn QSGTexture::Filtering filtering() const
257
258     Returns this material's filtering mode.
259
260     The default filtering is QSGTexture::Nearest.
261  */
262
263
264
265 /*!
266     \fn void setHorizontalWrapMode(QSGTexture::WrapMode mode)
267
268     Sets the horizontal wrap mode to \a mode.
269
270     The horizontal wrap mode is set on the texture instance just before the texture
271     is bound for rendering.
272  */
273
274
275
276  /*!
277      \fn QSGTexture::WrapMode horizontalWrapMode() const
278
279      Returns this material's horizontal wrap mode.
280
281      The default horizontal wrap mode is QSGTexutre::ClampToEdge
282   */
283
284
285
286 /*!
287     \fn void setVerticalWrapMode(QSGTexture::WrapMode mode)
288
289     Sets the vertical wrap mode to \a mode.
290
291     The vertical wrap mode is set on the texture instance just before the texture
292     is bound for rendering.
293  */
294
295
296
297  /*!
298      \fn QSGTexture::WrapMode verticalWrapMode() const
299
300      Returns this material's vertical wrap mode.
301
302      The default vertical wrap mode is QSGTexutre::ClampToEdge
303   */
304
305
306
307 /*!
308     \internal
309  */
310
311 int QSGOpaqueTextureMaterial::compare(const QSGMaterial *o) const
312 {
313     Q_ASSERT(o && type() == o->type());
314     const QSGOpaqueTextureMaterial *other = static_cast<const QSGOpaqueTextureMaterial *>(o);
315     if (int diff = m_texture->textureId() - other->texture()->textureId())
316         return diff;
317     return int(m_filtering) - int(other->m_filtering);
318 }
319
320
321
322 /*!
323     \class QSGTextureMaterial
324     \brief The QSGTextureMaterial class provides a convenient way of
325     rendering textured geometry in the scene graph.
326
327     The textured material will fill every pixel in a geometry with
328     the supplied texture.
329
330     The geometry to be rendered with a texture material requires
331     vertices in attribute location 0 and texture coordinates in attribute
332     location 1. The texture coordinate is a 2-dimensional floating-point
333     tuple. The QSGGeometry::defaultAttributes_TexturedPoint2D returns an
334     attribute set compatible with this material.
335
336     The texture to be rendered is set using setTexture(). How the
337     texure should be rendered can be specified using setMipmapFiltering(),
338     setFiltering(), setHorizontalWrapMode() and setVerticalWrapMode().
339     The rendering state is set on the texture instance just before it
340     is bound.
341
342     The textured material respects the current matrix and the alpha
343     channel of the texture. It will also respect the accumulated opacity
344     in the scenegraph.
345
346     A texture material must have a texture set before it is used as
347     a material in the scene graph.
348  */
349
350 static const char qt_scenegraph_texture_material_opacity_fragment[] =
351     "varying highp vec2 qt_TexCoord;                       \n"
352     "uniform sampler2D qt_Texture;                         \n"
353     "uniform lowp float opacity;                        \n"
354     "void main() {                                      \n"
355     "    gl_FragColor = texture2D(qt_Texture, qt_TexCoord) * opacity; \n"
356     "}";
357
358 class QSGTextureMaterialShader : public QSGOpaqueTextureMaterialShader
359 {
360 public:
361     virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
362     virtual void initialize();
363
364     static QSGMaterialType type;
365
366 protected:
367     virtual const char *fragmentShader() const { return qt_scenegraph_texture_material_opacity_fragment; }
368
369     int m_opacity_id;
370 };
371 QSGMaterialType QSGTextureMaterialShader::type;
372
373
374
375 /*!
376     \internal
377  */
378
379 QSGMaterialType *QSGTextureMaterial::type() const
380 {
381     return &QSGTextureMaterialShader::type;
382 }
383
384
385
386 /*!
387     \internal
388  */
389
390 QSGMaterialShader *QSGTextureMaterial::createShader() const
391 {
392     return new QSGTextureMaterialShader;
393 }
394
395 void QSGTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
396 {
397     Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
398     if (state.isOpacityDirty())
399         program()->setUniformValue(m_opacity_id, state.opacity());
400
401     QSGOpaqueTextureMaterialShader::updateState(state, newEffect, oldEffect);
402 }
403
404 void QSGTextureMaterialShader::initialize()
405 {
406     QSGOpaqueTextureMaterialShader::initialize();
407     m_opacity_id = program()->uniformLocation("opacity");
408 }
409
410 QT_END_NAMESPACE