1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the Qt scene graph research project.
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.
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.
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.
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.
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)
142 Q_ASSERT(m_attributes.count > 0);
143 Q_ASSERT(m_attributes.stride > 0);
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"
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);
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);
165 \fn int QSGGeometry::sizeOfVertex() const
167 Returns the size in bytes of one vertex.
169 This value comes from the attributes.
173 \fn int QSGGeometry::sizeOfIndex() const
175 Returns the byte size of the index type.
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.
182 QSGGeometry::~QSGGeometry()
188 delete m_server_data;
192 \fn int QSGGeometry::vertexCount() const
194 Returns the number of vertices in this geometry object.
198 \fn int QSGGeometry::indexCount() const
200 Returns the number of indices in this geometry object.
206 \fn void *QSGGeometry::vertexData()
208 Returns a pointer to the raw vertex data of this geometry object.
210 \sa vertexDataAsPoint2D(), vertexDataAsTexturedPoint2D
214 \fn const void *QSGGeometry::vertexData() const
216 Returns a pointer to the raw vertex data of this geometry object.
218 \sa vertexDataAsPoint2D(), vertexDataAsTexturedPoint2D
222 Returns a pointer to the raw index data of this geometry object.
224 \sa indexDataAsUShort(), indexDataAsUInt()
226 void *QSGGeometry::indexData()
228 return m_index_data_offset < 0
230 : ((char *) m_data + m_index_data_offset);
234 Returns a pointer to the raw index data of this geometry object.
236 \sa indexDataAsUShort(), indexDataAsUInt()
238 const void *QSGGeometry::indexData() const
240 return m_index_data_offset < 0
242 : ((char *) m_data + m_index_data_offset);
246 Sets the drawing mode to be used for this geometry.
248 The default value is GL_TRIANGLE_STRIP.
250 void QSGGeometry::setDrawingMode(GLenum mode)
252 m_drawing_mode = mode;
256 \fn int QSGGeometry::drawingMode() const
258 Returns the drawing mode of this geometry.
260 The default value is GL_TRIANGLE_STRIP.
264 \fn int QSGGeometry::indexType() const
266 Returns the primitive type used for indices in this
272 Resizes the vertex and index data of this geometry object to fit \a vertexCount
273 vertices and \a indexCount indices.
275 Vertex and index data will be invalidated after this call and the caller must
277 void QSGGeometry::allocate(int vertexCount, int indexCount)
279 if (vertexCount == m_vertex_count && indexCount == m_index_count)
282 m_vertex_count = vertexCount;
283 m_index_count = indexCount;
285 bool canUsePrealloc = m_index_count <= 0;
286 int vertexByteSize = m_attributes.stride * m_vertex_count;
291 if (canUsePrealloc && vertexByteSize <= (int) sizeof(m_prealloc)) {
292 m_data = (void *) &m_prealloc[0];
293 m_index_data_offset = -1;
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;
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...
308 markIndexDataDirty();
309 markVertexDataDirty();
315 Updates the geometry \a g with the coordinates in \a rect.
317 The function assumes the geometry object contains a single triangle strip
318 of QSGGeometry::Point2D vertices
320 void QSGGeometry::updateRectGeometry(QSGGeometry *g, const QRectF &rect)
322 Point2D *v = g->vertexDataAsPoint2D();
323 v[0].x = rect.left();
326 v[1].x = rect.left();
327 v[1].y = rect.bottom();
329 v[2].x = rect.right();
332 v[3].x = rect.right();
333 v[3].y = rect.bottom();
337 Updates the geometry \a g with the coordinates in \a rect and texture
338 coordinates from \a textureRect.
340 \a textureRect should be in normalized coordinates.
342 \a g is assumed to be a triangle strip of four vertices of type
343 QSGGeometry::TexturedPoint2D.
345 void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &textureRect)
347 TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
348 v[0].x = rect.left();
350 v[0].tx = textureRect.left();
351 v[0].ty = textureRect.top();
353 v[1].x = rect.left();
354 v[1].y = rect.bottom();
355 v[1].tx = textureRect.left();
356 v[1].ty = textureRect.bottom();
358 v[2].x = rect.right();
360 v[2].tx = textureRect.right();
361 v[2].ty = textureRect.top();
363 v[3].x = rect.right();
364 v[3].y = rect.bottom();
365 v[3].tx = textureRect.right();
366 v[3].ty = textureRect.bottom();
372 \enum QSGGeometry::DataPattern
374 The DataPattern enum is used to specify the use pattern for the vertex
375 and index data in a geometry object.
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.
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.
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.
392 \fn QSGGeometry::DataPattern QSGGeometry::indexDataPattern() const
394 Returns the usage pattern for indices in this geometry. The default
395 pattern is AlwaysUploadPattern.
399 Sets the usage pattern for indices to \a p.
401 The default is AlwaysUploadPattern. When set to anything other than
402 the default, the user must call markIndexDataDirty() after changing
406 void QSGGeometry::setIndexDataPattern(DataPattern p)
408 m_index_usage_pattern = p;
415 \fn QSGGeometry::DataPattern QSGGeometry::vertexDataPattern() const
417 Returns the usage pattern for vertices in this geometry. The default
418 pattern is AlwaysUploadPattern.
422 Sets the usage pattern for vertices to \a p.
424 The default is AlwaysUploadPattern. When set to anything other than
425 the default, the user must call markVertexDataDirty() after changing
429 void QSGGeometry::setVertexDataPattern(DataPattern p)
431 m_vertex_usage_pattern = p;
438 Mark that the vertices in this geometry has changed and must be uploaded
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).
445 void QSGGeometry::markIndexDataDirty()
447 m_dirty_index_data = true;
453 Mark that the vertices in this geometry has changed and must be uploaded
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).
460 void QSGGeometry::markVertexDataDirty()
462 m_dirty_vertex_data = true;