diff options
| author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-08-25 11:19:38 (GMT) |
|---|---|---|
| committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-08-25 11:19:38 (GMT) |
| commit | bf6b698cb0f2f21a714a33852981ee121cb87cb3 (patch) | |
| tree | 7ef6eef12e858c74d776dd7e6b92276604da9bee | |
| parent | 5c45c66b1743645b77826ad61508a79eadd48414 (diff) | |
| parent | d585ece2e2e71b49db9500a50211127f75256154 (diff) | |
| download | Qt-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.cpp | 9 | ||||
| -rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 5 | ||||
| -rw-r--r-- | src/gui/painting/qpainter.cpp | 9 | ||||
| -rw-r--r-- | src/opengl/qgl.cpp | 5 | ||||
| -rw-r--r-- | src/opengl/qgl_x11egl.cpp | 3 | ||||
| -rw-r--r-- | tests/auto/qfuturewatcher/tst_qfuturewatcher.cpp | 33 | ||||
| -rw-r--r-- | tests/auto/qglthreads/tst_qglthreads.cpp | 169 | ||||
| -rw-r--r-- | tests/auto/qglthreads/tst_qglthreads.h | 2 |
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 |
