1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the Qt scene graph research project.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qsggeometry.h"
43 #include "qsggeometry_p.h"
45 #include <qopenglcontext.h>
46 #include <qopenglfunctions.h>
47 #include <private/qopenglextensions_p.h>
52 QSGGeometry::Attribute QSGGeometry::Attribute::create(int attributeIndex, int tupleSize, int primitiveType, bool isPrimitive)
54 Attribute a = { attributeIndex, tupleSize, primitiveType, isPrimitive, 0 };
60 Convenience function which returns attributes to be used for 2D solid
64 const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_Point2D()
66 static Attribute data[] = {
67 QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true)
69 static AttributeSet attrs = { 1, sizeof(float) * 2, data };
74 Convenience function which returns attributes to be used for textured 2D drawing.
77 const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_TexturedPoint2D()
79 static Attribute data[] = {
80 QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),
81 QSGGeometry::Attribute::create(1, 2, GL_FLOAT)
83 static AttributeSet attrs = { 2, sizeof(float) * 4, data };
88 Convenience function which returns attributes to be used for per vertex colored 2D drawing.
91 const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D()
93 static Attribute data[] = {
94 QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),
95 QSGGeometry::Attribute::create(1, 4, GL_UNSIGNED_BYTE)
97 static AttributeSet attrs = { 2, 2 * sizeof(float) + 4 * sizeof(char), data };
104 \brief The QSGGeometry class provides low-level storage for graphics primitives
105 in the QML Scene Graph.
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.
115 Constructs a geometry object based on \a attributes.
117 The object allocate space for \a vertexCount vertices based on the accumulated
118 size in \a attributes and for \a indexCount.
120 Geometry objects are constructed with GL_TRIANGLE_STRIP as default drawing mode.
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.
126 QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes,
130 : m_drawing_mode(GL_TRIANGLE_STRIP)
133 , m_index_type(indexType)
134 , m_attributes(attributes)
136 , m_index_data_offset(-1)
139 , m_index_usage_pattern(AlwaysUploadPattern)
140 , m_vertex_usage_pattern(AlwaysUploadPattern)
143 Q_ASSERT(m_attributes.count > 0);
144 Q_ASSERT(m_attributes.stride > 0);
146 Q_ASSERT_X(indexType != GL_UNSIGNED_INT
147 || static_cast<QOpenGLExtensions *>(QOpenGLContext::currentContext()->functions())
148 ->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint),
149 "QSGGeometry::QSGGeometry",
150 "GL_UNSIGNED_INT is not supported, geometry will not render"
153 if (indexType != GL_UNSIGNED_BYTE
154 && indexType != GL_UNSIGNED_SHORT
155 && indexType != GL_UNSIGNED_INT) {
156 qFatal("QSGGeometry: Unsupported index type, %x.\n", indexType);
160 // Because allocate reads m_vertex_count, m_index_count and m_owns_data, these
161 // need to be set before calling allocate...
162 allocate(vertexCount, indexCount);
166 \fn int QSGGeometry::sizeOfVertex() const
168 Returns the size in bytes of one vertex.
170 This value comes from the attributes.
174 \fn int QSGGeometry::sizeOfIndex() const
176 Returns the byte size of the index type.
178 This value is either 1 when index type is GL_UNSIGNED_BYTE or 2 when
179 index type is GL_UNSIGNED_SHORT. For Desktop OpenGL, GL_UNSIGNED_INT
180 with the value 4 is also supported.
183 QSGGeometry::~QSGGeometry()
189 delete m_server_data;
193 \fn int QSGGeometry::vertexCount() const
195 Returns the number of vertices in this geometry object.
199 \fn int QSGGeometry::indexCount() const
201 Returns the number of indices in this geometry object.
207 \fn void *QSGGeometry::vertexData()
209 Returns a pointer to the raw vertex data of this geometry object.
211 \sa vertexDataAsPoint2D(), vertexDataAsTexturedPoint2D
215 \fn const void *QSGGeometry::vertexData() const
217 Returns a pointer to the raw vertex data of this geometry object.
219 \sa vertexDataAsPoint2D(), vertexDataAsTexturedPoint2D
223 Returns a pointer to the raw index data of this geometry object.
225 \sa indexDataAsUShort(), indexDataAsUInt()
227 void *QSGGeometry::indexData()
229 return m_index_data_offset < 0
231 : ((char *) m_data + m_index_data_offset);
235 Returns a pointer to the raw index data of this geometry object.
237 \sa indexDataAsUShort(), indexDataAsUInt()
239 const void *QSGGeometry::indexData() const
241 return m_index_data_offset < 0
243 : ((char *) m_data + m_index_data_offset);
247 Sets the drawing mode to be used for this geometry.
249 The default value is GL_TRIANGLE_STRIP.
251 void QSGGeometry::setDrawingMode(GLenum mode)
253 m_drawing_mode = mode;
257 Gets the current line width to be used for this geometry. This property only
258 applies where the drawingMode is GL_LINES or a related value.
260 The default value is 1.0
262 \sa setLineWidth(), drawingMode()
264 float QSGGeometry::lineWidth() const
270 Sets the line width to be used for this geometry. This property only applies
271 where the drawingMode is GL_LINES or a related value.
273 \sa lineWidth(), drawingMode()
275 void QSGGeometry::setLineWidth(float w)
281 \fn int QSGGeometry::drawingMode() const
283 Returns the drawing mode of this geometry.
285 The default value is GL_TRIANGLE_STRIP.
289 \fn int QSGGeometry::indexType() const
291 Returns the primitive type used for indices in this
297 Resizes the vertex and index data of this geometry object to fit \a vertexCount
298 vertices and \a indexCount indices.
300 Vertex and index data will be invalidated after this call and the caller must
302 void QSGGeometry::allocate(int vertexCount, int indexCount)
304 if (vertexCount == m_vertex_count && indexCount == m_index_count)
307 m_vertex_count = vertexCount;
308 m_index_count = indexCount;
310 bool canUsePrealloc = m_index_count <= 0;
311 int vertexByteSize = m_attributes.stride * m_vertex_count;
316 if (canUsePrealloc && vertexByteSize <= (int) sizeof(m_prealloc)) {
317 m_data = (void *) &m_prealloc[0];
318 m_index_data_offset = -1;
321 Q_ASSERT(m_index_type == GL_UNSIGNED_INT || m_index_type == GL_UNSIGNED_SHORT);
322 int indexByteSize = indexCount * (m_index_type == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32));
323 m_data = (void *) malloc(vertexByteSize + indexByteSize);
324 m_index_data_offset = vertexByteSize;
328 // If we have associated vbo data we could potentially crash later if
329 // the old buffers are used with the new vertex and index count, so we force
330 // an update in the renderer in that case. This is really the users responsibility
331 // but it is cheap for us to enforce this, so why not...
333 markIndexDataDirty();
334 markVertexDataDirty();
340 Updates the geometry \a g with the coordinates in \a rect.
342 The function assumes the geometry object contains a single triangle strip
343 of QSGGeometry::Point2D vertices
345 void QSGGeometry::updateRectGeometry(QSGGeometry *g, const QRectF &rect)
347 Point2D *v = g->vertexDataAsPoint2D();
348 v[0].x = rect.left();
351 v[1].x = rect.left();
352 v[1].y = rect.bottom();
354 v[2].x = rect.right();
357 v[3].x = rect.right();
358 v[3].y = rect.bottom();
362 Updates the geometry \a g with the coordinates in \a rect and texture
363 coordinates from \a textureRect.
365 \a textureRect should be in normalized coordinates.
367 \a g is assumed to be a triangle strip of four vertices of type
368 QSGGeometry::TexturedPoint2D.
370 void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &textureRect)
372 TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
373 v[0].x = rect.left();
375 v[0].tx = textureRect.left();
376 v[0].ty = textureRect.top();
378 v[1].x = rect.left();
379 v[1].y = rect.bottom();
380 v[1].tx = textureRect.left();
381 v[1].ty = textureRect.bottom();
383 v[2].x = rect.right();
385 v[2].tx = textureRect.right();
386 v[2].ty = textureRect.top();
388 v[3].x = rect.right();
389 v[3].y = rect.bottom();
390 v[3].tx = textureRect.right();
391 v[3].ty = textureRect.bottom();
397 \enum QSGGeometry::DataPattern
399 The DataPattern enum is used to specify the use pattern for the vertex
400 and index data in a geometry object.
402 \value AlwaysUploadPattern The data is always uploaded. This means that
403 the user does not need to explicitly mark index and vertex data as
404 dirty after changing it. This is the default.
406 \value DynamicPattern The data is modified repeatedly and drawn many times.
407 This is a hint that may provide better performance. When set
408 the user must make sure to mark the data as dirty after changing it.
410 \value StaticPattern The data is modified once and drawn many times. This is
411 a hint that may provide better performance. When set the user must make sure
412 to mark the data as dirty after changing it.
417 \fn QSGGeometry::DataPattern QSGGeometry::indexDataPattern() const
419 Returns the usage pattern for indices in this geometry. The default
420 pattern is AlwaysUploadPattern.
424 Sets the usage pattern for indices to \a p.
426 The default is AlwaysUploadPattern. When set to anything other than
427 the default, the user must call markIndexDataDirty() after changing
431 void QSGGeometry::setIndexDataPattern(DataPattern p)
433 m_index_usage_pattern = p;
440 \fn QSGGeometry::DataPattern QSGGeometry::vertexDataPattern() const
442 Returns the usage pattern for vertices in this geometry. The default
443 pattern is AlwaysUploadPattern.
447 Sets the usage pattern for vertices to \a p.
449 The default is AlwaysUploadPattern. When set to anything other than
450 the default, the user must call markVertexDataDirty() after changing
454 void QSGGeometry::setVertexDataPattern(DataPattern p)
456 m_vertex_usage_pattern = p;
463 Mark that the vertices in this geometry has changed and must be uploaded
466 This function only has an effect when the usage pattern for vertices is
467 StaticData and the renderer that renders this geometry uploads the geometry
468 into Vertex Buffer Objects (VBOs).
470 void QSGGeometry::markIndexDataDirty()
472 m_dirty_index_data = true;
478 Mark that the vertices in this geometry has changed and must be uploaded
481 This function only has an effect when the usage pattern for vertices is
482 StaticData and the renderer that renders this geometry uploads the geometry
483 into Vertex Buffer Objects (VBOs).
485 void QSGGeometry::markVertexDataDirty()
487 m_dirty_vertex_data = true;