rename QSGGeometry::stride() to sizeOfVertex for symetry with index
[profile/ivi/qtdeclarative.git] / src / declarative / scenegraph / coreapi / qsggeometry.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the Qt scene graph research project.
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 "qsggeometry.h"
43 #include "qsggeometry_p.h"
44
45 #include <qopenglcontext.h>
46 #include <qopenglfunctions.h>
47 #include <private/qopenglextensions_p.h>
48
49 QT_BEGIN_NAMESPACE
50
51
52 QSGGeometry::Attribute QSGGeometry::Attribute::create(int attributeIndex, int tupleSize, int primitiveType, bool isPrimitive)
53 {
54     Attribute a = { attributeIndex, tupleSize, primitiveType, isPrimitive, 0 };
55     return a;
56 }
57
58
59 /*!
60     Convenience function which returns attributes to be used for 2D solid
61     color drawing.
62  */
63
64 const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_Point2D()
65 {
66     static Attribute data[] = {
67         QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true)
68     };
69     static AttributeSet attrs = { 1, sizeof(float) * 2, data };
70     return attrs;
71 }
72
73 /*!
74     Convenience function which returns attributes to be used for textured 2D drawing.
75  */
76
77 const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_TexturedPoint2D()
78 {
79     static Attribute data[] = {
80         QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),
81         QSGGeometry::Attribute::create(1, 2, GL_FLOAT)
82     };
83     static AttributeSet attrs = { 2, sizeof(float) * 4, data };
84     return attrs;
85 }
86
87 /*!
88     Convenience function which returns attributes to be used for per vertex colored 2D drawing.
89  */
90
91 const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D()
92 {
93     static Attribute data[] = {
94         QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),
95         QSGGeometry::Attribute::create(1, 4, GL_UNSIGNED_BYTE)
96     };
97     static AttributeSet attrs = { 2, 2 * sizeof(float) + 4 * sizeof(char), data };
98     return attrs;
99 }
100
101
102 /*!
103     \class QSGGeometry
104     \brief The QSGGeometry class provides low-level storage for graphics primitives
105     in the QML Scene Graph.
106
107     The QSGGeometry class provides a few convenience attributes and attribute accessors
108     by default. The defaultAttributes_Point2D() function returns attributes to be used
109     in normal solid color rectangles, while the defaultAttributes_TexturedPoint2D function
110     returns attributes to be used for the common pixmap usecase.
111  */
112
113
114 /*!
115     Constructs a geometry object based on \a attributes.
116
117     The object allocate space for \a vertexCount vertices based on the accumulated
118     size in \a attributes and for \a indexCount.
119
120     Geometry objects are constructed with GL_TRIANGLE_STRIP as default drawing mode.
121
122     The attribute structure is assumed to be POD and the geometry object
123     assumes this will not go away. There is no memory management involved.
124  */
125
126 QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes,
127                          int vertexCount,
128                          int indexCount,
129                          int indexType)
130     : m_drawing_mode(GL_TRIANGLE_STRIP)
131     , m_vertex_count(0)
132     , m_index_count(0)
133     , m_index_type(indexType)
134     , m_attributes(attributes)
135     , m_data(0)
136     , m_index_data_offset(-1)
137     , m_server_data(0)
138     , m_owns_data(false)
139     , m_index_usage_pattern(AlwaysUploadPattern)
140     , m_vertex_usage_pattern(AlwaysUploadPattern)
141 {
142     Q_ASSERT(m_attributes.count > 0);
143     Q_ASSERT(m_attributes.stride > 0);
144
145     Q_ASSERT_X(indexType != GL_UNSIGNED_INT
146                || static_cast<QOpenGLExtensions *>(QOpenGLContext::currentContext()->functions())
147                   ->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint),
148                "QSGGeometry::QSGGeometry",
149                "GL_UNSIGNED_INT is not supported, geometry will not render"
150                );
151
152     if (indexType != GL_UNSIGNED_BYTE
153         && indexType != GL_UNSIGNED_SHORT
154         && indexType != GL_UNSIGNED_INT) {
155         qFatal("QSGGeometry: Unsupported index type, %x.\n", indexType);
156     }
157
158
159     // Because allocate reads m_vertex_count, m_index_count and m_owns_data, these
160     // need to be set before calling allocate...
161     allocate(vertexCount, indexCount);
162 }
163
164 /*!
165     \fn int QSGGeometry::sizeOfVertex() const
166
167     Returns the size in bytes of one vertex.
168
169     This value comes from the attributes.
170  */
171
172 /*!
173     \fn int QSGGeometry::sizeOfIndex() const
174
175     Returns the byte size of the index type.
176
177     This value is either 1 when index type is GL_UNSIGNED_BYTE or 2 when
178     index type is GL_UNSIGNED_SHORT. For Desktop OpenGL, GL_UNSIGNED_INT
179     with the value 4 is also supported.
180  */
181
182 QSGGeometry::~QSGGeometry()
183 {
184     if (m_owns_data)
185         qFree(m_data);
186
187     if (m_server_data)
188         delete m_server_data;
189 }
190
191 /*!
192     \fn int QSGGeometry::vertexCount() const
193
194     Returns the number of vertices in this geometry object.
195  */
196
197 /*!
198     \fn int QSGGeometry::indexCount() const
199
200     Returns the number of indices in this geometry object.
201  */
202
203
204
205 /*!
206     \fn void *QSGGeometry::vertexData()
207
208     Returns a pointer to the raw vertex data of this geometry object.
209
210     \sa vertexDataAsPoint2D(), vertexDataAsTexturedPoint2D
211  */
212
213 /*!
214     \fn const void *QSGGeometry::vertexData() const
215
216     Returns a pointer to the raw vertex data of this geometry object.
217
218     \sa vertexDataAsPoint2D(), vertexDataAsTexturedPoint2D
219  */
220
221 /*!
222     Returns a pointer to the raw index data of this geometry object.
223
224     \sa indexDataAsUShort(), indexDataAsUInt()
225  */
226 void *QSGGeometry::indexData()
227 {
228     return m_index_data_offset < 0
229             ? 0
230             : ((char *) m_data + m_index_data_offset);
231 }
232
233 /*!
234     Returns a pointer to the raw index data of this geometry object.
235
236     \sa indexDataAsUShort(), indexDataAsUInt()
237  */
238 const void *QSGGeometry::indexData() const
239 {
240     return m_index_data_offset < 0
241             ? 0
242             : ((char *) m_data + m_index_data_offset);
243 }
244
245 /*!
246     Sets the drawing mode to be used for this geometry.
247
248     The default value is GL_TRIANGLE_STRIP.
249  */
250 void QSGGeometry::setDrawingMode(GLenum mode)
251 {
252     m_drawing_mode = mode;
253 }
254
255 /*!
256     \fn int QSGGeometry::drawingMode() const
257
258     Returns the drawing mode of this geometry.
259
260     The default value is GL_TRIANGLE_STRIP.
261  */
262
263 /*!
264     \fn int QSGGeometry::indexType() const
265
266     Returns the primitive type used for indices in this
267     geometry object.
268  */
269
270
271 /*!
272     Resizes the vertex and index data of this geometry object to fit \a vertexCount
273     vertices and \a indexCount indices.
274
275     Vertex and index data will be invalidated after this call and the caller must
276  */
277 void QSGGeometry::allocate(int vertexCount, int indexCount)
278 {
279     if (vertexCount == m_vertex_count && indexCount == m_index_count)
280         return;
281
282     m_vertex_count = vertexCount;
283     m_index_count = indexCount;
284
285     bool canUsePrealloc = m_index_count <= 0;
286     int vertexByteSize = m_attributes.stride * m_vertex_count;
287
288     if (m_owns_data)
289         qFree(m_data);
290
291     if (canUsePrealloc && vertexByteSize <= (int) sizeof(m_prealloc)) {
292         m_data = (void *) &m_prealloc[0];
293         m_index_data_offset = -1;
294         m_owns_data = false;
295     } else {
296         Q_ASSERT(m_index_type == GL_UNSIGNED_INT || m_index_type == GL_UNSIGNED_SHORT);
297         int indexByteSize = indexCount * (m_index_type == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32));
298         m_data = (void *) qMalloc(vertexByteSize + indexByteSize);
299         m_index_data_offset = vertexByteSize;
300         m_owns_data = true;
301     }
302
303     // If we have associated vbo data we could potentially crash later if
304     // the old buffers are used with the new vertex and index count, so we force
305     // an update in the renderer in that case. This is really the users responsibility
306     // but it is cheap for us to enforce this, so why not...
307     if (m_server_data) {
308         markIndexDataDirty();
309         markVertexDataDirty();
310     }
311
312 }
313
314 /*!
315     Updates the geometry \a g with the coordinates in \a rect.
316
317     The function assumes the geometry object contains a single triangle strip
318     of QSGGeometry::Point2D vertices
319  */
320 void QSGGeometry::updateRectGeometry(QSGGeometry *g, const QRectF &rect)
321 {
322     Point2D *v = g->vertexDataAsPoint2D();
323     v[0].x = rect.left();
324     v[0].y = rect.top();
325
326     v[1].x = rect.left();
327     v[1].y = rect.bottom();
328
329     v[2].x = rect.right();
330     v[2].y = rect.top();
331
332     v[3].x = rect.right();
333     v[3].y = rect.bottom();
334 }
335
336 /*!
337     Updates the geometry \a g with the coordinates in \a rect and texture
338     coordinates from \a textureRect.
339
340     \a textureRect should be in normalized coordinates.
341
342     \a g is assumed to be a triangle strip of four vertices of type
343     QSGGeometry::TexturedPoint2D.
344  */
345 void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &textureRect)
346 {
347     TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
348     v[0].x = rect.left();
349     v[0].y = rect.top();
350     v[0].tx = textureRect.left();
351     v[0].ty = textureRect.top();
352
353     v[1].x = rect.left();
354     v[1].y = rect.bottom();
355     v[1].tx = textureRect.left();
356     v[1].ty = textureRect.bottom();
357
358     v[2].x = rect.right();
359     v[2].y = rect.top();
360     v[2].tx = textureRect.right();
361     v[2].ty = textureRect.top();
362
363     v[3].x = rect.right();
364     v[3].y = rect.bottom();
365     v[3].tx = textureRect.right();
366     v[3].ty = textureRect.bottom();
367 }
368
369
370
371 /*!
372     \enum QSGGeometry::DataPattern
373
374     The DataPattern enum is used to specify the use pattern for the vertex
375     and index data in a geometry object.
376
377     \value AlwaysUploadPattern The data is always uploaded. This means that
378     the user does not need to explicitly mark index and vertex data as
379     dirty after changing it. This is the default.
380
381     \value DynamicPattern The data is modified repeatedly and drawn many times.
382     This is a hint that may provide better performance. When set
383     the user must make sure to mark the data as dirty after changing it.
384
385     \value StaticPattern The data is modified once and drawn many times. This is
386     a hint that may provide better performance. When set the user must make sure
387     to mark the data as dirty after changing it.
388  */
389
390
391 /*!
392     \fn QSGGeometry::DataPattern QSGGeometry::indexDataPattern() const
393
394     Returns the usage pattern for indices in this geometry. The default
395     pattern is AlwaysUploadPattern.
396  */
397
398 /*!
399     Sets the usage pattern for indices to \a p.
400
401     The default is AlwaysUploadPattern. When set to anything other than
402     the default, the user must call markIndexDataDirty() after changing
403     the index data.
404  */
405
406 void QSGGeometry::setIndexDataPattern(DataPattern p)
407 {
408     m_index_usage_pattern = p;
409 }
410
411
412
413
414 /*!
415     \fn QSGGeometry::DataPattern QSGGeometry::vertexDataPattern() const
416
417     Returns the usage pattern for vertices in this geometry. The default
418     pattern is AlwaysUploadPattern.
419  */
420
421 /*!
422     Sets the usage pattern for vertices to \a p.
423
424     The default is AlwaysUploadPattern. When set to anything other than
425     the default, the user must call markVertexDataDirty() after changing
426     the vertex data.
427  */
428
429 void QSGGeometry::setVertexDataPattern(DataPattern p)
430 {
431     m_vertex_usage_pattern = p;
432 }
433
434
435
436
437 /*!
438     Mark that the vertices in this geometry has changed and must be uploaded
439     again.
440
441     This function only has an effect when the usage pattern for vertices is
442     StaticData and the renderer that renders this geometry uploads the geometry
443     into Vertex Buffer Objects (VBOs).
444  */
445 void QSGGeometry::markIndexDataDirty()
446 {
447     m_dirty_index_data = true;
448 }
449
450
451
452 /*!
453     Mark that the vertices in this geometry has changed and must be uploaded
454     again.
455
456     This function only has an effect when the usage pattern for vertices is
457     StaticData and the renderer that renders this geometry uploads the geometry
458     into Vertex Buffer Objects (VBOs).
459  */
460 void QSGGeometry::markVertexDataDirty()
461 {
462     m_dirty_vertex_data = true;
463 }
464
465
466 QT_END_NAMESPACE