summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-08-25 11:19:38 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-08-25 11:19:38 (GMT)
commitbf6b698cb0f2f21a714a33852981ee121cb87cb3 (patch)
tree7ef6eef12e858c74d776dd7e6b92276604da9bee
parent5c45c66b1743645b77826ad61508a79eadd48414 (diff)
parentd585ece2e2e71b49db9500a50211127f75256154 (diff)
downloadQt-bf6b698cb0f2f21a714a33852981ee121cb87cb3.zip
Qt-bf6b698cb0f2f21a714a33852981ee121cb87cb3.tar.gz
Qt-bf6b698cb0f2f21a714a33852981ee121cb87cb3.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-2: qdrawhelper: fix assert in fetchTransformedBilinear Stabilize tst_QFutureWatcher::warnRace (second attempt) Call eglReleaseThread() when a thread exits, and fix warnings. Add a couple of GL thread tests. Stabilize tst_QFutureWatcher::warnRace QFutureWatcher: display a warning when connecting after calling setFuture() Fix tabArray support for boundingRect measurement
-rw-r--r--src/corelib/concurrent/qfuturewatcher.cpp9
-rw-r--r--src/gui/painting/qdrawhelper.cpp5
-rw-r--r--src/gui/painting/qpainter.cpp9
-rw-r--r--src/opengl/qgl.cpp5
-rw-r--r--src/opengl/qgl_x11egl.cpp3
-rw-r--r--tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp33
-rw-r--r--tests/auto/qglthreads/tst_qglthreads.cpp169
-rw-r--r--tests/auto/qglthreads/tst_qglthreads.h2
8 files changed, 220 insertions, 15 deletions
diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp
index d4573c6..21b0789 100644
--- a/src/corelib/concurrent/qfuturewatcher.cpp
+++ b/src/corelib/concurrent/qfuturewatcher.cpp
@@ -359,6 +359,15 @@ void QFutureWatcherBase::connectNotify(const char * signal)
Q_D(QFutureWatcherBase);
if (qstrcmp(signal, SIGNAL(resultReadyAt(int))) == 0)
d->resultAtConnected.ref();
+#ifndef QT_NO_DEBUG
+ if (qstrcmp(signal, SIGNAL(finished())) == 0) {
+ if (futureInterface().isRunning()) {
+ //connections should be established before calling stFuture to avoid race.
+ // (The future could finish before the connection is made.)
+ qWarning("QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race");
+ }
+ }
+#endif
}
void QFutureWatcherBase::disconnectNotify(const char * signal)
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 054f96f..2184fef 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -747,7 +747,6 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
if (fdx <= fixed_scale && fdx > 0) { // scale up on X
int disty = (fy & 0x0000ffff) >> 8;
int idisty = 256 - disty;
- int count = length * data->m11 + 2;
int x = fx >> 16;
// The idea is first to do the interpolation between the row s1 and the row s2
@@ -756,7 +755,9 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
// intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB
// intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG
quint32 intermediate_buffer[2][buffer_size + 2];
- Q_ASSERT(length * data->m11 <= buffer_size);
+ // count is the size used in the intermediate_buffer.
+ int count = qCeil(length * data->m11) + 2; //+1 for the last pixel to interpolate with, and +1 for rounding errors.
+ Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case
int f = 0;
int lim = count;
if (blendType == BlendTransformedBilinearTiled) {
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 314f349..c0f195a 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -7997,7 +7997,7 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
}
void qt_format_text(const QFont &fnt, const QRectF &_r,
int tf, const QTextOption *option, const QString& str, QRectF *brect,
- int tabstops, int *, int tabarraylen,
+ int tabstops, int *ta, int tabarraylen,
QPainter *painter)
{
@@ -8120,6 +8120,13 @@ start_lengthVariant:
if (engine.option.tabStop() < 0 && tabstops > 0)
engine.option.setTabStop(tabstops);
+ if (engine.option.tabs().isEmpty() && ta) {
+ QList<qreal> tabs;
+ for (int i = 0; i < tabarraylen; i++)
+ tabs.append(qreal(ta[i]));
+ engine.option.setTabArray(tabs);
+ }
+
engine.option.setTextDirection(layout_direction);
if (tf & Qt::AlignJustify)
engine.option.setAlignment(Qt::AlignJustify);
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 71d42a5..d9ba100 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -107,6 +107,11 @@ extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
#endif
struct QGLThreadContext {
+#ifdef QT_OPENGL_ES
+ ~QGLThreadContext() {
+ eglReleaseThread();
+ }
+#endif
QGLContext *context;
};
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index 9d28de0..1f7e60a 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -97,7 +97,6 @@ QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
XVisualInfo visualInfo;
XVisualInfo *vi;
int numVisuals;
- EGLint id = 0;
visualInfo.visualid = QEgl::getCompatibleVisualId(config);
vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals);
@@ -346,7 +345,7 @@ void QGLWidgetPrivate::recreateEglSurface()
// old surface before re-creating a new one. Note: This should not be the case as the
// surface should be deleted before the old window id.
if (glcx->d_func()->eglSurface != EGL_NO_SURFACE && (currentId != eglSurfaceWindowId)) {
- qWarning("EGL surface for deleted window %x was not destroyed", eglSurfaceWindowId);
+ qWarning("EGL surface for deleted window %lx was not destroyed", eglSurfaceWindowId);
glcx->d_func()->destroyEglSurfaceForDevice();
}
diff --git a/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp
index c53c67a..c980d80 100644
--- a/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp
+++ b/tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp
@@ -47,6 +47,7 @@
#include <qfuturewatcher.h>
#include <qtconcurrentrun.h>
#include <qtconcurrentmap.h>
+#include "../../shared/util.h"
#ifndef QT_NO_CONCURRENT_TEST
#include <private/qfutureinterface_p.h>
@@ -81,6 +82,7 @@ private slots:
void incrementalMapResults();
void incrementalFilterResults();
void qfutureSynchornizer();
+ void warnRace();
};
QTEST_MAIN(tst_QFutureWatcher)
@@ -466,12 +468,12 @@ void tst_QFutureWatcher::toMuchProgress()
ProgressObject o;
QFutureWatcher<void> f;
- f.setFuture((new ProgressEmitterTask())->start());
QObject::connect(&f, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
#ifdef PRINT
QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(printProgress(int)));
#endif
QObject::connect(&f, SIGNAL(progressValueChanged(int)), &o, SLOT(registerProgress(int)));
+ f.setFuture((new ProgressEmitterTask())->start());
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
@@ -886,6 +888,35 @@ void tst_QFutureWatcher::qfutureSynchornizer()
QVERIFY(t.elapsed() < taskCount * 10);
}
+class DummyObject : public QObject {
+ Q_OBJECT
+public slots:
+ void dummySlot() {}
+public:
+ static void function(QMutex *m)
+ {
+ QMutexLocker lock(m);
+ }
+};
+
+void tst_QFutureWatcher::warnRace()
+{
+#ifndef QT_NO_DEBUG
+ QTest::ignoreMessage(QtWarningMsg, "QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race");
+#endif
+ QFutureWatcher<void> watcher;
+ DummyObject object;
+ QMutex mutex;
+ mutex.lock();
+
+ QFuture<void> future = QtConcurrent::run(DummyObject::function, &mutex);
+ watcher.setFuture(future);
+ QTRY_VERIFY(future.isStarted());
+ connect(&watcher, SIGNAL(finished()), &object, SLOT(dummySlot()));
+ mutex.unlock();
+ future.waitForFinished();
+}
+
#include "tst_qfuturewatcher.moc"
#else
diff --git a/tests/auto/qglthreads/tst_qglthreads.cpp b/tests/auto/qglthreads/tst_qglthreads.cpp
index cce3161..eb31e07 100644
--- a/tests/auto/qglthreads/tst_qglthreads.cpp
+++ b/tests/auto/qglthreads/tst_qglthreads.cpp
@@ -45,10 +45,6 @@
#include <QtOpenGL/QtOpenGL>
#include "tst_qglthreads.h"
-#ifdef Q_WS_X11
-#include <private/qt_x11_p.h>
-#endif
-
#define RUNNING_TIME 5000
tst_QGLThreads::tst_QGLThreads(QObject *parent)
@@ -56,8 +52,6 @@ tst_QGLThreads::tst_QGLThreads(QObject *parent)
{
}
-
-
/*
swapInThread
@@ -339,6 +333,7 @@ void renderAScene(int w, int h)
class ThreadSafeGLWidget : public QGLWidget
{
public:
+ ThreadSafeGLWidget(QWidget *parent = 0) : QGLWidget(parent) {}
void paintEvent(QPaintEvent *)
{
// ignored as we're anyway swapping as fast as we can
@@ -426,7 +421,7 @@ void tst_QGLThreads::renderInThread_data()
void tst_QGLThreads::renderInThread()
{
#ifdef Q_OS_MAC
- QSKIP("OpenGL threading tests are currently disabled on mac as they were causing reboots", SkipAll);
+ QSKIP("OpenGL threading tests are currently disabled on Mac as they were causing reboots", SkipAll);
#endif
QFETCH(bool, resize);
@@ -461,15 +456,171 @@ void tst_QGLThreads::renderInThread()
QVERIFY(!thread.failure);
}
+class ThreadPainter : public QObject
+{
+ Q_OBJECT
+public:
+ ThreadPainter(QPaintDevice *pd) : paintDevice(pd), fail(true) {
+ pixmap = QPixmap(40, 40);
+ pixmap.fill(Qt::green);
+ QPainter p(&pixmap);
+ p.drawLine(0, 0, 40, 40);
+ p.drawLine(0, 40, 40, 0);
+ }
+
+public slots:
+ void draw() {
+ bool beginFailed = false;
+ QTime time;
+ time.start();
+ int rotAngle = 10;
+ QSize s(paintDevice->width(), paintDevice->height());
+ while (time.elapsed() < RUNNING_TIME) {
+ QPainter p;
+ if (!p.begin(paintDevice)) {
+ beginFailed = true;
+ break;
+ }
+ p.translate(s.width()/2, s.height()/2);
+ p.rotate(rotAngle);
+ p.translate(-s.width()/2, -s.height()/2);
+ p.fillRect(0, 0, s.width(), s.height(), Qt::red);
+ QRect rect(QPoint(0, 0), s);
+ p.drawPixmap(10, 10, pixmap);
+ p.drawTiledPixmap(50, 50, 100, 100, pixmap);
+ p.drawText(rect.center(), "This is a piece of text");
+ p.end();
+ rotAngle += 2;
+#ifdef Q_WS_WIN
+ Sleep(20);
+#else
+ usleep(20 * 1000);
+#endif
+ }
+
+ fail = beginFailed;
+ QThread::currentThread()->quit();
+ }
+ bool failed() { return fail; }
+private:
+ QPixmap pixmap;
+ QPaintDevice *paintDevice;
+ bool fail;
+};
-int main(int argc, char **argv)
+class PainterThreads
+{
+public:
+ PainterThreads(int count, bool drawOnWidgets) : numThreads(count)
+ , useWidgets(drawOnWidgets)
+ {
+ for (int i=0; i<numThreads; ++i) {
+ if (useWidgets)
+ widgets.append(new ThreadSafeGLWidget);
+ else
+ pixmaps.append(new QPixmap(200, 200));
+ threads.append(new QThread);
+ if (useWidgets) {
+ painters.append(new ThreadPainter(widgets.at(i)));
+ widgets.at(i)->resize(150, 150);
+ widgets.at(i)->show();
+ QTest::qWaitForWindowShown(widgets.at(i));
+ widgets.at(i)->doneCurrent();
+ } else {
+ painters.append(new ThreadPainter(pixmaps.at(i)));
+ }
+ painters.at(i)->moveToThread(threads.at(i));
+ painters.at(i)->connect(threads.at(i), SIGNAL(started()), painters.at(i), SLOT(draw()));
+ }
+ }
+
+ ~PainterThreads() {
+ qDeleteAll(threads);
+ qDeleteAll(painters);
+ if (useWidgets)
+ qDeleteAll(widgets);
+ else
+ qDeleteAll(pixmaps);
+ }
+
+
+ void start() {
+ for (int i=0; i<numThreads; ++i)
+ threads.at(i)->start();
+ }
+
+ bool areRunning() {
+ bool running = false;
+ for (int i=0; i<numThreads; ++i){
+ if (threads.at(i)->isRunning())
+ running = true;
+ }
+
+ return running;
+ }
+
+ bool failed() {
+ for (int i=0; i<numThreads; ++i) {
+ if (painters.at(i)->failed())
+ return true;
+ }
+
+ return false;
+ }
+
+private:
+ QList<QThread *> threads;
+ QList<QPixmap *> pixmaps;
+ QList<ThreadSafeGLWidget *> widgets;
+ QList<ThreadPainter *> painters;
+ int numThreads;
+ bool useWidgets;
+};
+
+
+void tst_QGLThreads::painterOnGLWidgetInThread()
+{
+#ifdef Q_OS_MAC
+ QSKIP("OpenGL threading tests are currently disabled on Mac as they were causing reboots", SkipAll);
+#endif
+ PainterThreads threads(5, true);
+ threads.start();
+
+ while (threads.areRunning()) {
+ qApp->processEvents();
+#ifdef Q_WS_WIN
+ Sleep(100);
+#else
+ usleep(100 * 1000);
+#endif
+ }
+ QVERIFY(!threads.failed());
+}
+
+void tst_QGLThreads::painterOnPixmapInThread()
{
#ifdef Q_WS_X11
- XInitThreads();
+ QSKIP("Drawing text to XPixmaps in threads currently doesn't work.", SkipAll);
+#endif
+ PainterThreads threads(5, false);
+ threads.start();
+
+ while (threads.areRunning()) {
+ qApp->processEvents();
+#ifdef Q_WS_WIN
+ Sleep(100);
+#else
+ usleep(100 * 1000);
#endif
+ }
+ QVERIFY(!threads.failed());
+}
+int main(int argc, char **argv)
+{
+ QApplication::setAttribute(Qt::AA_X11InitThreads);
QApplication app(argc, argv);
QTEST_DISABLE_KEYPAD_NAVIGATION \
diff --git a/tests/auto/qglthreads/tst_qglthreads.h b/tests/auto/qglthreads/tst_qglthreads.h
index 9e97909..ae6b953 100644
--- a/tests/auto/qglthreads/tst_qglthreads.h
+++ b/tests/auto/qglthreads/tst_qglthreads.h
@@ -56,6 +56,8 @@ private slots:
void renderInThread_data();
void renderInThread();
+ void painterOnGLWidgetInThread();
+ void painterOnPixmapInThread();
};
#endif // TST_QGLTHREADS_H