summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qmetaobject.cpp7
-rw-r--r--src/opengl/qglbuffer.cpp92
-rw-r--r--src/opengl/qglbuffer.h9
-rw-r--r--src/testlib/qbenchmark.cpp2
-rw-r--r--src/testlib/qbenchmarkmeasurement.cpp7
-rw-r--r--src/testlib/qbenchmarkmeasurement_p.h1
-rw-r--r--tests/auto/qmetaobject/tst_qmetaobject.cpp51
7 files changed, 156 insertions, 13 deletions
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();
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 <QtOpenGL/qgl.h>
#include <QtOpenGL/private/qgl_p.h>
#include <QtOpenGL/private/qglextensions_p.h>
+#include <QtCore/qatomic.h>
#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<QGLBufferPrivate> d_ptr;
+ QGLBufferPrivate *d_ptr;
- Q_DISABLE_COPY(QGLBuffer)
Q_DECLARE_PRIVATE(QGLBuffer)
};
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;
}
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;
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<QString>)");
+ QVERIFY(index > 0);
+ QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index);
+ QList<QString> returnValue, argument;
+ argument << QString("one") << QString("two") << QString("three");
+ //wrong object
+ //QVERIFY(!sl13.invoke(this, Q_RETURN_ARG(QList<QString>, returnValue), Q_ARG(QList<QString>, argument)));
+ QVERIFY(!sl13.invoke(0, Q_RETURN_ARG(QList<QString>, returnValue), Q_ARG(QList<QString>, argument)));
+ QCOMPARE(returnValue, QList<QString>());
+
+ QVERIFY(sl13.invoke(&obj, Q_RETURN_ARG(QList<QString>, returnValue), Q_ARG(QList<QString>, argument)));
+ QCOMPARE(returnValue, argument);
+ QCOMPARE(obj.slotResult, QString("sl13"));
+}
+
QTEST_MAIN(tst_QMetaObject)
#include "tst_qmetaobject.moc"