summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2010-11-19 10:47:58 +0100
committerGunnar Sletta <gunnar.sletta@nokia.com>2010-11-19 10:47:58 +0100
commit651bed285a79ba2d541d061abb641ad074607b79 (patch)
tree5edbd62933b216a04498a1124f347b7796815609
parent7b98280f9fc038657a111770d15564c4703d786a (diff)
parent97d808e1f5ce754f2bf218107bb200a8a52fc137 (diff)
Merge branch 'master' of scm.dev.nokia.troll.no:research/qt-scene-graph
-rw-r--r--src/canvas/qvsyncanimationdriver.cpp1
-rw-r--r--src/canvas/qxclipnode.cpp87
-rw-r--r--src/canvas/qxclipnode_p.h6
-rw-r--r--src/effects/shadereffectitem.cpp18
-rw-r--r--src/graphicsitems/qxitem.cpp34
-rw-r--r--src/graphicsitems/qxitem.h1
-rw-r--r--src/graphicsitems/qxrectangle.cpp6
-rw-r--r--src/scenegraph/coreapi/geometry.cpp158
-rw-r--r--src/scenegraph/coreapi/geometry.h50
-rw-r--r--src/scenegraph/coreapi/qmlrenderer.cpp99
-rw-r--r--src/scenegraph/coreapi/qmlrenderer.h8
-rw-r--r--src/scenegraph/coreapi/renderer.cpp128
-rw-r--r--src/scenegraph/coreapi/renderer.h39
-rw-r--r--src/scenegraph_include.pri2
-rw-r--r--tests/rrClip.qml15
-rw-r--r--tools/qmlscene/main.cpp26
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(), &currentRenderOrder);
- 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()));