From aaf3e8013d21b7f9247da7751a340b75d1deedc2 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Fri, 28 May 2010 17:40:08 +1000 Subject: Make QGLBuffer copiable Reviewed-by: Gunnar --- src/opengl/qglbuffer.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++----- src/opengl/qglbuffer.h | 9 +++-- 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp index 223243c..d6e0109 100644 --- a/src/opengl/qglbuffer.cpp +++ b/src/opengl/qglbuffer.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include "qglbuffer.h" QT_BEGIN_NAMESPACE @@ -55,6 +56,20 @@ QT_BEGIN_NAMESPACE Buffer objects are created in the GL server so that the client application can avoid uploading vertices, indices, texture image data, etc every time they are needed. + + QGLBuffer objects can be copied around as a reference to the + underlying GL buffer object: + + \code + QGLBuffer buffer1(QGLBuffer::IndexBuffer); + buffer1.create(); + + QGLBuffer buffer2 = buffer1; + \endcode + + QGLBuffer performs a shallow copy when objects are copied in this + manner, but does not implement copy-on-write semantics. The original + object will be affected whenever the copy is modified. */ /*! @@ -116,13 +131,15 @@ class QGLBufferPrivate { public: QGLBufferPrivate(QGLBuffer::Type t) - : type(t), + : ref(1), + type(t), guard(0), usagePattern(QGLBuffer::StaticDraw), actualUsagePattern(QGLBuffer::StaticDraw) { } + QAtomicInt ref; QGLBuffer::Type type; QGLSharedResourceGuard guard; QGLBuffer::UsagePattern usagePattern; @@ -130,6 +147,19 @@ public: }; /*! + Constructs a new buffer object of type QGLBuffer::VertexBuffer. + + Note: this constructor just creates the QGLBuffer instance. The actual + buffer object in the GL server is not created until create() is called. + + \sa create() +*/ +QGLBuffer::QGLBuffer() + : d_ptr(new QGLBufferPrivate(QGLBuffer::VertexBuffer)) +{ +} + +/*! Constructs a new buffer object of \a type. Note: this constructor just creates the QGLBuffer instance. The actual @@ -142,6 +172,18 @@ QGLBuffer::QGLBuffer(QGLBuffer::Type type) { } +/*! + Constructs a shallow copy of \a other. + + Note: QGLBuffer does not implement copy-on-write semantics, + so \a other will be affected whenever the copy is modified. +*/ +QGLBuffer::QGLBuffer(const QGLBuffer &other) + : d_ptr(other.d_ptr) +{ + d_ptr->ref.ref(); +} + #define ctx d->guard.context() /*! @@ -150,13 +192,27 @@ QGLBuffer::QGLBuffer(QGLBuffer::Type type) */ QGLBuffer::~QGLBuffer() { - Q_D(QGLBuffer); - GLuint bufferId = d->guard.id(); - if (bufferId) { - // Switch to the original creating context to destroy it. - QGLShareContextScope scope(d->guard.context()); - glDeleteBuffers(1, &bufferId); + if (!d_ptr->ref.deref()) { + destroy(); + delete d_ptr; + } +} + +/*! + Assigns a shallow copy of \a other to this object. + + Note: QGLBuffer does not implement copy-on-write semantics, + so \a other will be affected whenever the copy is modified. +*/ +QGLBuffer &QGLBuffer::operator=(const QGLBuffer &other) +{ + if (d_ptr != other.d_ptr) { + other.d_ptr->ref.ref(); + if (!d_ptr->ref.deref()) + destroy(); + d_ptr = other.d_ptr; } + return *this; } /*! @@ -215,7 +271,7 @@ void QGLBuffer::setUsagePattern(QGLBuffer::UsagePattern value) This function will return false if the GL implementation does not support buffers, or there is no current QGLContext. - \sa isCreated(), allocate(), write() + \sa isCreated(), allocate(), write(), destroy() */ bool QGLBuffer::create() { @@ -242,7 +298,7 @@ bool QGLBuffer::create() /*! Returns true if this buffer has been created; false otherwise. - \sa create() + \sa create(), destroy() */ bool QGLBuffer::isCreated() const { @@ -251,6 +307,24 @@ bool QGLBuffer::isCreated() const } /*! + Destroys this buffer object, including the storage being + used in the GL server. All references to the buffer will + become invalid. +*/ +void QGLBuffer::destroy() +{ + Q_D(QGLBuffer); + GLuint bufferId = d->guard.id(); + if (bufferId) { + // Switch to the original creating context to destroy it. + QGLShareContextScope scope(d->guard.context()); + glDeleteBuffers(1, &bufferId); + } + d->guard.setId(0); + d->guard.setContext(0); +} + +/*! Reads the \a count bytes in this buffer starting at \a offset into \a data. Returns true on success; false if reading from the buffer is not supported. Buffer reading is not supported diff --git a/src/opengl/qglbuffer.h b/src/opengl/qglbuffer.h index 2fe1f1f..a1b45ff 100644 --- a/src/opengl/qglbuffer.h +++ b/src/opengl/qglbuffer.h @@ -64,9 +64,13 @@ public: PixelUnpackBuffer = 0x88EC // GL_PIXEL_UNPACK_BUFFER }; + QGLBuffer(); explicit QGLBuffer(QGLBuffer::Type type); + QGLBuffer(const QGLBuffer &other); ~QGLBuffer(); + QGLBuffer &operator=(const QGLBuffer &other); + enum UsagePattern { StreamDraw = 0x88E0, // GL_STREAM_DRAW @@ -95,6 +99,8 @@ public: bool create(); bool isCreated() const; + void destroy(); + bool bind() const; void release() const; @@ -114,9 +120,8 @@ public: bool unmap(); private: - QScopedPointer d_ptr; + QGLBufferPrivate *d_ptr; - Q_DISABLE_COPY(QGLBuffer) Q_DECLARE_PRIVATE(QGLBuffer) }; -- cgit v0.12 From b9d899339118f24b34182e7dbe7aed5956d927e7 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 25 May 2010 15:16:38 +0200 Subject: add test for QMetaMethod::invoke --- tests/auto/qmetaobject/tst_qmetaobject.cpp | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp index c0b1303..b6d4558 100644 --- a/tests/auto/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -172,6 +172,8 @@ private slots: void stdSet(); void classInfo(); + void metaMethod(); + signals: void value6Changed(); void value7Changed(const QString &); @@ -886,5 +888,54 @@ void tst_QMetaObject::classInfo() QCOMPARE(QLatin1String(b.metaObject()->classInfo(index).value()), QLatin1String("Christopher Pike")); } +void tst_QMetaObject::metaMethod() +{ + QString str("foo"); + QString ret("bar"); + QMetaMethod method; + QVERIFY(!method.invoke(this)); + QVERIFY(!method.invoke(this, Q_ARG(QString, str))); + QVERIFY(!method.invoke(this, Q_RETURN_ARG(QString, ret), Q_ARG(QString, str))); + QCOMPARE(str, QString("foo")); + QCOMPARE(ret, QString("bar")); + + + QtTestObject obj; + QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); + QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); + + int index = QtTestObject::staticMetaObject.indexOfMethod("sl5(QString,QString,QString,QString,QString)"); + QVERIFY(index > 0); + method = QtTestObject::staticMetaObject.method(index); + //wrong args + QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"))); + //QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"), Q_ARG(QString, "6"))); + //QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(int, 5))); + QVERIFY(!method.invoke(&obj, Q_RETURN_ARG(QString, ret), Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); + + //wrong object + //QVERIFY(!method.invoke(this, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); + QVERIFY(!method.invoke(0, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); + QCOMPARE(ret, QString("bar")); + QCOMPARE(obj.slotResult, QString()); + + QVERIFY(method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); + QCOMPARE(obj.slotResult, QString("sl5:12345")); + + index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QList)"); + QVERIFY(index > 0); + QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index); + QList returnValue, argument; + argument << QString("one") << QString("two") << QString("three"); + //wrong object + //QVERIFY(!sl13.invoke(this, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); + QVERIFY(!sl13.invoke(0, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); + QCOMPARE(returnValue, QList()); + + QVERIFY(sl13.invoke(&obj, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); + QCOMPARE(returnValue, argument); + QCOMPARE(obj.slotResult, QString("sl13")); +} + QTEST_MAIN(tst_QMetaObject) #include "tst_qmetaobject.moc" -- cgit v0.12 From 49a5cf7cd44584e04d1f54f3fbd0d5c86fe55c83 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 28 May 2010 11:49:20 +0200 Subject: QMetaMethod::invoke: Document that the function does not check the arguments And added an assert to ease debugging Task-number: QTBUG-10945 --- src/corelib/kernel/qmetaobject.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 4ad78fd..79a38cd 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1454,6 +1454,11 @@ QMetaMethod::MethodType QMetaMethod::methodType() const If the "compute" slot does not take exactly one QString, one int and one double in the specified order, the call will fail. + \warning this method will not test the validity of the arguments: \a object + must be an instance of the class of the QMetaObject of which this QMetaMethod + has been constructed with. The arguments must have the same type as the ones + expected by the method, else, the behaviour is undefined. + \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod() */ bool QMetaMethod::invoke(QObject *object, @@ -1473,6 +1478,8 @@ bool QMetaMethod::invoke(QObject *object, if (!object || !mobj) return false; + Q_ASSERT(mobj->cast(object)); + // check return type if (returnValue.data()) { const char *retType = typeName(); -- cgit v0.12 From fa7dfb24c2d165cad438eb28c83ac2fd60831b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 27 May 2010 16:07:46 +0200 Subject: Improve precision of testlib benchmarking. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 20 ms is a bit too to get a precise measurement due to limited timer resolution. We increase the limit to 50 ms and introduce a warm-up iteration to prevent any state or cache-related issues which can be hard to account for in the tests. On the N900 this seems to decrease the variance of test results by 30 %, and fixes some cases where the results were way off due to hidden state. Task-number: QT-3390 Reviewed-by: Morten Sørvig --- src/testlib/qbenchmarkmeasurement.cpp | 7 ++++++- src/testlib/qbenchmarkmeasurement_p.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/testlib/qbenchmarkmeasurement.cpp b/src/testlib/qbenchmarkmeasurement.cpp index c03cbff..0a84792 100644 --- a/src/testlib/qbenchmarkmeasurement.cpp +++ b/src/testlib/qbenchmarkmeasurement.cpp @@ -66,7 +66,7 @@ qint64 QBenchmarkTimeMeasurer::stop() bool QBenchmarkTimeMeasurer::isMeasurementAccepted(qint64 measurement) { - return (measurement > 20); + return (measurement > 50); } int QBenchmarkTimeMeasurer::adjustIterationCount(int suggestion) @@ -74,6 +74,11 @@ int QBenchmarkTimeMeasurer::adjustIterationCount(int suggestion) return suggestion; } +bool QBenchmarkTimeMeasurer::needsWarmupIteration() +{ + return true; +} + int QBenchmarkTimeMeasurer::adjustMedianCount(int) { return 1; diff --git a/src/testlib/qbenchmarkmeasurement_p.h b/src/testlib/qbenchmarkmeasurement_p.h index 8ad3613..932852c 100644 --- a/src/testlib/qbenchmarkmeasurement_p.h +++ b/src/testlib/qbenchmarkmeasurement_p.h @@ -84,6 +84,7 @@ public: bool isMeasurementAccepted(qint64 measurement); int adjustIterationCount(int sugestion); int adjustMedianCount(int suggestion); + bool needsWarmupIteration(); QTest::QBenchmarkMetric metricType(); private: QTime time; -- cgit v0.12 From 60c12264b0ff01bb4888323b3acda0bc581021a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 28 May 2010 11:55:47 +0200 Subject: Fixed bug where testlib would not respect the -iterations option. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Morten Sørvig --- src/testlib/qbenchmark.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testlib/qbenchmark.cpp b/src/testlib/qbenchmark.cpp index 23c5639..c88ecb0 100644 --- a/src/testlib/qbenchmark.cpp +++ b/src/testlib/qbenchmark.cpp @@ -159,7 +159,7 @@ void QBenchmarkTestMethodData::setResult( if (QBenchmarkGlobalData::current->iterationCount != -1) accepted = true; - if (QBenchmarkTestMethodData::current->runOnce || !setByMacro) { + else if (QBenchmarkTestMethodData::current->runOnce || !setByMacro) { iterationCount = 1; accepted = true; } -- cgit v0.12