diff options
-rwxr-xr-x | configure | 23 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_unix.cpp | 5 | ||||
-rw-r--r-- | src/corelib/thread/qthread.cpp | 15 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 13 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp | 3 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h | 3 | ||||
-rw-r--r-- | src/plugins/graphicssystems/meego/qmeegographicssystem.cpp | 8 | ||||
-rw-r--r-- | tests/auto/qmutex/tst_qmutex.cpp | 38 | ||||
-rw-r--r-- | tests/auto/qthread/tst_qthread.cpp | 191 |
9 files changed, 143 insertions, 156 deletions
@@ -6056,19 +6056,28 @@ if [ "$PLATFORM_QWS" = "yes" ]; then fi # QWS +EGL_VARIANT=none # EGL Support if [ "$PLATFORM_X11" = "yes" -o "$PLATFORM_QWS" = "yes" ]; then if [ "$CFG_EGL" != "no" ]; then # detect EGL support - if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl4gles1" "EGL (GLES/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then - # EGL specified by QMAKE_*_EGL, included with <GLES/egl.h> - CFG_EGL=yes - CFG_EGL_GLES_INCLUDES=yes - elif "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl" "EGL (EGL/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl" "EGL (EGL/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then # EGL specified by QMAKE_*_EGL, included with <EGL/egl.h> + EGL_VARIANT=regular CFG_EGL=yes - CFG_EGL_GLES_INCLUDES=no - else + fi + + # Prefer this variant for ES1 + if [ "$CFG_OPENGL" = "es1" -o "$EGL_VARIANT" = "none" ]; then + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl4gles1" "EGL (GLES/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then + # EGL specified by QMAKE_*_EGL, included with <GLES/egl.h> + EGL_VARIANT=gles + CFG_EGL=yes + CFG_EGL_GLES_INCLUDES=yes + fi + fi + + if [ "$EGL_VARIANT" = "none" ]; then if [ "$CFG_EGL" = "yes" ]; then echo "The EGL functionality test failed!" echo " EGL is required for OpenGL ES to manage contexts & surfaces." diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 41d87a7..dd7e5d1 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -94,8 +94,11 @@ bool QMutexPrivate::wait(int timeout) errorCode = pthread_cond_timedwait(&cond, &mutex, &ti); } if (errorCode) { - if (errorCode == ETIMEDOUT) + if (errorCode == ETIMEDOUT) { + if (wakeup) + errorCode = 0; break; + } report_error(errorCode, "QMutex::lock()", "cv wait"); } } diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index f4bfa5d..8223cff 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -482,7 +482,10 @@ int QThread::exec() Q_D(QThread); QMutexLocker locker(&d->mutex); d->data->quitNow = false; - d->exited = false; + if (d->exited) { + d->exited = false; + return d->returnCode; + } locker.unlock(); QEventLoop eventLoop; @@ -506,10 +509,12 @@ int QThread::exec() Note that unlike the C library function of the same name, this function \e does return to the caller -- it is event processing - that stops. - - This function does nothing if the thread does not have an event - loop. + that stops. + + No QEventLoops will be started anymore in this thread until + QThread::exec() has been called again. If the eventloop in QThread::exec() + is not running then the next call to QThread::exec() will also return + immediately. \sa quit() QEventLoop */ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index ad2852e..cda31e5 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1489,7 +1489,7 @@ namespace { { public: QOpenGLStaticTextUserData() - : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0) + : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0), cacheSerialNumber(0) { } @@ -1501,6 +1501,7 @@ namespace { QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; QFontEngineGlyphCache::Type glyphType; + int cacheSerialNumber; }; } @@ -1518,12 +1519,10 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp QGLTextureGlyphCache *cache = (QGLTextureGlyphCache *) staticTextItem->fontEngine()->glyphCache(ctx, glyphType, QTransform()); - if (!cache || cache->cacheType() != glyphType) { + if (!cache || cache->cacheType() != glyphType || cache->context() == 0) { cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); staticTextItem->fontEngine()->setGlyphCache(ctx, cache); recreateVertexArrays = true; - } else if (cache->context() == 0) { // Old context has been destroyed, new context has same ptr value - cache->setContext(ctx); } if (staticTextItem->userDataNeedsUpdate) { @@ -1534,8 +1533,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp recreateVertexArrays = true; } else { QOpenGLStaticTextUserData *userData = static_cast<QOpenGLStaticTextUserData *>(staticTextItem->userData()); - if (userData->glyphType != glyphType) + if (userData->glyphType != glyphType) { recreateVertexArrays = true; + } else if (userData->cacheSerialNumber != cache->serialNumber()) { + recreateVertexArrays = true; + } } // We only need to update the cache with new glyphs if we are actually going to recreate the vertex arrays. @@ -1580,6 +1582,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp } userData->glyphType = glyphType; + userData->cacheSerialNumber = cache->serialNumber(); // Use cache if backend optimizations is turned on vertexCoordinates = &userData->vertexCoordinateArray; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 58c78ec..312d66f 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -52,12 +52,15 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT bool qt_cleartype_enabled; #endif +QBasicAtomicInt qgltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); + QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) : QImageTextureGlyphCache(type, matrix) , ctx(0) , m_width(0) , m_height(0) , m_filterMode(Nearest) + , m_serialNumber(qgltextureglyphcache_serial_number.fetchAndAddRelaxed(1)) { setContext(context); } diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 1c1b7c4..2eb4e65 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -83,6 +83,8 @@ public: inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } + inline int serialNumber() const { return m_serialNumber; } + enum FilterMode { Nearest, Linear @@ -140,6 +142,7 @@ private: QGLShaderProgram *m_program; FilterMode m_filterMode; + int m_serialNumber; }; QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index 20b092e..a70d232 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -42,6 +42,7 @@ #include <QDebug> #include <private/qpixmap_raster_p.h> #include <private/qwindowsurface_gl_p.h> +#include <private/qwindowsurface_raster_p.h> #include <private/qegl_p.h> #include <private/qglextensions_p.h> #include <private/qgl_p.h> @@ -75,7 +76,12 @@ QMeeGoGraphicsSystem::~QMeeGoGraphicsSystem() QWindowSurface* QMeeGoGraphicsSystem::createWindowSurface(QWidget *widget) const { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLWidget *shareWidget = qt_gl_share_widget(); + + if (!shareWidget) + return new QRasterWindowSurface(widget); + + QGLShareContextScope ctx(shareWidget->context()); QMeeGoGraphicsSystem::surfaceWasCreated = true; QWindowSurface *surface = new QGLWindowSurface(widget); diff --git a/tests/auto/qmutex/tst_qmutex.cpp b/tests/auto/qmutex/tst_qmutex.cpp index 3c4c767..ea983cb 100644 --- a/tests/auto/qmutex/tst_qmutex.cpp +++ b/tests/auto/qmutex/tst_qmutex.cpp @@ -67,6 +67,7 @@ private slots: void lock_unlock_locked_tryLock(); void stressTest(); void tryLockRace(); + void qtbug16115_trylock(); }; static const int iterations = 100; @@ -464,5 +465,42 @@ void tst_QMutex::tryLockRace() TryLockRaceThread::mutex.unlock(); } +static volatile int qtbug16115_trylock_counter; + +void tst_QMutex::qtbug16115_trylock() +{ + //Used to deadlock on unix + struct TrylockThread : QThread { + TrylockThread(QMutex &mut) : mut(mut) {} + QMutex &mut; + void run() { + for (int i = 0; i < 1000000; ++i) { + if (mut.tryLock(0)) { + Q_ASSERT((++qtbug16115_trylock_counter) == 1); + Q_ASSERT((--qtbug16115_trylock_counter) == 0); + mut.unlock(); + } + } + } + }; + QMutex mut; + TrylockThread t1(mut); + TrylockThread t2(mut); + TrylockThread t3(mut); + t1.start(); + t2.start(); + t3.start(); + + for (int i = 0; i < 1000000; ++i) { + mut.lock(); + Q_ASSERT((++qtbug16115_trylock_counter) == 1); + Q_ASSERT((--qtbug16115_trylock_counter) == 0); + mut.unlock(); + } + t1.wait(); + t2.wait(); + t3.wait(); +} + QTEST_MAIN(tst_QMutex) #include "tst_qmutex.moc" diff --git a/tests/auto/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp index c7036e4..e6bf9ce 100644 --- a/tests/auto/qthread/tst_qthread.cpp +++ b/tests/auto/qthread/tst_qthread.cpp @@ -86,7 +86,6 @@ private slots: void start(); void terminate(); void quit(); - void execAfterQuit(); void wait(); void started(); void finished(); @@ -266,34 +265,6 @@ public: } }; -class ExecAfterQuitThreadHelper: public QObject -{ - Q_OBJECT - QThread *thr; -public: - ExecAfterQuitThreadHelper(QThread *thr) : thr(thr) {} -public slots: - void doIt() { thr->exit(0); } -}; - -class ExecAfterQuitThread: public QThread -{ -public: - int returnValue; - void run() - { - ExecAfterQuitThreadHelper obj(this); - - QMetaObject::invokeMethod(&obj, "doIt", Qt::QueuedConnection); - exit(1); - - // returnValue will be either 0 or 1, depending on which of the two - // above take effect. The correct value is 0, since exit(1) before - // exec() should have no effect - returnValue = exec(); - } -}; - tst_QThread::tst_QThread() { @@ -453,52 +424,34 @@ void tst_QThread::stackSize() void tst_QThread::exit() { - { - Exit_Thread thread; - thread.object = new Exit_Object; - thread.object->moveToThread(&thread); - thread.code = 42; - thread.result = 0; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - // but the thread is not running the event loop yet (the mutex is locked) - - // start the event loop - thread.cond.wait(locker.mutex()); - - // the Exit_Object above will cause the thread to exit - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - QCOMPARE(thread.result, thread.code); - delete thread.object; - } + Exit_Thread thread; + thread.object = new Exit_Object; + thread.object->moveToThread(&thread); + thread.code = 42; + thread.result = 0; + QVERIFY(!thread.isFinished()); + QVERIFY(!thread.isRunning()); + QMutexLocker locker(&thread.mutex); + thread.start(); + QVERIFY(thread.isRunning()); + QVERIFY(!thread.isFinished()); + thread.cond.wait(locker.mutex()); + QVERIFY(thread.wait(five_minutes)); + QVERIFY(thread.isFinished()); + QVERIFY(!thread.isRunning()); + QCOMPARE(thread.result, thread.code); + delete thread.object; - { - Exit_Thread thread2; - thread2.object = 0; - thread2.code = 53; - thread2.result = 0; - QMutexLocker locker2(&thread2.mutex); - thread2.start(); - - // the mutex is locked, so the thread has *not* started running the event loop yet - // this will do nothing: - thread2.exit(thread2.code); - - // the thread will now start running - thread2.cond.wait(locker2.mutex()); - - // this will cause it to exit now - thread2.exit(++thread2.code); - QVERIFY(thread2.wait(five_minutes)); - QCOMPARE(thread2.result, thread2.code); - } + Exit_Thread thread2; + thread2.object = 0; + thread2.code = 53; + thread2.result = 0; + QMutexLocker locker2(&thread2.mutex); + thread2.start(); + thread2.exit(thread2.code); + thread2.cond.wait(locker2.mutex()); + QVERIFY(thread2.wait(five_minutes)); + QCOMPARE(thread2.result, thread2.code); } void tst_QThread::start() @@ -545,59 +498,32 @@ void tst_QThread::terminate() void tst_QThread::quit() { - // very similar to exit() above - { - Quit_Thread thread; - thread.object = new Quit_Object; - thread.object->moveToThread(&thread); - thread.result = -1; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - - // start the thread, but keep the event loop from starting - // (while the mutex is locked) - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - - // unlock the mutex and let the event loop run - // the Quit_Object above will cause the thread to quit - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - QCOMPARE(thread.result, 0); - delete thread.object; - } - - { - Quit_Thread thread2; - thread2.object = 0; - thread2.result = -1; - - // start the thread, but keep the event loop from starting - // (while the mutex is locked) - QMutexLocker locker2(&thread2.mutex); - thread2.start(); - thread2.quit(); // does nothing, the event loop is not running! - - // unlock the mutex and let the event loop run - thread2.cond.wait(locker2.mutex()); - - // there's no Quit_Object so it won't quit on its own - thread2.quit(); - QVERIFY(thread2.wait(five_minutes)); - QCOMPARE(thread2.result, 0); - } -} - -void tst_QThread::execAfterQuit() -{ - ExecAfterQuitThread thread; + Quit_Thread thread; + thread.object = new Quit_Object; + thread.object->moveToThread(&thread); + thread.result = -1; + QVERIFY(!thread.isFinished()); + QVERIFY(!thread.isRunning()); + QMutexLocker locker(&thread.mutex); thread.start(); - QVERIFY(thread.wait()); - QCOMPARE(thread.returnValue, 0); + QVERIFY(thread.isRunning()); + QVERIFY(!thread.isFinished()); + thread.cond.wait(locker.mutex()); + QVERIFY(thread.wait(five_minutes)); + QVERIFY(thread.isFinished()); + QVERIFY(!thread.isRunning()); + QCOMPARE(thread.result, 0); + delete thread.object; + + Quit_Thread thread2; + thread2.object = 0; + thread2.result = -1; + QMutexLocker locker2(&thread2.mutex); + thread2.start(); + thread2.quit(); + thread2.cond.wait(locker2.mutex()); + QVERIFY(thread2.wait(five_minutes)); + QCOMPARE(thread2.result, 0); } void tst_QThread::wait() @@ -1068,17 +994,8 @@ void tst_QThread::QTBUG15378_exitAndExec() Thread thread; thread.value = 0; thread.start(); - thread.exit(42); // will do nothing, this value should not appear - thread.sem1.release(); //should enter the first loop - - Exit_Object *exit_object = new Exit_Object; - exit_object->code = 556; - exit_object->thread = &thread; - QMetaObject::invokeMethod(exit_object, "slot", Qt::QueuedConnection); - exit_object->deleteLater(); - exit_object->moveToThread(&thread); // should exit the first loop - exit_object = 0; - + thread.exit(556); + thread.sem1.release(); //should exit the first loop thread.sem2.acquire(); int v = thread.value; QCOMPARE(v, 556); |