diff options
author | Gunnar Sletta <gunnar.sletta@nokia.com> | 2010-11-19 10:47:58 +0100 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@nokia.com> | 2010-11-19 10:47:58 +0100 |
commit | 651bed285a79ba2d541d061abb641ad074607b79 (patch) | |
tree | 5edbd62933b216a04498a1124f347b7796815609 | |
parent | 7b98280f9fc038657a111770d15564c4703d786a (diff) | |
parent | 97d808e1f5ce754f2bf218107bb200a8a52fc137 (diff) |
Merge branch 'master' of scm.dev.nokia.troll.no:research/qt-scene-graph
-rw-r--r-- | src/canvas/qvsyncanimationdriver.cpp | 1 | ||||
-rw-r--r-- | src/canvas/qxclipnode.cpp | 87 | ||||
-rw-r--r-- | src/canvas/qxclipnode_p.h | 6 | ||||
-rw-r--r-- | src/effects/shadereffectitem.cpp | 18 | ||||
-rw-r--r-- | src/graphicsitems/qxitem.cpp | 34 | ||||
-rw-r--r-- | src/graphicsitems/qxitem.h | 1 | ||||
-rw-r--r-- | src/graphicsitems/qxrectangle.cpp | 6 | ||||
-rw-r--r-- | src/scenegraph/coreapi/geometry.cpp | 158 | ||||
-rw-r--r-- | src/scenegraph/coreapi/geometry.h | 50 | ||||
-rw-r--r-- | src/scenegraph/coreapi/qmlrenderer.cpp | 99 | ||||
-rw-r--r-- | src/scenegraph/coreapi/qmlrenderer.h | 8 | ||||
-rw-r--r-- | src/scenegraph/coreapi/renderer.cpp | 128 | ||||
-rw-r--r-- | src/scenegraph/coreapi/renderer.h | 39 | ||||
-rw-r--r-- | src/scenegraph_include.pri | 2 | ||||
-rw-r--r-- | tests/rrClip.qml | 15 | ||||
-rw-r--r-- | tools/qmlscene/main.cpp | 26 |
16 files changed, 344 insertions, 334 deletions
diff --git a/src/canvas/qvsyncanimationdriver.cpp b/src/canvas/qvsyncanimationdriver.cpp index ac16938..dd84dd3 100644 --- a/src/canvas/qvsyncanimationdriver.cpp +++ b/src/canvas/qvsyncanimationdriver.cpp @@ -69,6 +69,7 @@ bool QVSyncAnimationDriver::event(QEvent *e) if (e->type() == QEvent::User + 1) { while (isRunning() && !d->aborted) { + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); QApplication::processEvents(QEventLoop::AllEvents, 1); advance(); ((WidgetAccessor *) d->window)->paint(); diff --git a/src/canvas/qxclipnode.cpp b/src/canvas/qxclipnode.cpp index a954b62..aded473 100644 --- a/src/canvas/qxclipnode.cpp +++ b/src/canvas/qxclipnode.cpp @@ -44,83 +44,80 @@ #include "qxclipnode_p.h" #include "utilities.h" +#include <QtGui/QVector2D> #include <QtCore/qmath.h> QxClipNode::QxClipNode(const QRectF &rect) : m_rect(rect), m_radius(0) { - updateGeometry(); + updateGeometryDescription(Utilities::getRectGeometryDescription(), GL_UNSIGNED_SHORT); + Utilities::setupRectGeometry(geometry(), m_rect); setFlag(ClipIsRectangular, true); } void QxClipNode::setRect(const QRectF &rect) { m_rect = rect; - updateGeometry(); + setUpdateFlag(UpdateGeometry); } void QxClipNode::setRadius(qreal radius) { m_radius = radius; - updateGeometry(); + setUpdateFlag(UpdateGeometry); setFlag(ClipIsRectangular, radius == 0); } +void QxClipNode::update(uint updateFlags) +{ + if (updateFlags & UpdateGeometry) + updateGeometry(); +} + void QxClipNode::updateGeometry() { if (qFuzzyIsNull(m_radius)) { updateGeometryDescription(Utilities::getRectGeometryDescription(), GL_UNSIGNED_SHORT); Utilities::setupRectGeometry(geometry(), m_rect); } else { - // ### Fix. - updateGeometryDescription(Utilities::getRectGeometryDescription(), GL_UNSIGNED_SHORT); - Utilities::setupRectGeometry(geometry(), m_rect); - /* - //XXX copy of what is in QxRectangle (we should reuse the geometry generated there if possible) + struct Vertex + { + QVector2D position; + }; + + Geometry *g = geometry(); + int vertexCount = 0; + QRectF rect = m_rect; - qreal radius = m_radius; - - QArray<QVector2D> vertices; - QGLVertexBuffer v; - - qreal zero = 0. * M_PI/180.; - qreal ninety = 90. * M_PI/180.; - qreal oneeighty = 180. * M_PI/180.; - qreal twoseventy = 270. * M_PI/180.; - qreal nninety = -90. * M_PI/180.; - qreal step = -1.5708/radius; - - //upper left - QPointF cp(rect.x() + radius, rect.y() + radius); - for (qreal angle = twoseventy; angle >= oneeighty; angle += step) { - vertices.append(QVector2D(cp.x() + qFastSin(angle) * radius, cp.y() + qFastCos(angle) * radius)); - } + rect.adjust(m_radius, m_radius, -m_radius, -m_radius); - //upper right - cp = QPointF(rect.x() + rect.width() - radius, rect.y() + radius); - for (qreal angle = oneeighty; angle >= ninety; angle += step) { - vertices.append(QVector2D(cp.x() + qFastSin(angle) * radius, cp.y() + qFastCos(angle) * radius)); - } + int segments = qMin(15, qCeil(m_radius)); // Number of segments per corner. - //lower right - cp = QPointF(rect.x() + rect.width() - radius, rect.y() + rect.height() - radius); - for (qreal angle = ninety; angle >= zero; angle += step) { - vertices.append(QVector2D(cp.x() + qFastSin(angle) * radius, cp.y() + qFastCos(angle) * radius)); - } + // Overestimate the number of vertices and indices, reduce afterwards when the actual numbers are known. + g->setVertexCount((segments + 1) * 4); + g->setIndexCount(0); + + Vertex *vertices = (Vertex *)g->vertexData(); + + for (int part = 0; part < 2; ++part) { + for (int i = 0; i <= segments; ++i) { + //### Should change to calculate sin/cos only once. + qreal angle = qreal(0.5 * M_PI) * (part + i / qreal(segments)); + qreal s = qFastSin(angle); + qreal c = qFastCos(angle); + qreal y = (part ? rect.bottom() : rect.top()) - m_radius * c; // current inner y-coordinate. + qreal lx = rect.left() - m_radius * s; // current inner left x-coordinate. + qreal rx = rect.right() + m_radius * s; // current inner right x-coordinate. - //lower left - cp = QPointF(rect.x() + radius, rect.y() + rect.height() - radius); - for (qreal angle = zero; angle >= nninety; angle += step) { - vertices.append(QVector2D(cp.x() + qFastSin(angle) * radius, cp.y() + qFastCos(angle) * radius)); + vertices[vertexCount++].position = QVector2D(rx, y); + vertices[vertexCount++].position = QVector2D(lx, y); + } } - vertices.append(QVector2D(rect.x(), rect.y() + radius)); - v.addAttribute(QGL::Position, vertices); + g->setDrawingMode(QGL::TriangleStrip); + g->setVertexCount(vertexCount); - setDrawingMode(QGL::TriangleFan); - setVertexBuffer(v); - setIndexBuffer(Utilities::createIndexBuffer(vertices.count())); - */ + markDirty(DirtyGeometry); } setBoundingRect(m_rect); } diff --git a/src/canvas/qxclipnode_p.h b/src/canvas/qxclipnode_p.h index 76d7bbf..0754897 100644 --- a/src/canvas/qxclipnode_p.h +++ b/src/canvas/qxclipnode_p.h @@ -49,6 +49,10 @@ class QxClipNode : public ClipNode { public: + enum UpdateFlag { + UpdateGeometry = 1 + }; + QxClipNode(const QRectF &); void setRect(const QRectF &); @@ -57,6 +61,8 @@ public: void setRadius(qreal radius); qreal radius() const { return m_radius; } + virtual void update(uint updateFlags); + private: void updateGeometry(); QRectF m_rect; diff --git a/src/effects/shadereffectitem.cpp b/src/effects/shadereffectitem.cpp index d995ad4..4b85c93 100644 --- a/src/effects/shadereffectitem.cpp +++ b/src/effects/shadereffectitem.cpp @@ -145,6 +145,24 @@ void CustomShaderMaterialData::updateEffectState(Renderer *, AbstractEffect *new case QVariant::Int: q->m_program.setUniformValue(name.constData(), v.toInt()); break; + case QVariant::Size: + case QVariant::SizeF: + q->m_program.setUniformValue(name.constData(), v.toSizeF()); + break; + case QVariant::Point: + case QVariant::PointF: + q->m_program.setUniformValue(name.constData(), v.toPointF()); + break; + case QVariant::Rect: + case QVariant::RectF: + { + QRectF r = v.toRectF(); + q->m_program.setUniformValue(name.constData(), r.x(), r.y(), r.width(), r.height()); + } + break; + case QVariant::Vector3D: + q->m_program.setUniformValue(name.constData(), qvariant_cast<QVector3D>(v)); + break; default: // QObjects are probably mapped to sampler2Ds which are handled above. if (!qVariantCanConvert<QObject *>(v)) diff --git a/src/graphicsitems/qxitem.cpp b/src/graphicsitems/qxitem.cpp index fc66ff4..7101215 100644 --- a/src/graphicsitems/qxitem.cpp +++ b/src/graphicsitems/qxitem.cpp @@ -751,16 +751,18 @@ QRectF QxItem::mapToScene(const QRectF &r) const return t.map(r).boundingRect(); } -QPointF QxItem::mapToItem(QxItem *, const QPointF &) const +QPointF QxItem::mapToItem(QxItem *item, const QPointF &point) const { - qWarning("QxItem::mapToItem(): Not impl"); - return QPointF(); + if (item) + return itemTransform(item).map(point); + return mapToScene(point); } -QPointF QxItem::mapFromItem(QxItem *, const QPointF &) const +QPointF QxItem::mapFromItem(QxItem *item, const QPointF &point) const { - qWarning("QxItem::mapFromItem(): Not impl"); - return QPointF(); + if (item) + return item->itemTransform(this).map(point); + return mapFromScene(point); } bool QxItem::isVisible() const @@ -1036,15 +1038,17 @@ void QxItemPrivate::updateClip() Q_Q(QxItem); if (clipNode) { - Q_ASSERT(clipNode); - Q_ASSERT(clipNode->parent() == &transformNode); - Q_ASSERT(clipNode->childCount() == 1); - Q_ASSERT(clipNode->childAtIndex(0) == &groupNode); - - // Remove the clip node from the scene graph. - transformNode.removeChildNode(clipNode); - clipNode->removeChildNode(&groupNode); - transformNode.prependChildNode(&groupNode); + if (clipNode->parent() != 0) { + Q_ASSERT(clipNode); + Q_ASSERT(clipNode->parent() == &transformNode); + Q_ASSERT(clipNode->childCount() == 1); + Q_ASSERT(clipNode->childAtIndex(0) == &groupNode); + + // Remove the clip node from the scene graph. + transformNode.removeChildNode(clipNode); + clipNode->removeChildNode(&groupNode); + transformNode.prependChildNode(&groupNode); + } } else { clipNode = new QxClipNode(QRectF(0, 0, 0, 0)); clipNode->setFlag(Node::OwnedByParent, false); diff --git a/src/graphicsitems/qxitem.h b/src/graphicsitems/qxitem.h index e2a9c64..2e95fce 100644 --- a/src/graphicsitems/qxitem.h +++ b/src/graphicsitems/qxitem.h @@ -67,6 +67,7 @@ class QT_SCENEGRAPH_EXPORT QxItem : public QObject, public QDeclarativeParserSta Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL) + Q_PROPERTY(QPointF pos READ pos WRITE setPos FINAL) Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL) Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL) Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged FINAL) diff --git a/src/graphicsitems/qxrectangle.cpp b/src/graphicsitems/qxrectangle.cpp index ff3b174..6d240c5 100644 --- a/src/graphicsitems/qxrectangle.cpp +++ b/src/graphicsitems/qxrectangle.cpp @@ -41,6 +41,7 @@ #include "qxrectangle_p.h" #include "qxrectangle_p_p.h" +#include "qxclipnode_p.h" #include "geometry.h" #include "vertexcolormaterial.h" @@ -177,10 +178,9 @@ void QxRectangle::setRadius(qreal radius) if (d->node) d->node->setRadius(radius); -#ifdef ROUNDEDRECT_CLIP if (d->clipNode) d->clipNode->setRadius(d->radius); -#endif + emit radiusChanged(); } @@ -247,6 +247,8 @@ void QxRectangle::componentComplete() d->updateGradient(); d->updateBorderWidth(); d->updateBorderColor(); + if (d->clipNode) + d->clipNode->setRadius(d->radius); setPaintNode(d->node); // Must call setRect() before calling setPaintNode() for clipping to be correct. } diff --git a/src/scenegraph/coreapi/geometry.cpp b/src/scenegraph/coreapi/geometry.cpp index 1e8f735..3f52b34 100644 --- a/src/scenegraph/coreapi/geometry.cpp +++ b/src/scenegraph/coreapi/geometry.cpp @@ -46,27 +46,30 @@ #include <QApplication> Geometry::Geometry() - : m_isVertexDataDirty(false) - , m_isIndexDataDirty(false) - , m_mode(QGL::Triangles) + : m_mode(QGL::Triangles) , m_vertex_stride(0) , m_index_stride(0) { setIndexType(GL_UNSIGNED_SHORT); + GeometryDataUploader::registerGeometry(this); } Geometry::Geometry(const QVector<QGLAttributeDescription> &description, GLenum indexType) - : m_isVertexDataDirty(false) - , m_isIndexDataDirty(false) - , m_mode(QGL::Triangles) + : m_mode(QGL::Triangles) { setIndexType(indexType); setVertexDescription(description); + GeometryDataUploader::registerGeometry(this); +} + +Geometry::~Geometry() +{ + GeometryDataUploader::unregisterGeometry(this); } void *Geometry::vertexData() { - m_isVertexDataDirty = true; + GeometryDataUploader::markVertexDirty(); return m_vertex_data.data(); } @@ -81,7 +84,7 @@ void Geometry::setVertexDescription(const QVector<QGLAttributeDescription> &desc void *Geometry::indexData() { - m_isIndexDataDirty = true; + GeometryDataUploader::markIndexDirty(); return m_index_data.data(); } @@ -96,7 +99,7 @@ void Geometry::setIndexType(GLenum indexType) ushort *Geometry::ushortIndexData() { if (m_index_type == GL_UNSIGNED_SHORT) { - m_isIndexDataDirty = true; + GeometryDataUploader::markIndexDirty(); return reinterpret_cast<ushort *>(indexData()); } return 0; @@ -105,7 +108,7 @@ ushort *Geometry::ushortIndexData() uint *Geometry::uintIndexData() { if (m_index_type == GL_UNSIGNED_INT) { - m_isIndexDataDirty = true; + GeometryDataUploader::markIndexDirty(); return reinterpret_cast<uint *>(indexData()); } return 0; @@ -138,3 +141,138 @@ QGLAttributeValue Geometry::attributeValue(QGL::VertexAttribute attribute) const } return QGLAttributeValue(); } + + +// Copy bigger memory blocks at once +static inline void arraycpy(QArray<uchar> &dest, const QArray<uchar> &src) +{ + int extendSize = src.size(); + int size = dest.size(); + dest.extend(extendSize); + memcpy(dest.data() + size, src.data(), extendSize * sizeof(uchar)); +} + +bool GeometryDataUploader::m_use_buffers = true; +QSet<const Geometry *> GeometryDataUploader::m_geometries; +QGLBuffer GeometryDataUploader::m_vertex_buffer(QGLBuffer::VertexBuffer); +QGLBuffer GeometryDataUploader::m_index_buffer(QGLBuffer::IndexBuffer); +QArray<uchar> GeometryDataUploader::m_vertex_data; +QArray<uchar> GeometryDataUploader::m_index_data; +QHash<const Geometry *, int> GeometryDataUploader::m_vertex_offsets; +QHash<const Geometry *, int> GeometryDataUploader::m_index_offsets; +bool GeometryDataUploader::m_vertex_bound = false; +bool GeometryDataUploader::m_index_bound = false; +bool GeometryDataUploader::m_vertex_dirty = false; +bool GeometryDataUploader::m_index_dirty = false; + +void GeometryDataUploader::registerGeometry(const Geometry *g) +{ + if (!m_use_buffers) + return; + + m_geometries.insert(g); +} + +void GeometryDataUploader::unregisterGeometry(const Geometry *g) +{ + if (!m_use_buffers) + return; + + m_geometries.remove(g); +} + +void GeometryDataUploader::addGeometryVertex(const Geometry *g) +{ + if (!m_use_buffers || g->vertexCount() == 0) + return; + + const QArray<uchar> &vertexData = g->vertexArray(); + m_vertex_offsets.insert(g, m_vertex_data.count()); + arraycpy(m_vertex_data, vertexData); +} + +void GeometryDataUploader::addGeometryIndex(const Geometry *g) +{ + if (!m_use_buffers || g->indexCount() == 0) + return; + + if (g->indexCount()) { + const QArray<uchar> &indexData = g->indexArray(); + m_index_offsets.insert(g, m_index_data.count()); + arraycpy(m_index_data, indexData); + } +} + +void GeometryDataUploader::bind() +{ + if (!m_use_buffers) + return; + + if (!m_vertex_buffer.isCreated()) + m_vertex_buffer.create(); + if (!m_index_buffer.isCreated()) + m_index_buffer.create(); + + if (!m_vertex_bound) + m_vertex_bound = m_vertex_buffer.bind(); + if (!m_index_bound) + m_index_bound = m_index_buffer.bind(); +} + +void GeometryDataUploader::release() +{ + if (!m_use_buffers) + return; + + if (m_vertex_bound) + m_vertex_buffer.release(); + if (m_index_bound) + m_index_buffer.release(); + m_vertex_bound = false; + m_index_bound = false; +} + +void GeometryDataUploader::upload() +{ + if (!m_use_buffers || (!m_vertex_dirty && !m_index_dirty)) + return; + + bind(); + + if (m_vertex_dirty) + clearVertexData(); + if (m_index_dirty) + clearIndexData(); + + QSet<const Geometry *>::const_iterator i; + for (i = m_geometries.begin(); i != m_geometries.end(); ++i) { + if (m_vertex_dirty) + addGeometryVertex(*i); + if (m_index_dirty) + addGeometryIndex(*i); + } + + if (!m_vertex_data.isEmpty() && m_vertex_dirty) + m_vertex_buffer.allocate(m_vertex_data.data(), m_vertex_data.size()); + if (!m_index_data.isEmpty() && m_index_dirty) + m_index_buffer.allocate(m_index_data.data(), m_index_data.size()); + + m_vertex_dirty = false; + m_index_dirty = false; +} + +const void *GeometryDataUploader::vertexData(const Geometry *g, int offset) +{ + if (m_use_buffers) + return reinterpret_cast<const void *>(m_vertex_offsets.value(g) + offset); + else + return reinterpret_cast<const void *>(g->vertexArray().constData() + offset); +} + +const void *GeometryDataUploader::indexData(const Geometry *g) +{ + if (m_use_buffers) + return reinterpret_cast<const void *>(m_index_offsets.value(g)); + else + return g->constIndexData(); +} diff --git a/src/scenegraph/coreapi/geometry.h b/src/scenegraph/coreapi/geometry.h index 4ebe580..7876dba 100644 --- a/src/scenegraph/coreapi/geometry.h +++ b/src/scenegraph/coreapi/geometry.h @@ -57,6 +57,7 @@ class QT_SCENEGRAPH_EXPORT Geometry public: Geometry(); // Creates a null geometry. Geometry(const QVector<QGLAttributeDescription> &description, GLenum indexType = GL_UNSIGNED_SHORT); + ~Geometry(); void *vertexData(); const void *constVertexData() const { return m_vertex_data.constData(); } @@ -105,15 +106,7 @@ public: bool isNull() const { return m_vertex_description.isEmpty(); } - bool isVertexDataDirty() const { return m_isVertexDataDirty; } - void setVertexDataDirty(bool d) { m_isVertexDataDirty = d; } - bool isIndexDataDirty() const { return m_isIndexDataDirty; } - void setIndexDataDirty(bool d) { m_isIndexDataDirty = d; } - protected: - bool m_isVertexDataDirty; - bool m_isIndexDataDirty; - QArray<uchar> m_vertex_data; QArray<uchar> m_index_data; @@ -124,4 +117,45 @@ protected: int m_index_stride; }; +class GeometryDataUploader +{ +public: + static void registerGeometry(const Geometry *); + static void unregisterGeometry(const Geometry *); + + static void bind(); + static void release(); + static void upload(); + + static const void *vertexData(const Geometry *g, int offset = 0); + static const void *indexData(const Geometry *g); + + static void setUseBuffers(bool b) { m_use_buffers = b; } + static bool useBuffers() { return m_use_buffers; } + + static void markVertexDirty() { m_vertex_dirty = true; } + static void markIndexDirty() { m_index_dirty = true; } + +private: + static void addGeometryVertex(const Geometry *); + static void addGeometryIndex(const Geometry *); + + static void clearVertexData() { m_vertex_offsets.clear(); m_vertex_data.clear(); } + static void clearIndexData() { m_index_offsets.clear(); m_index_data.clear(); } + + static bool m_use_buffers; + static QSet<const Geometry *> m_geometries; + static QGLBuffer m_vertex_buffer; + static QGLBuffer m_index_buffer; + static QArray<uchar> m_vertex_data; + static QArray<uchar> m_index_data; + static QHash<const Geometry *, int> m_vertex_offsets; + static QHash<const Geometry *, int> m_index_offsets; + static bool m_vertex_bound; + static bool m_index_bound; + static bool m_vertex_dirty; + static bool m_index_dirty; +}; + + #endif diff --git a/src/scenegraph/coreapi/qmlrenderer.cpp b/src/scenegraph/coreapi/qmlrenderer.cpp index ceea599..eada040 100644 --- a/src/scenegraph/coreapi/qmlrenderer.cpp +++ b/src/scenegraph/coreapi/qmlrenderer.cpp @@ -50,6 +50,8 @@ #include <QtGui/qapplication.h> #include <QtCore/qpair.h> +//#define FORCE_NO_REORDER + static bool nodeLessThan(GeometryNode *a, GeometryNode *b) { // Sort by clip... @@ -119,14 +121,14 @@ T Heap<T, prealloc>::pop() QMLRenderer::QMLRenderer() - : m_dirtyVertexData(false) - , m_dirtyIndexData(false) + : Renderer() { -#if defined(QML_RUNTIME_TESTING) QStringList args = qApp->arguments(); +#if defined(QML_RUNTIME_TESTING) m_render_opaque_nodes = !args.contains("--no-opaque-nodes"); m_render_alpha_nodes = !args.contains("--no-alpha-nodes"); #endif + GeometryDataUploader::setUseBuffers(!args.contains("--no-vbo")); } void QMLRenderer::render() @@ -173,14 +175,9 @@ void QMLRenderer::render() m_opaqueNodes.clear(); m_transparentNodes.clear(); - m_clipNodes.clear(); - int currentRenderOrder = 0; + int currentRenderOrder = 1; buildLists(rootNode(), ¤tRenderOrder); - if (m_geometry_uploader.useBuffers()) - uploadNodeData(); - - ++currentRenderOrder; m_renderOrderMatrix.setToIdentity(); m_renderOrderMatrix.scale(1, 1, qreal(1) / currentRenderOrder); @@ -203,8 +200,6 @@ void QMLRenderer::render() m_currentProgram->deactivate(); m_projectionMatrix.pop(); - - m_geometry_uploader.release(); } class Foo : public QPair<int, GeometryNode *> @@ -227,39 +222,30 @@ void QMLRenderer::buildLists(Node *node, int *currentRenderOrder) g = geomNode->geometry(); if (g->vertexCount()) { //Sanity check +#ifdef FORCE_NO_REORDER + if (true) { +#else if (geomNode->material()->flags() & AbstractEffect::Blending) { - geomNode->setRenderOrder(*currentRenderOrder); +#endif + geomNode->setRenderOrder(*currentRenderOrder - 1); m_transparentNodes.append(geomNode); } else { - geomNode->setRenderOrder(*currentRenderOrder + 1); + geomNode->setRenderOrder(*currentRenderOrder); m_opaqueNodes.append(geomNode); *currentRenderOrder += 2; } } - } else if (node->type() == Node::ClipNodeType) { - ClipNode *clipNode = static_cast<ClipNode *>(node); - g = clipNode->geometry(); - - if (g->vertexCount()) //Sanity check - m_clipNodes.append(clipNode); - } - - if (g && m_geometry_uploader.useBuffers()) { - if (g->isVertexDataDirty() || !m_geometry_uploader.containsGeometryVertex(g)) { - m_dirtyVertexData = true; - g->setVertexDataDirty(false); - } - if (g->isIndexDataDirty() || (g->indexCount() && !m_geometry_uploader.containsGeometryIndex(g))) { - m_dirtyIndexData = true; - g->setIndexDataDirty(false); - } } int count = node->childCount(); if (!count) return; +#ifdef FORCE_NO_REORDER + static bool reorder = false; +#else static bool reorder = !qApp->arguments().contains("--no-reorder"); +#endif if (reorder && count > 1 && (node->flags() & Node::ChildrenDoNotOverloap)) { QVarLengthArray<int, 16> beginIndices(count); @@ -298,51 +284,6 @@ void QMLRenderer::buildLists(Node *node, int *currentRenderOrder) } } -void QMLRenderer::uploadNodeData() -{ - m_geometry_uploader.bind(); - - if (!m_dirtyVertexData && !m_dirtyIndexData) - return; - - if (m_dirtyVertexData) - m_geometry_uploader.clearVertexData(); - if (m_dirtyIndexData) - m_geometry_uploader.clearIndexData(); - - int count = m_opaqueNodes.count(); - for (int i = 0; i < count; ++i) { - GeometryNode *geomNode = m_opaqueNodes.at(i); - if (m_dirtyVertexData) - m_geometry_uploader.addGeometryVertex(geomNode->geometry()); - if (m_dirtyIndexData) - m_geometry_uploader.addGeometryIndex(geomNode->geometry()); - } - - count = m_transparentNodes.count(); - for (int i = 0; i < count; ++i) { - GeometryNode *geomNode = m_transparentNodes.at(i); - if (m_dirtyVertexData) - m_geometry_uploader.addGeometryVertex(geomNode->geometry()); - if (m_dirtyIndexData) - m_geometry_uploader.addGeometryIndex(geomNode->geometry()); - } - - count = m_clipNodes.count(); - for (int i = 0; i < count; ++i) { - ClipNode *clipNode = m_clipNodes.at(i); - if (m_dirtyVertexData) - m_geometry_uploader.addGeometryVertex(clipNode->geometry()); - if (m_dirtyIndexData) - m_geometry_uploader.addGeometryIndex(clipNode->geometry()); - } - - m_geometry_uploader.upload(); - - m_dirtyVertexData = false; - m_dirtyIndexData = false; -} - void QMLRenderer::renderNodes(const QVector<GeometryNode *> &list, int renderOrders) { const float scale = 1.0f / renderOrders; @@ -375,7 +316,11 @@ void QMLRenderer::renderNodes(const QVector<GeometryNode *> &list, int renderOrd if (changeClip) { clipType = updateStencilClip(geomNode->clipList()); m_currentClip = geomNode->clipList(); +#ifdef FORCE_NO_REORDER + glDepthMask(false); +#else glDepthMask((material->flags() & AbstractEffect::Blending) == 0); +#endif //++clipChangeCount; } @@ -422,7 +367,7 @@ void QMLRenderer::renderNodes(const QVector<GeometryNode *> &list, int renderOrd GLboolean normalize = attr.type() != GL_FLOAT && attr.type() != GL_DOUBLE; #endif glVertexAttribPointer(*attributes, attr.tupleSize(), attr.type(), normalize, attr.stride(), - m_geometry_uploader.vertexData(g, offset)); + GeometryDataUploader::vertexData(g, offset)); offset += attr.tupleSize() * attr.sizeOfType(); } else { qWarning("Attribute required by effect is missing."); @@ -432,7 +377,7 @@ void QMLRenderer::renderNodes(const QVector<GeometryNode *> &list, int renderOrd QPair<int, int> indexRange = geomNode->indexRange(); if (g->indexCount()) glDrawElements(GLenum(g->drawingMode()), indexRange.second - indexRange.first, g->indexType(), - m_geometry_uploader.indexData(g)); + GeometryDataUploader::indexData(g)); else glDrawArrays(GLenum(g->drawingMode()), indexRange.first, indexRange.second - indexRange.first); } diff --git a/src/scenegraph/coreapi/qmlrenderer.h b/src/scenegraph/coreapi/qmlrenderer.h index c0b7947..d2dd6f3 100644 --- a/src/scenegraph/coreapi/qmlrenderer.h +++ b/src/scenegraph/coreapi/qmlrenderer.h @@ -46,16 +46,14 @@ class QMLRenderer : public Renderer { + Q_OBJECT public: QMLRenderer(); void render(); - bool allowRenderOrderUpdates() const { return false; } - private: void buildLists(Node *node, int *currentRenderOrder); - void uploadNodeData(); void renderNodes(const QVector <GeometryNode *> &list, int renderOrders); const ClipNode *m_currentClip; @@ -65,12 +63,8 @@ private: QMatrix4x4 m_renderOrderMatrix; QVector<GeometryNode *> m_opaqueNodes; QVector<GeometryNode *> m_transparentNodes; - QVector<ClipNode *> m_clipNodes; QVector<GeometryNode *> m_tempNodes; - bool m_dirtyVertexData; - bool m_dirtyIndexData; - #ifdef QML_RUNTIME_TESTING bool m_render_opaque_nodes; bool m_render_alpha_nodes; diff --git a/src/scenegraph/coreapi/renderer.cpp b/src/scenegraph/coreapi/renderer.cpp index 53310ea..e082acb 100644 --- a/src/scenegraph/coreapi/renderer.cpp +++ b/src/scenegraph/coreapi/renderer.cpp @@ -62,125 +62,10 @@ void BindableFbo::bind() const m_fbo->bind(); } -// Copy bigger memory blocks at once -static inline void arraycpy(QArray<uchar> &dest, const QArray<uchar> &src) -{ - int extendSize = src.size(); - int size = dest.size(); - dest.extend(extendSize); - memcpy(dest.data() + size, src.data(), extendSize * sizeof(uchar)); -} - - -GeometryDataUploader::GeometryDataUploader() - : m_use_buffers(!qApp->arguments().contains("--no-vbo")) - , m_vertex_buffer(QGLBuffer::VertexBuffer) - , m_index_buffer(QGLBuffer::IndexBuffer) - , m_vertex_bound(false) - , m_index_bound(false) -{ -} - -void GeometryDataUploader::addGeometryVertex(const Geometry *g) -{ - if (!m_use_buffers) - return; - - const QArray<uchar> &vertexData = g->vertexArray(); - m_vertex_offsets.insert(g, m_vertex_data.count()); - arraycpy(m_vertex_data, vertexData); -} - -void GeometryDataUploader::addGeometryIndex(const Geometry *g) -{ - if (!m_use_buffers) - return; - - if (g->indexCount()) { - const QArray<uchar> &indexData = g->indexArray(); - m_index_offsets.insert(g, m_index_data.count()); - arraycpy(m_index_data, indexData); - } -} - -bool GeometryDataUploader::containsGeometryVertex(const Geometry *g) -{ - if (!m_use_buffers) - return true; - - return m_vertex_offsets.contains(g); -} - -bool GeometryDataUploader::containsGeometryIndex(const Geometry *g) -{ - if (!m_use_buffers) - return true; - - return m_index_offsets.contains(g); -} - -void GeometryDataUploader::bind() -{ - if (!m_use_buffers) - return; - - if (!m_vertex_buffer.isCreated()) - m_vertex_buffer.create(); - if (!m_index_buffer.isCreated()) - m_index_buffer.create(); - - if (!m_vertex_bound) - m_vertex_bound = m_vertex_buffer.bind(); - if (!m_index_bound) - m_index_bound = m_index_buffer.bind(); -} - -void GeometryDataUploader::release() -{ - if (!m_use_buffers) - return; - - if (m_vertex_bound) - m_vertex_buffer.release(); - if (m_index_bound) - m_index_buffer.release(); - m_vertex_bound = false; - m_index_bound = false; -} - -void GeometryDataUploader::upload() -{ - if (!m_use_buffers) - return; - - bind(); - - if (!m_vertex_data.isEmpty()) - m_vertex_buffer.allocate(m_vertex_data.data(), m_vertex_data.size()); - - if (!m_index_data.isEmpty()) - m_index_buffer.allocate(m_index_data.data(), m_index_data.size()); -} - -const void *GeometryDataUploader::vertexData(const Geometry *g, int offset) -{ - if (m_use_buffers) - return reinterpret_cast<const void *>(m_vertex_offsets.value(g) + offset); - else - return reinterpret_cast<const void *>(g->vertexArray().constData() + offset); -} - -const void *GeometryDataUploader::indexData(const Geometry *g) -{ - if (m_use_buffers) - return reinterpret_cast<const void *>(m_index_offsets.value(g)); - else - return g->constIndexData(); -} - Renderer::Renderer() - : m_clear_color(Qt::transparent) + : QObject() + , m_clear_color(Qt::transparent) , m_root_node(0) , m_changed_emitted(false) { @@ -229,7 +114,10 @@ void Renderer::renderScene(const Bindable &bindable) preprocess(); bindable.bind(); + GeometryDataUploader::bind(); + GeometryDataUploader::upload(); render(); + GeometryDataUploader::release(); m_changed_emitted = false; } @@ -240,7 +128,7 @@ void Renderer::setProjectMatrixToDeviceRect() m_device_rect.x() + m_device_rect.width(), m_device_rect.y() + m_device_rect.height(), m_device_rect.y(), - 100, + qreal(0.01), -1); setProjectMatrix(matrix); } @@ -445,14 +333,14 @@ Renderer::ClipType Renderer::updateStencilClip(const ClipNode *clip) const QGLAttributeValue &v = geometry->attributeValue(QGL::Position); glVertexAttribPointer(QGL::Position, v.tupleSize(), v.type(), GL_FALSE, v.stride(), - m_geometry_uploader.vertexData(geometry)); + GeometryDataUploader::vertexData(geometry)); m_clip_program.setUniformValue(m_clip_matrix_id, m); QPair<int, int> range = clip->indexRange(); if (geometry->indexCount()) { glDrawElements(GLenum(geometry->drawingMode()), range.second - range.first, geometry->indexType() - , m_geometry_uploader.indexData(geometry)); + , GeometryDataUploader::indexData(geometry)); } else { glDrawArrays(GLenum(geometry->drawingMode()), range.first, range.second - range.first); } diff --git a/src/scenegraph/coreapi/renderer.h b/src/scenegraph/coreapi/renderer.h index 9c63150..1d9856f 100644 --- a/src/scenegraph/coreapi/renderer.h +++ b/src/scenegraph/coreapi/renderer.h @@ -76,41 +76,6 @@ private: QGLFramebufferObject *m_fbo; }; -class GeometryDataUploader -{ -public: - GeometryDataUploader(); - - void addGeometryVertex(const Geometry *); - void addGeometryIndex(const Geometry *); - - bool containsGeometryVertex(const Geometry *); - bool containsGeometryIndex(const Geometry *); - - void bind(); - void release(); - void upload(); - - const void *vertexData(const Geometry *g, int offset = 0); - const void *indexData(const Geometry *g); - - void clearVertexData() { m_vertex_offsets.clear(); m_vertex_data.clear(); } - void clearIndexData() { m_index_offsets.clear(); m_index_data.clear(); } - - bool useBuffers() const { return m_use_buffers; } - -private: - bool m_use_buffers; - - QGLBuffer m_vertex_buffer; - QGLBuffer m_index_buffer; - QArray<uchar> m_vertex_data; - QArray<uchar> m_index_data; - QHash<const Geometry *, int> m_vertex_offsets; - QHash<const Geometry *, int> m_index_offsets; - bool m_vertex_bound; - bool m_index_bound; -}; class QT_SCENEGRAPH_EXPORT Renderer : public QObject, protected QGLFunctions { @@ -164,8 +129,6 @@ public: virtual void nodeChanged(Node *node, Node::DirtyFlags flags); virtual void materialChanged(GeometryNode *node, AbstractEffect *from, AbstractEffect *to); - virtual bool allowRenderOrderUpdates() const = 0; - public slots: signals: @@ -186,8 +149,6 @@ protected: QMatrix4x4Stack m_projectionMatrix; QMatrix4x4Stack m_modelViewMatrix; - GeometryDataUploader m_geometry_uploader; - private: RootNode *m_root_node; QRect m_device_rect; diff --git a/src/scenegraph_include.pri b/src/scenegraph_include.pri index 654ee96..6b0d38e 100644 --- a/src/scenegraph_include.pri +++ b/src/scenegraph_include.pri @@ -10,7 +10,7 @@ INCLUDEPATH += \ $$PWD QT += opengl declarative -LIBS += -lQtSceneGraph -L$$PWD/../lib +LIBS += -L$$PWD/../lib -lQtSceneGraph DEFINES += QT_USE_SCENEGRAPH DEFINES += QML_RUNTIME_TESTING diff --git a/tests/rrClip.qml b/tests/rrClip.qml index 7105ba0..ece7605 100644 --- a/tests/rrClip.qml +++ b/tests/rrClip.qml @@ -46,14 +46,21 @@ Rectangle { height: 480 Rectangle { - width: 400; height: 400 + width: 400; height: 400; anchors.centerIn: parent - radius: 100 + radius: 200 + color: "transparent" clip: true Rectangle { - anchors.fill: parent - color: "green" + anchors.centerIn: parent + width: 400; height: 400 + gradient: Gradient { + GradientStop { position: 0.0; color: "white" } + GradientStop { position: 1.0; color: "green" } + } + + NumberAnimation on rotation { to: 360; duration: 3000; loops: -1 } } } } diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp index 37f4df3..b49f194 100644 --- a/tools/qmlscene/main.cpp +++ b/tools/qmlscene/main.cpp @@ -229,10 +229,19 @@ protected: struct Options { - Options() : originalQml(false), maximized(false), fullscreen(false), scenegraphOnGraphicsview(false), clip(false) { } + Options() + : originalQml(false) + , originalQmlRaster(false) + , maximized(false) + , fullscreen(false) + , scenegraphOnGraphicsview(false) + , clip(false) + { + } QUrl file; bool originalQml; + bool originalQmlRaster; bool maximized; bool fullscreen; bool scenegraphOnGraphicsview; @@ -359,8 +368,9 @@ static void usage() qWarning(" options:"); qWarning(" --maximized................................ run maximized"); qWarning(" --fullscreen............................... run fullscreen"); - qWarning(" --original-qml............................. run using QGraphicsView instead of scenegraph"); - qWarning(" --multisample.............................. use a GL context with multisample buffer"); + qWarning(" --original-qml............................. run using QGraphicsView instead of scenegraph (OpenGL engine)"); + qWarning(" --original-qml-raster...................... run using QGraphicsView instead of scenegraph (Raster engine)"); + qWarning(" --no-multisample........................... Disable multisampling (anti-aliasing)"); qWarning(" --continuous-update........................ Continuously render the scene"); qWarning(" --nonblocking-swap......................... Do not wait for v-sync to swap buffers"); qWarning(" --sg-on-gv [--clip]........................ Scenegraph on graphicsview (and clip to item)"); @@ -380,6 +390,8 @@ int main(int argc, char ** argv) options.file = QUrl::fromLocalFile(argv[i]); else if (QString::fromLatin1(argv[i]).toLower() == QLatin1String("--original-qml")) options.originalQml = true; + else if (QString::fromLatin1(argv[i]).toLower() == QLatin1String("--original-qml-raster")) + options.originalQmlRaster = true; else if (QString::fromLatin1(argv[i]).toLower() == QLatin1String("--maximized")) options.maximized = true; else if (QString::fromLatin1(argv[i]).toLower() == QLatin1String("--fullscreen")) @@ -429,7 +441,7 @@ int main(int argc, char ** argv) loadDummyDataFiles(*engine, fi.path()); } item->setSource(options.file); - } else if (!options.originalQml) { + } else if (!options.originalQml && !options.originalQmlRaster) { QxGraphicsView *qxView = new MyQxGraphicsView(); engine = qxView->engine(); for (int i = 0; i < imports.size(); ++i) @@ -452,8 +464,10 @@ int main(int argc, char ** argv) loadDummyDataFiles(*engine, fi.path()); } gvView->setSource(options.file); - QGLWidget *viewport = new QGLWidget(getFormat()); - gvView->setViewport(viewport); + if (!options.originalQmlRaster) { + QGLWidget *viewport = new QGLWidget(getFormat()); + gvView->setViewport(viewport); + } } QObject::connect(engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit())); |