diff options
37 files changed, 358 insertions, 311 deletions
diff --git a/src/3rdparty/libmng/libmng_object_prc.c b/src/3rdparty/libmng/libmng_object_prc.c index f6691ff..e1724b4 100644 --- a/src/3rdparty/libmng/libmng_object_prc.c +++ b/src/3rdparty/libmng/libmng_object_prc.c @@ -2876,7 +2876,6 @@ mng_retcode mng_create_ani_chrm (mng_datap pData, mng_chunkp pChunk) #endif { - mng_ptr pTemp; mng_ani_chrmp pCHRM; #ifdef MNG_SUPPORT_TRACE @@ -2886,6 +2885,7 @@ mng_retcode mng_create_ani_chrm (mng_datap pData, if (pData->bCacheplayback) /* caching playback info ? */ { #ifdef MNG_OPTIMIZE_OBJCLEANUP + mng_ptr pTemp; mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_chrm), mng_free_obj_general, mng_process_ani_chrm, @@ -3115,7 +3115,6 @@ mng_retcode mng_create_ani_iccp (mng_datap pData, mng_chunkp pChunk) #endif { - mng_ptr pTemp; mng_ani_iccpp pICCP; #ifdef MNG_SUPPORT_TRACE @@ -3125,6 +3124,7 @@ mng_retcode mng_create_ani_iccp (mng_datap pData, if (pData->bCacheplayback) /* caching playback info ? */ { #ifdef MNG_OPTIMIZE_OBJCLEANUP + mng_ptr pTemp; mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_iccp), mng_free_ani_iccp, mng_process_ani_iccp, @@ -3252,7 +3252,6 @@ mng_retcode mng_create_ani_bkgd (mng_datap pData, mng_retcode mng_create_ani_bkgd (mng_datap pData) #endif { - mng_ptr pTemp; mng_ani_bkgdp pBKGD; #ifdef MNG_SUPPORT_TRACE @@ -3262,6 +3261,7 @@ mng_retcode mng_create_ani_bkgd (mng_datap pData) if (pData->bCacheplayback) /* caching playback info ? */ { #ifdef MNG_OPTIMIZE_OBJCLEANUP + mng_ptr pTemp; mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_bkgd), mng_free_obj_general, mng_process_ani_bkgd, @@ -4918,7 +4918,6 @@ mng_retcode mng_process_ani_term (mng_datap pData, #ifndef MNG_SKIPCHUNK_SAVE mng_retcode mng_create_ani_save (mng_datap pData) { - mng_ptr pTemp; mng_ani_savep pSAVE; #ifdef MNG_SUPPORT_TRACE @@ -4928,6 +4927,7 @@ mng_retcode mng_create_ani_save (mng_datap pData) if (pData->bCacheplayback) /* caching playback info ? */ { #ifdef MNG_OPTIMIZE_OBJCLEANUP + mng_ptr pTemp; mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_save), mng_free_obj_general, mng_process_ani_save, @@ -5009,7 +5009,6 @@ mng_retcode mng_create_ani_seek (mng_datap pData, mng_chunkp pChunk) #endif { - mng_ptr pTemp; mng_ani_seekp pSEEK; #ifdef MNG_SUPPORT_TRACE @@ -5019,6 +5018,7 @@ mng_retcode mng_create_ani_seek (mng_datap pData, if (pData->bCacheplayback) /* caching playback info ? */ { #ifdef MNG_OPTIMIZE_OBJCLEANUP + mng_ptr pTemp; mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_seek), mng_free_ani_seek, mng_process_ani_seek, @@ -6106,7 +6106,7 @@ mng_retcode mng_create_ani_disc (mng_datap pData, #endif { mng_ani_discp pDISC; - mng_retcode iRetcode; + mng_retcode iRetcode; #ifdef MNG_SUPPORT_TRACE MNG_TRACE (pData, MNG_FN_CREATE_ANI_DISC, MNG_LC_START); diff --git a/src/3rdparty/libmng/libmng_prop_xs.c b/src/3rdparty/libmng/libmng_prop_xs.c index 88e416d..3849d51 100644 --- a/src/3rdparty/libmng/libmng_prop_xs.c +++ b/src/3rdparty/libmng/libmng_prop_xs.c @@ -1033,7 +1033,7 @@ mng_retcode MNG_DECL mng_set_jpeg_dctmethod (mng_handle hHandle, return MNG_NOERROR; } -#endif MNG_SUPPORT_WRITE +#endif /* MNG_SUPPORT_WRITE */ #endif /* MNG_ACCESS_JPEG */ #endif /* MNG_INCLUDE_JNG */ diff --git a/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp b/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp index 3af4a29..c538eb1 100644 --- a/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp @@ -586,13 +586,14 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV unsigned bytecodeOffsetTemp = bytecodeOffset; CodeBlock *codeBlockTemp = codeBlock; while (!(handler = codeBlockTemp->handlerForBytecodeOffset(bytecodeOffsetTemp))) { + void* returnPC = callFrameTemp->returnPC(); callFrameTemp = callFrameTemp->callerFrame(); if (callFrameTemp->hasHostCallFrameFlag()) { hasHandler = false; break; } else { codeBlockTemp = callFrameTemp->codeBlock(); - bytecodeOffsetTemp = bytecodeOffsetForPC(callFrameTemp, codeBlockTemp, callFrameTemp->returnPC()); + bytecodeOffsetTemp = bytecodeOffsetForPC(callFrameTemp, codeBlockTemp, returnPC); } } if (debugger) diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 580484b..e54bad6 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -565,7 +565,7 @@ QString QFSFileEngine::currentPath(const QString &) // try to create it (can happen with application private dirs) // Ignore mkdir failures; we want to be consistent with Open C // current path regardless. - QT_MKDIR(QFile::encodeName(nativeCurrentName), 0777); + QT_MKDIR(QFile::encodeName(QLatin1String(nativeCurrentName)), 0777); #else # if defined(QT_DEBUG) qWarning("QFSFileEngine::currentPath: stat(\".\") failed"); diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index de3e368..d93cdba 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -62,6 +62,7 @@ #include <stdio.h> #include "qplatformdefs.h" +#include "qdir.h" #include "qstring.h" #include "qprocess.h" #include "qprocess_p.h" @@ -261,8 +262,8 @@ static TInt qt_create_symbian_process(RProcess **proc, const QString &programNam if (err == KErrNotFound) { // Strip path from program name and try again (i.e. try from default location "\sys\bin") - int index = programName.lastIndexOf(QChar('\\')); - int index2 = programName.lastIndexOf(QChar('/')); + int index = programName.lastIndexOf(QDir::separator()); + int index2 = programName.lastIndexOf(QChar(QLatin1Char('/'))); index = qMax(index, index2); if (index != -1 && programName.length() >= index) { diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 36bd20e..3dbde3f 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2184,10 +2184,10 @@ QStringList QCoreApplication::libraryPaths() QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); #if defined(Q_OS_SYMBIAN) // Add existing path on all drives for relative PluginsPath in Symbian - if (installPathPlugins.at(1) != QChar(':')) { + if (installPathPlugins.at(1) != QChar(QLatin1Char(':'))) { QString tempPath = installPathPlugins; - if (tempPath.at(tempPath.length() - 1) != QChar('\\')) { - tempPath += QChar('\\'); + if (tempPath.at(tempPath.length() - 1) != QDir::separator()) { + tempPath += QDir::separator(); } RFs& fs = qt_s60GetRFs(); TPtrC tempPathPtr(reinterpret_cast<const TText*> (tempPath.constData())); diff --git a/src/corelib/tools/qlocale_symbian.cpp b/src/corelib/tools/qlocale_symbian.cpp index 9bd6ac0..931fbb4 100644 --- a/src/corelib/tools/qlocale_symbian.cpp +++ b/src/corelib/tools/qlocale_symbian.cpp @@ -797,7 +797,7 @@ QLocale QSystemLocale::fallbackLocale() const } TLanguage lang = User::Language(); - QString locale = qt_symbianLocaleName(lang); + QString locale = QLatin1String(qt_symbianLocaleName(lang)); return QLocale(locale); } @@ -853,7 +853,7 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const case LanguageId: case CountryId: { TLanguage language = User::Language(); - QString locale = qt_symbianLocaleName(language); + QString locale = QLatin1String(qt_symbianLocaleName(language)); QLocale::Language lang; QLocale::Country cntry; getLangAndCountry(locale, lang, cntry); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 4fc0aed..d67011b 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -934,7 +934,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } QGraphicsItem *lastSubFocusItem = subFocusItem; - if (subFocusItem && !inDestructor) { + if (subFocusItem) { // Update the child focus chain; when reparenting an item that has a // focus child, ensure that that focus child clears its focus child // chain from our parents before it's reparented. @@ -1226,6 +1226,8 @@ QGraphicsItem::~QGraphicsItem() Q_ASSERT(d_ptr->children.isEmpty()); } + d_ptr->subFocusItem = 0; + if (d_ptr->scene) { d_ptr->scene->d_func()->removeItemHelper(this); } else { diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index f7db819..b198ae1 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -213,7 +213,7 @@ void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event) QList<QInputMethodEvent::Attribute> attributes; attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos + x, 0, QVariant()); - QInputMethodEvent event("", attributes); + QInputMethodEvent event(QLatin1String(""), attributes); sendEvent(event); } } @@ -500,8 +500,8 @@ void QCoeFepInputContext::SetInlineEditingCursorVisibilityL(TBool aCursorVisibil void QCoeFepInputContext::CancelFepInlineEdit() { QList<QInputMethodEvent::Attribute> attributes; - QInputMethodEvent event("", attributes); - event.setCommitString("", 0, 0); + QInputMethodEvent event(QLatin1String(""), attributes); + event.setCommitString(QLatin1String(""), 0, 0); m_preeditString.clear(); sendEvent(event); @@ -618,7 +618,7 @@ void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian) } QList<QInputMethodEvent::Attribute> attributes; - QInputMethodEvent event("", attributes); + QInputMethodEvent event(QLatin1String(""), attributes); event.setCommitString(m_preeditString, 0, 0);//m_preeditString.size()); m_preeditString.clear(); sendEvent(event); diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index 0600bd9..1038f74 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -1740,7 +1740,7 @@ struct QPaintBufferCacheEntry QVariant::Type type; quint64 cacheKey; }; -Q_DECLARE_METATYPE(QPaintBufferCacheEntry); +Q_DECLARE_METATYPE(QPaintBufferCacheEntry) QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 147b64c..2dcc20c 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7556,7 +7556,6 @@ start_lengthVariant: bool hasMoreLengthVariants = false; // compatible behaviour to the old implementation. Replace // tabs by spaces - bool has_tab = false; int old_offset = offset; for (; offset < text.length(); offset++) { QChar chr = text.at(offset); @@ -7572,7 +7571,6 @@ start_lengthVariant: } else if (!tabarraylen && !tabstops) { tabstops = qRound(fm.width(QLatin1Char('x'))*8); } - has_tab = true; } else if (chr == QChar(ushort(0x9c))) { // string with multiple length variants hasMoreLengthVariants = true; diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index af7d37e..4fdf48b 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -117,7 +117,7 @@ private: static void checkAndUnCompressBitmap(CFbsBitmap*& aOriginalBitmap); static void unCompressBitmapL(const TRect& aTrgRect, CFbsBitmap* aTrgBitmap, CFbsBitmap* aSrcBitmap); static void colorGroupAndIndex(QS60StyleEnums::SkinParts skinID, - TAknsItemID &colorGroup, int colorIndex); + TAknsItemID &colorGroup, int &colorIndex); static void fallbackInfo(const QS60StyleEnums::SkinParts &stylepart, TDes& fallbackFileName, TInt& fallbackIndex); static bool checkSupport(const int supportedRelease); static TAknsItemID checkAndUpdateReleaseSpecificGraphics(int part); @@ -1016,7 +1016,7 @@ QS60StylePrivate::QS60StylePrivate() void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVariant &value) { - if (name == QLatin1String("foo")) { + if (QLatin1String(name) == QLatin1String("foo")) { // BaR } else { setStyleProperty(name, value); @@ -1025,7 +1025,7 @@ void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVarian QVariant QS60StylePrivate::styleProperty_specific(const char *name) const { - if (name == QLatin1String("foo")) + if (QLatin1String(name) == QLatin1String("foo")) return QLatin1String("Bar"); else return styleProperty(name); @@ -1331,7 +1331,7 @@ QSize QS60StylePrivate::screenSize() } void QS60StyleModeSpecifics::colorGroupAndIndex( - QS60StyleEnums::SkinParts skinID, TAknsItemID &colorGroup, int colorIndex) + QS60StyleEnums::SkinParts skinID, TAknsItemID &colorGroup, int &colorIndex) { switch(skinID) { case QS60StyleEnums::SP_QgnIndiSubMenu: diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 419aef1..742b5b0 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -1770,8 +1770,6 @@ case PE_FrameDockWidget: #endif // QT_NO_PROGRESSBAR case PE_FrameTabWidget: { - QRect rect = opt->rect; - QPalette pal = opt->palette; qDrawWinButton(p, opt->rect, opt->palette, false, 0); break; } diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index 20361f9..dd0fcb4 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -66,7 +66,7 @@ QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameF foreach (const QFileInfo &drive, QDir::drives()) driveStrings.append(drive.absolutePath()); driveStrings.sort(); - const QString zDriveString("Z:/"); + const QString zDriveString(QLatin1String("Z:/")); driveStrings.removeAll(zDriveString); driveStrings.prepend(zDriveString); diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp index a0e2ec7..b78e51b 100644 --- a/src/gui/util/qdesktopservices_s60.cpp +++ b/src/gui/util/qdesktopservices_s60.cpp @@ -101,17 +101,17 @@ static void handleMailtoSchemeLX(const QUrl &url) // this function has many intermingled leaves and throws. Qt and Symbian objects do not have // destructor dependencies, and cleanup object is used to prevent cleanup stack dependency on stack. QString recipient = url.path(); - QString subject = url.queryItemValue("subject"); - QString body = url.queryItemValue("body"); - QString to = url.queryItemValue("to"); - QString cc = url.queryItemValue("cc"); - QString bcc = url.queryItemValue("bcc"); + QString subject = url.queryItemValue(QLatin1String("subject")); + QString body = url.queryItemValue(QLatin1String("body")); + QString to = url.queryItemValue(QLatin1String("to")); + QString cc = url.queryItemValue(QLatin1String("cc")); + QString bcc = url.queryItemValue(QLatin1String("bcc")); // these fields might have comma separated addresses - QStringList recipients = recipient.split(",", QString::SkipEmptyParts); - QStringList tos = to.split(",", QString::SkipEmptyParts); - QStringList ccs = cc.split(",", QString::SkipEmptyParts); - QStringList bccs = bcc.split(",", QString::SkipEmptyParts); + QStringList recipients = recipient.split(QLatin1String(","), QString::SkipEmptyParts); + QStringList tos = to.split(QLatin1String(","), QString::SkipEmptyParts); + QStringList ccs = cc.split(QLatin1String(","), QString::SkipEmptyParts); + QStringList bccs = bcc.split(QLatin1String(","), QString::SkipEmptyParts); RSendAs sendAs; @@ -200,7 +200,7 @@ static void handleOtherSchemesL(const TDesC& aUrl) static bool handleOtherSchemes(const QUrl &url) { - QString encUrl(url.toEncoded()); + QString encUrl(QString::fromUtf8(url.toEncoded())); TPtrC urlPtr(qt_QString2TPtrC(encUrl)); TRAPD( err, handleOtherSchemesL(urlPtr)); return err ? false : true; diff --git a/src/multimedia/audio/qaudioinput.h b/src/multimedia/audio/qaudioinput.h index 3e0b354..277a6cf 100644 --- a/src/multimedia/audio/qaudioinput.h +++ b/src/multimedia/audio/qaudioinput.h @@ -96,7 +96,7 @@ Q_SIGNALS: void notify(); private: - Q_DISABLE_COPY(QAudioInput); + Q_DISABLE_COPY(QAudioInput) QAbstractAudioInput* d; }; diff --git a/src/multimedia/video/qvideosurfaceformat.h b/src/multimedia/video/qvideosurfaceformat.h index 8e93067..b3005bd 100644 --- a/src/multimedia/video/qvideosurfaceformat.h +++ b/src/multimedia/video/qvideosurfaceformat.h @@ -147,7 +147,7 @@ Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, const QVideoSurfaceFormat &); QT_END_NAMESPACE -Q_DECLARE_METATYPE(QVideoSurfaceFormat::FrameRate); +Q_DECLARE_METATYPE(QVideoSurfaceFormat::FrameRate) Q_DECLARE_METATYPE(QVideoSurfaceFormat::Direction) Q_DECLARE_METATYPE(QVideoSurfaceFormat::YuvColorSpace) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index e88b7d9..799c749 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1360,6 +1360,9 @@ bool operator!=(const QGLFormat& a, const QGLFormat& b) *****************************************************************************/ QGLContextPrivate::~QGLContextPrivate() { + if (!reference->deref()) + delete reference; + if (!group->m_refs.deref()) { Q_ASSERT(group->context() == q_ptr); delete group; @@ -5007,4 +5010,30 @@ void QGLContextResource::removeOne(const QGLContext *key) m_resources.erase(it); } +QGLContextReference::QGLContextReference(const QGLContext *ctx) + : m_ref(1), m_ctx(ctx) +{ + connect(QGLSignalProxy::instance(), + SIGNAL(aboutToDestroyContext(const QGLContext *)), + this, SLOT(aboutToDestroyContext(const QGLContext *))); +} + +void QGLContextReference::aboutToDestroyContext(const QGLContext *ctx) +{ + // Bail out if our context is not being destroyed. + if (ctx != m_ctx || !m_ctx) + return; + + // Find some other context that this one is shared with to take over. + QList<const QGLContext *> shares = qgl_share_reg()->shares(m_ctx); + shares.removeAll(m_ctx); + if (!shares.isEmpty()) { + m_ctx = shares[0]; + return; + } + + // No more contexts sharing with this one, so the reference is now invalid. + m_ctx = 0; +} + QT_END_NAMESPACE diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index 99f3823..1776004 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -396,6 +396,7 @@ private: friend class QGLPixmapFilterBase; friend class QGLTextureGlyphCache; friend class QGLShareRegister; + friend class QGLSharedResourceGuard; friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags(); #ifdef Q_WS_MAC public: diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index c8338d0..fdd28a4 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -237,13 +237,37 @@ private: friend class QGLContextPrivate; }; +// Reference to a QGLContext which automatically switches to another +// shared context when the main one is destroyed. If there is no +// shared context to switch to, the context pointer is set to null. +// Note: should be merged into QGLContextGroup at some point. +class QGLContextReference : public QObject +{ + Q_OBJECT +public: + QGLContextReference(const QGLContext *ctx); + ~QGLContextReference() {} + + const QGLContext *context() const { return m_ctx; } + + void ref() { m_ref.ref(); } + bool deref() { return m_ref.deref(); } + +private slots: + void aboutToDestroyContext(const QGLContext *ctx); + +private: + QAtomicInt m_ref; + const QGLContext *m_ctx; +}; + class QGLTexture; class QGLContextPrivate { Q_DECLARE_PUBLIC(QGLContext) public: - explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);} + explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {reference = new QGLContextReference(context); group = new QGLContextGroup(context);} ~QGLContextPrivate(); QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options); @@ -305,6 +329,7 @@ public: QGLContext *q_ptr; QGLFormat::OpenGLVersionFlags version_flags; + QGLContextReference *reference; QGLContextGroup *group; GLint max_texture_size; @@ -554,6 +579,65 @@ private: QGLContext *m_ctx; }; +// Put a guard around a GL object identifier and its context. +// When the context goes away, a shared context will be used +// in its place. If there are no more shared contexts, then +// the identifier is returned as zero - it is assumed that the +// context destruction cleaned up the identifier in this case. +class Q_OPENGL_EXPORT QGLSharedResourceGuard +{ +public: + QGLSharedResourceGuard(const QGLContext *context) + : m_ctxref(0), m_id(0) + { + setContext(context); + } + QGLSharedResourceGuard(const QGLContext *context, GLuint id) + : m_ctxref(0), m_id(id) + { + setContext(context); + } + ~QGLSharedResourceGuard() + { + if (m_ctxref && !m_ctxref->deref()) + delete m_ctxref; + } + + const QGLContext *context() const + { + return m_ctxref ? m_ctxref->context() : 0; + } + + void setContext(const QGLContext *context) + { + if (m_ctxref && !m_ctxref->deref()) + delete m_ctxref; + if (context) { + m_ctxref = context->d_ptr->reference; + m_ctxref->ref(); + } else { + m_ctxref = 0; + } + } + + GLuint id() const + { + if (m_ctxref && m_ctxref->context()) + return m_id; + else + return 0; + } + + void setId(GLuint id) + { + m_id = id; + } + +private: + QGLContextReference *m_ctxref; + GLuint m_id; +}; + QT_END_NAMESPACE #endif // QGL_P_H diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index f14fa4d..094f675 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -382,7 +382,6 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, { QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext()); ctx = QGLContextPrivate::contextGroup(currentContext); - glDevice.setFBO(q); bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject); if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(currentContext))) @@ -644,7 +643,6 @@ QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target) : d_ptr(new QGLFramebufferObjectPrivate) { Q_D(QGLFramebufferObject); - d->glDevice.setFBO(this); d->init(this, size, NoAttachment, target, DEFAULT_FORMAT); } @@ -654,7 +652,7 @@ QGLFramebufferObject::QGLFramebufferObject(const QSize &size, QMacCompatGLenum t : d_ptr(new QGLFramebufferObjectPrivate) { Q_D(QGLFramebufferObject); - d->init(size, NoAttachment, target, DEFAULT_FORMAT); + d->init(this, size, NoAttachment, target, DEFAULT_FORMAT); } #endif diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 4a910ee..0b7fe87 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -246,18 +246,11 @@ QT_BEGIN_NAMESPACE #define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 #endif -inline bool qt_check_sharing_with_current_context(QGLContextGroup *group) -{ - const QGLContext *context = QGLContext::currentContext(); - return context && QGLContextPrivate::contextGroup(context) == group; -} - class QGLShaderPrivate { public: - QGLShaderPrivate(QGLShader::ShaderType type) - : ctx(0) - , shader(0) + QGLShaderPrivate(const QGLContext *context, QGLShader::ShaderType type) + : shaderGuard(context) , shaderType(type) , compiled(false) , isPartial((type & QGLShader::PartialShader) != 0) @@ -265,8 +258,7 @@ public: { } - QGLContextGroup *ctx; - GLuint shader; + QGLSharedResourceGuard shaderGuard; QGLShader::ShaderType shaderType; bool compiled; bool isPartial; @@ -274,20 +266,22 @@ public: QString log; QByteArray partialSource; - bool create(const QGLContext *context); + bool create(); bool compile(QGLShader *q); + void deleteShader(); }; -bool QGLShaderPrivate::create(const QGLContext *context) +#define ctx shaderGuard.context() + +bool QGLShaderPrivate::create() { - if (!context) - context = QGLContext::currentContext(); + const QGLContext *context = shaderGuard.context(); if (!context) return false; - ctx = QGLContextPrivate::contextGroup(context); if (isPartial) return true; if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) { + GLuint shader; if (shaderType == QGLShader::VertexShader) shader = glCreateShader(GL_VERTEX_SHADER); else @@ -296,6 +290,7 @@ bool QGLShaderPrivate::create(const QGLContext *context) qWarning() << "QGLShader: could not create shader"; return false; } + shaderGuard.setId(shader); return true; } else { return false; @@ -309,6 +304,7 @@ bool QGLShaderPrivate::compile(QGLShader *q) compiled = true; return true; } + GLuint shader = shaderGuard.id(); if (!shader) return false; glCompileShader(shader); @@ -332,6 +328,17 @@ bool QGLShaderPrivate::compile(QGLShader *q) return compiled; } +void QGLShaderPrivate::deleteShader() +{ + if (shaderGuard.id()) { + glDeleteShader(shaderGuard.id()); + shaderGuard.setId(0); + } +} + +#undef ctx +#define ctx d->shaderGuard.context() + /*! Constructs a new QGLShader object of the specified \a type and attaches it to \a parent. If shader programs are not supported, @@ -347,8 +354,8 @@ bool QGLShaderPrivate::compile(QGLShader *q) QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent) : QObject(parent) { - d = new QGLShaderPrivate(type); - d->create(QGLContext::currentContext()); + d = new QGLShaderPrivate(QGLContext::currentContext(), type); + d->create(); } /*! @@ -364,14 +371,9 @@ QGLShader::QGLShader (const QString& fileName, QGLShader::ShaderType type, QObject *parent) : QObject(parent) { - d = new QGLShaderPrivate(type); - if (d->create(QGLContext::currentContext()) && !compileFile(fileName)) { - if (d->shader) { - QGLContextGroup *ctx = d->ctx; - glDeleteShader(d->shader); - } - d->shader = 0; - } + d = new QGLShaderPrivate(QGLContext::currentContext(), type); + if (d->create() && !compileFile(fileName)) + d->deleteShader(); } /*! @@ -389,14 +391,16 @@ QGLShader::QGLShader QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent) : QObject(parent) { - d = new QGLShaderPrivate(type); + if (!context) + context = QGLContext::currentContext(); + d = new QGLShaderPrivate(context, type); #ifndef QT_NO_DEBUG if (context && !qgl_share_reg()->checkSharing(context, QGLContext::currentContext())) { qWarning("QGLShader::QGLShader: \'context\' must be the currect context or sharing with it."); return; } #endif - d->create(context); + d->create(); } /*! @@ -412,20 +416,17 @@ QGLShader::QGLShader (const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent) : QObject(parent) { - d = new QGLShaderPrivate(type); + if (!context) + context = QGLContext::currentContext(); + d = new QGLShaderPrivate(context, type); #ifndef QT_NO_DEBUG if (context && !qgl_share_reg()->checkSharing(context, QGLContext::currentContext())) { qWarning("QGLShader::QGLShader: \'context\' must be currect context or sharing with it."); return; } #endif - if (d->create(context) && !compileFile(fileName)) { - if (d->shader) { - QGLContextGroup *ctx = d->ctx; - glDeleteShader(d->shader); - } - d->shader = 0; - } + if (d->create() && !compileFile(fileName)) + d->deleteShader(); } /*! @@ -435,14 +436,9 @@ QGLShader::QGLShader */ QGLShader::~QGLShader() { - if (d->shader) { - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) - qWarning("QGLShader::~QGLShader: Shader is not associated with current context."); - else -#endif - glDeleteShader(d->shader); + if (d->shaderGuard.id()) { + QGLShareContextScope scope(d->shaderGuard.context()); + glDeleteShader(d->shaderGuard.id()); } delete d; } @@ -489,17 +485,11 @@ static const char redefineHighp[] = */ bool QGLShader::compile(const char *source) { -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(d->ctx)) { - qWarning("QGLShader::compile: Shader is not associated with current context."); - return false; - } -#endif if (d->isPartial) { d->partialSource = QByteArray(source); d->hasPartialSource = true; return d->compile(this); - } else if (d->shader) { + } else if (d->shaderGuard.id()) { QVarLengthArray<const char *> src; int headerLen = 0; while (source && source[headerLen] == '#') { @@ -529,8 +519,7 @@ bool QGLShader::compile(const char *source) src.append(redefineHighp); #endif src.append(source + headerLen); - QGLContextGroup *ctx = d->ctx; - glShaderSource(d->shader, src.size(), src.data(), 0); + glShaderSource(d->shaderGuard.id(), src.size(), src.data(), 0); return d->compile(this); } else { return false; @@ -612,22 +601,15 @@ bool QGLShader::compileFile(const QString& fileName) */ bool QGLShader::setShaderBinary(GLenum format, const void *binary, int length) { - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) { - qWarning("QGLShader::setShaderBinary: Shader is not associated with current context."); - return false; - } -#endif - #if !defined(QT_OPENGL_ES_2) if (!glShaderBinary) return false; #endif - if (d->isPartial || !d->shader) + GLuint shader = d->shaderGuard.id(); + if (d->isPartial || !shader) return false; glGetError(); // Clear error state. - glShaderBinary(1, &(d->shader), format, binary, length); + glShaderBinary(1, &shader, format, binary, length); d->compiled = (glGetError() == GL_NO_ERROR); return d->compiled; } @@ -652,26 +634,18 @@ bool QGLShader::setShaderBinary(GLenum format, const void *binary, int length) bool QGLShader::setShaderBinary (QGLShader& otherShader, GLenum format, const void *binary, int length) { - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) { - qWarning("QGLShader::setShaderBinary: Shader is not associated with current context."); - return false; - } -#endif - #if !defined(QT_OPENGL_ES_2) if (!glShaderBinary) return false; #endif - if (d->isPartial || !d->shader) + if (d->isPartial || !d->shaderGuard.id()) return false; - if (otherShader.d->isPartial || !otherShader.d->shader) + if (otherShader.d->isPartial || !otherShader.d->shaderGuard.id()) return false; glGetError(); // Clear error state. GLuint shaders[2]; - shaders[0] = d->shader; - shaders[1] = otherShader.d->shader; + shaders[0] = d->shaderGuard.id(); + shaders[1] = otherShader.d->shaderGuard.id(); glShaderBinary(2, shaders, format, binary, length); d->compiled = (glGetError() == GL_NO_ERROR); otherShader.d->compiled = d->compiled; @@ -706,25 +680,18 @@ QList<GLenum> QGLShader::shaderBinaryFormats() */ QByteArray QGLShader::sourceCode() const { -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(d->ctx)) { - qWarning("QGLShader::sourceCode: Shader is not associated with current context."); - return false; - } -#endif - if (d->isPartial) return d->partialSource; - if (!d->shader) + GLuint shader = d->shaderGuard.id(); + if (!shader) return QByteArray(); GLint size = 0; - QGLContextGroup *ctx = d->ctx; - glGetShaderiv(d->shader, GL_SHADER_SOURCE_LENGTH, &size); + glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &size); if (size <= 0) return QByteArray(); GLint len = 0; char *source = new char [size]; - glGetShaderSource(d->shader, size, &len, source); + glGetShaderSource(shader, size, &len, source); QByteArray src(source); delete [] source; return src; @@ -761,15 +728,17 @@ QString QGLShader::log() const */ GLuint QGLShader::shaderId() const { - return d->shader; + return d->shaderGuard.id(); } +#undef ctx +#define ctx programGuard.context() + class QGLShaderProgramPrivate { public: QGLShaderProgramPrivate(const QGLContext *context) - : ctx(context ? QGLContextPrivate::contextGroup(context) : 0) - , program(0) + : programGuard(context) , linked(false) , inited(false) , hasPartialShaders(false) @@ -780,8 +749,7 @@ public: } ~QGLShaderProgramPrivate(); - QGLContextGroup *ctx; - GLuint program; + QGLSharedResourceGuard programGuard; bool linked; bool inited; bool hasPartialShaders; @@ -795,16 +763,14 @@ public: QGLShaderProgramPrivate::~QGLShaderProgramPrivate() { - if (program) { -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) - qWarning("QGLShaderProgram: Shader program is not associated with current context."); - else -#endif - glDeleteProgram(program); + if (programGuard.id()) { + QGLShareContextScope scope(programGuard.context()); + glDeleteProgram(programGuard.id()); } } +#undef ctx +#define ctx d->programGuard.context() /*! Constructs a new shader program and attaches it to \a parent. @@ -844,27 +810,23 @@ QGLShaderProgram::~QGLShaderProgram() bool QGLShaderProgram::init() { - if (d->program || d->inited) + if (d->programGuard.id() || d->inited) return true; d->inited = true; - const QGLContext *context = QGLContext::currentContext(); + const QGLContext *context = d->programGuard.context(); + if (!context) { + context = QGLContext::currentContext(); + d->programGuard.setContext(context); + } if (!context) return false; - if (!d->ctx) - d->ctx = QGLContextPrivate::contextGroup(context); -#ifndef QT_NO_DEBUG - else if (!qt_check_sharing_with_current_context(d->ctx)) { - qWarning("QGLShaderProgram: Shader program is not associated with current context."); - return false; - } -#endif if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) { - QGLContextGroup *ctx = d->ctx; - d->program = glCreateProgram(); - if (!(d->program)) { + GLuint program = glCreateProgram(); + if (!program) { qWarning() << "QGLShaderProgram: could not create shader program"; return false; } + d->programGuard.setId(program); return true; } else { qWarning() << "QGLShaderProgram: shader programs are not supported"; @@ -889,24 +851,18 @@ bool QGLShaderProgram::addShader(QGLShader *shader) return false; if (d->shaders.contains(shader)) return true; // Already added to this shader program. - if (d->program && shader) { -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(d->ctx)) { - qWarning("QGLShaderProgram::addShader: Program is not associated with current context."); - return false; - } -#endif - if (shader->d->ctx != d->ctx) { + if (d->programGuard.id() && shader) { + if (!qgl_share_reg()->checkSharing(shader->d->shaderGuard.context(), + d->programGuard.context())) { qWarning("QGLShaderProgram::addShader: Program and shader are not associated with same context."); return false; } if (!shader->d->compiled) return false; if (!shader->d->isPartial) { - if (!shader->d->shader) + if (!shader->d->shaderGuard.id()) return false; - QGLContextGroup *ctx = d->ctx; - glAttachShader(d->program, shader->d->shader); + glAttachShader(d->programGuard.id(), shader->d->shaderGuard.id()); } else { d->hasPartialShaders = true; } @@ -1017,14 +973,9 @@ bool QGLShaderProgram::addShaderFromFile */ void QGLShaderProgram::removeShader(QGLShader *shader) { - if (d->program && shader && shader->d->shader) { - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) - qWarning("QGLShaderProgram::removeShader: Program is not associated with current context."); - else -#endif - glDetachShader(d->program, shader->d->shader); + if (d->programGuard.id() && shader && shader->d->shaderGuard.id()) { + QGLShareContextScope scope(d->programGuard.context()); + glDetachShader(d->programGuard.id(), shader->d->shaderGuard.id()); } d->linked = false; // Program needs to be relinked. if (shader) { @@ -1056,15 +1007,9 @@ QList<QGLShader *> QGLShaderProgram::shaders() const void QGLShaderProgram::removeAllShaders() { d->removingShaders = true; - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) - qWarning("QGLShaderProgram::removeAllShaders: Program is not associated with current context."); - else -#endif foreach (QGLShader *shader, d->shaders) { - if (d->program && shader && shader->d->shader) - glDetachShader(d->program, shader->d->shader); + if (d->programGuard.id() && shader && shader->d->shaderGuard.id()) + glDetachShader(d->programGuard.id(), shader->d->shaderGuard.id()); } foreach (QGLShader *shader, d->anonShaders) { // Delete shader objects that were created anonymously. @@ -1113,22 +1058,17 @@ QByteArray QGLShaderProgram::programBinary(int *format) const if (!isLinked()) return QByteArray(); - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) - qWarning("QGLShaderProgram::programBinary: Program is not associated with current context."); -#endif - // Get the length of the binary data, bailing out if there is none. GLint length = 0; - glGetProgramiv(d->program, GL_PROGRAM_BINARY_LENGTH_OES, &length); + GLuint program = d->programGuard.id(); + glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH_OES, &length); if (length <= 0) return QByteArray(); // Retrieve the binary data. QByteArray binary(length, 0); GLenum binaryFormat; - glGetProgramBinaryOES(d->program, length, 0, &binaryFormat, binary.data()); + glGetProgramBinaryOES(program, length, 0, &binaryFormat, binary.data()); if (format) *format = (int)binaryFormat; return binary; @@ -1149,25 +1089,22 @@ QByteArray QGLShaderProgram::programBinary(int *format) const bool QGLShaderProgram::setProgramBinary(int format, const QByteArray& binary) { #if defined(QT_OPENGL_ES_2) - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) - qWarning("QGLShaderProgram::setProgramBinary: Program is not associated with current context."); -#endif - // Load the binary and check that it was linked correctly. - glProgramBinaryOES(d->program, (GLenum)format, + GLuint program = d->programGuard.id(); + if (!program) + return false; + glProgramBinaryOES(program, (GLenum)format, binary.constData(), binary.size()); GLint value = 0; - glGetProgramiv(d->program, GL_LINK_STATUS, &value); + glGetProgramiv(program, GL_LINK_STATUS, &value); d->linked = (value != 0); value = 0; - glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value); d->log = QString(); if (value > 1) { char *logbuf = new char [value]; GLint len; - glGetProgramInfoLog(d->program, value, &len, logbuf); + glGetProgramInfoLog(program, value, &len, logbuf); d->log = QString::fromLatin1(logbuf); QString name = objectName(); if (name.isEmpty()) @@ -1222,16 +1159,9 @@ QList<int> QGLShaderProgram::programBinaryFormats() */ bool QGLShaderProgram::link() { - if (!d->program) - return false; - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) { - qWarning("QGLShaderProgram::link: Program is not associated with current context."); + GLuint program = d->programGuard.id(); + if (!program) return false; - } -#endif - if (d->hasPartialShaders) { // Compile the partial vertex and fragment shaders. QByteArray vertexSource; @@ -1244,7 +1174,7 @@ bool QGLShaderProgram::link() } if (vertexSource.isEmpty()) { if (d->vertexShader) { - glDetachShader(d->program, d->vertexShader->d->shader); + glDetachShader(program, d->vertexShader->d->shaderGuard.id()); delete d->vertexShader; d->vertexShader = 0; } @@ -1257,11 +1187,11 @@ bool QGLShaderProgram::link() d->log = d->vertexShader->log(); return false; } - glAttachShader(d->program, d->vertexShader->d->shader); + glAttachShader(program, d->vertexShader->d->shaderGuard.id()); } if (fragmentSource.isEmpty()) { if (d->fragmentShader) { - glDetachShader(d->program, d->fragmentShader->d->shader); + glDetachShader(program, d->fragmentShader->d->shaderGuard.id()); delete d->fragmentShader; d->fragmentShader = 0; } @@ -1274,20 +1204,20 @@ bool QGLShaderProgram::link() d->log = d->fragmentShader->log(); return false; } - glAttachShader(d->program, d->fragmentShader->d->shader); + glAttachShader(program, d->fragmentShader->d->shaderGuard.id()); } } - glLinkProgram(d->program); + glLinkProgram(program); GLint value = 0; - glGetProgramiv(d->program, GL_LINK_STATUS, &value); + glGetProgramiv(program, GL_LINK_STATUS, &value); d->linked = (value != 0); value = 0; - glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value); d->log = QString(); if (value > 1) { char *logbuf = new char [value]; GLint len; - glGetProgramInfoLog(d->program, value, &len, logbuf); + glGetProgramInfoLog(program, value, &len, logbuf); d->log = QString::fromLatin1(logbuf); QString name = objectName(); if (name.isEmpty()) @@ -1330,21 +1260,18 @@ QString QGLShaderProgram::log() const */ bool QGLShaderProgram::enable() { - if (!d->program) + GLuint program = d->programGuard.id(); + if (!program) return false; if (!d->linked && !link()) return false; - QGLContextGroup *ctx = d->ctx; -#ifndef QT_NO_DEBUG - if (!qt_check_sharing_with_current_context(ctx)) { - qWarning("QGLShaderProgram::enable: Program is not associated with current context."); - return false; - } -#endif - glUseProgram(d->program); + glUseProgram(program); return true; } +#undef ctx +#define ctx QGLContext::currentContext() + /*! Disables the active shader program in the current QGLContext. This is equivalent to calling \c{glUseProgram(0)}. @@ -1353,7 +1280,6 @@ bool QGLShaderProgram::enable() */ void QGLShaderProgram::disable() { - const QGLContext *ctx = QGLContext::currentContext(); #if defined(QT_OPENGL_ES_2) glUseProgram(0); #else @@ -1362,7 +1288,8 @@ void QGLShaderProgram::disable() #endif } -#define ctx d->ctx +#undef ctx +#define ctx d->programGuard.context() /*! Returns the OpenGL identifier associated with this shader program. @@ -1371,7 +1298,7 @@ void QGLShaderProgram::disable() */ GLuint QGLShaderProgram::programId() const { - return d->program; + return d->programGuard.id(); } /*! @@ -1384,7 +1311,7 @@ GLuint QGLShaderProgram::programId() const */ void QGLShaderProgram::bindAttributeLocation(const char *name, int location) { - glBindAttribLocation(d->program, location, name); + glBindAttribLocation(d->programGuard.id(), location, name); } /*! @@ -1399,7 +1326,7 @@ void QGLShaderProgram::bindAttributeLocation(const char *name, int location) */ void QGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location) { - glBindAttribLocation(d->program, location, name.constData()); + glBindAttribLocation(d->programGuard.id(), location, name.constData()); } /*! @@ -1414,7 +1341,7 @@ void QGLShaderProgram::bindAttributeLocation(const QByteArray& name, int locatio */ void QGLShaderProgram::bindAttributeLocation(const QString& name, int location) { - glBindAttribLocation(d->program, location, name.toLatin1().constData()); + glBindAttribLocation(d->programGuard.id(), location, name.toLatin1().constData()); } /*! @@ -1427,7 +1354,7 @@ void QGLShaderProgram::bindAttributeLocation(const QString& name, int location) int QGLShaderProgram::attributeLocation(const char *name) const { if (d->linked) { - return glGetAttribLocation(d->program, name); + return glGetAttribLocation(d->programGuard.id(), name); } else { qWarning() << "QGLShaderProgram::attributeLocation(" << name << "): shader program is not linked"; @@ -1887,7 +1814,7 @@ void QGLShaderProgram::disableAttributeArray(const char *name) int QGLShaderProgram::uniformLocation(const char *name) const { if (d->linked) { - return glGetUniformLocation(d->program, name); + return glGetUniformLocation(d->programGuard.id(), name); } else { qWarning() << "QGLShaderProgram::uniformLocation(" << name << "): shader program is not linked"; diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 7a09d91..2ca6d26 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -374,12 +374,7 @@ QScriptContext *QScriptContext::parentContext() const { const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); JSC::CallFrame *callerFrame = frame->callerFrame()->removeHostCallFrameFlag(); - if (callerFrame && callerFrame->callerFrame()->hasHostCallFrameFlag() - && callerFrame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(frame)->globalExec()) { - //skip the "fake" context created in Interpreter::execute. - callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag(); - } - return reinterpret_cast<QScriptContext *>(callerFrame); + return QScriptEnginePrivate::contextForFrame(callerFrame); } /*! diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index c22a465..1be76a9 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -162,16 +162,19 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte // Get the line number: //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context - QScriptContext *rewindContext = context->engine()->currentContext(); - if (rewindContext != context) { //ignore top context (native function) + JSC::CallFrame *rewindContext = QScriptEnginePrivate::get(context->engine())->currentFrame; + if (QScriptEnginePrivate::contextForFrame(rewindContext) == context) { //top context + frame = rewindContext; //for retreiving the global context's "fake" frame + // An agent might have provided the line number. + lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber; + } else { // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored - while (rewindContext && rewindContext->parentContext() != context) - rewindContext = rewindContext->parentContext(); + while (rewindContext && QScriptEnginePrivate::contextForFrame(rewindContext->callerFrame()->removeHostCallFrameFlag()) != context) + rewindContext = rewindContext->callerFrame()->removeHostCallFrameFlag(); if (rewindContext) { - JSC::ExecState *aboveFrame = QScriptEnginePrivate::frameForContext(rewindContext); - frame = aboveFrame->callerFrame()->removeHostCallFrameFlag(); //it will be different for the global context. + frame = rewindContext->callerFrame()->removeHostCallFrameFlag(); //for retreiving the global context's "fake" frame - JSC::Instruction *returnPC = aboveFrame->returnPC(); + JSC::Instruction *returnPC = rewindContext->returnPC(); JSC::CodeBlock *codeBlock = frame->codeBlock(); if (returnPC && codeBlock) { #if ENABLE(JIT) @@ -183,9 +186,6 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), bytecodeOffset); } } - } else { - // An agent might have provided the line number. - lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber; } // Get the filename and the scriptId: diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 6dc10d6..087e49c 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -985,6 +985,11 @@ void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, JSC::JSValue prot QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame) { + if (frame && frame->callerFrame()->hasHostCallFrameFlag() + && frame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(frame)->globalExec()) { + //skip the "fake" context created in Interpreter::execute. + frame = frame->callerFrame()->removeHostCallFrameFlag(); + } return reinterpret_cast<QScriptContext *>(frame); } diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index f9296fb..2766cca 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -707,6 +707,7 @@ QVariant QSQLiteDriver::handle() const QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const { + Q_UNUSED(type); return _q_escapeIdentifier(identifier); } diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index 1fd35e0..06a49d8 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -1203,10 +1203,9 @@ static void parsePen(QSvgNode *node, } //stroke-width handling - qreal w = 0; if (!attributes.strokeWidth.isEmpty() && attributes.strokeWidth != QT_INHERIT) { QSvgHandler::LengthType lt; - prop->setWidth(w = parseLength(attributes.strokeWidth.toString(), lt, handler)); + prop->setWidth(parseLength(attributes.strokeWidth.toString(), lt, handler)); } //stroke-dasharray diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 3ddf43b..564bf24 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -697,14 +697,12 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) case Translate: { startElem *= 3; endElem *= 3; - qreal from1, from2, from3; - qreal to1, to2, to3; + qreal from1, from2; + qreal to1, to2; from1 = m_args[startElem++]; from2 = m_args[startElem++]; - from3 = m_args[startElem++]; to1 = m_args[endElem++]; to2 = m_args[endElem++]; - to3 = m_args[endElem++]; qreal transXDiff = (to1-from1) * percentOfAnimation; qreal transX = from1 + transXDiff; @@ -717,14 +715,12 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) case Scale: { startElem *= 3; endElem *= 3; - qreal from1, from2, from3; - qreal to1, to2, to3; + qreal from1, from2; + qreal to1, to2; from1 = m_args[startElem++]; from2 = m_args[startElem++]; - from3 = m_args[startElem++]; to1 = m_args[endElem++]; to2 = m_args[endElem++]; - to3 = m_args[endElem++]; qreal transXDiff = (to1-from1) * percentOfAnimation; qreal transX = from1 + transXDiff; @@ -764,14 +760,10 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) case SkewX: { startElem *= 3; endElem *= 3; - qreal from1, from2, from3; - qreal to1, to2, to3; + qreal from1; + qreal to1; from1 = m_args[startElem++]; - from2 = m_args[startElem++]; - from3 = m_args[startElem++]; to1 = m_args[endElem++]; - to2 = m_args[endElem++]; - to3 = m_args[endElem++]; qreal transXDiff = (to1-from1) * percentOfAnimation; qreal transX = from1 + transXDiff; @@ -782,14 +774,10 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) case SkewY: { startElem *= 3; endElem *= 3; - qreal from1, from2, from3; - qreal to1, to2, to3; + qreal from1; + qreal to1; from1 = m_args[startElem++]; - from2 = m_args[startElem++]; - from3 = m_args[startElem++]; to1 = m_args[endElem++]; - to2 = m_args[endElem++]; - to3 = m_args[endElem++]; qreal transYDiff = (to1 - from1) * percentOfAnimation; diff --git a/tests/auto/q3popupmenu/tst_q3popupmenu.cpp b/tests/auto/q3popupmenu/tst_q3popupmenu.cpp index 3be416c..5585c3a 100644 --- a/tests/auto/q3popupmenu/tst_q3popupmenu.cpp +++ b/tests/auto/q3popupmenu/tst_q3popupmenu.cpp @@ -117,6 +117,8 @@ void tst_Q3PopupMenu::task177490_highlighted() QApplication::processEvents(); #endif Q3PopupMenu menu1; + //don't let the window manager move the popup while we are testing + menu1.setWindowFlags(Qt::X11BypassWindowManagerHint); menu1.insertItem("Item 1"); Q3PopupMenu menu2; @@ -133,16 +135,12 @@ void tst_Q3PopupMenu::task177490_highlighted() QTest::mouseMove(&menu1, QPoint(x, y1)); QTest::mouseMove(&menu1, QPoint(x, y1 + 1)); - QTest::qWait(1000); + QTest::qWait(100); QTest::mouseMove(&menu1, QPoint(x, y2)); QTest::mouseMove(&menu1, QPoint(x, y2 + 1)); - QTest::qWait(1000); + QTest::qWait(100); - if (!menu2.isVisible()) - QEXPECT_FAIL( - "", "expected failure due to visibilty/focus problem; to be investigated later", - Abort); QCOMPARE(spy.count(), 2); // one per menu item } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index cbb0802..b8061da 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -60,6 +60,9 @@ #include <QVBoxLayout> #include <QGraphicsEffect> +#include "../../shared/util.h" + + //TESTED_CLASS= //TESTED_FILES= @@ -1933,7 +1936,7 @@ void tst_QGraphicsItem::zValue() QApplication::sendPostedEvents(); //glib workaround #endif - QVERIFY(!_paintedItems.isEmpty()); + QTRY_VERIFY(!_paintedItems.isEmpty()); QVERIFY((_paintedItems.size() % 4) == 0); for (int i = 0; i < 3; ++i) QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue()); @@ -2917,6 +2920,7 @@ void tst_QGraphicsItem::hoverEventsGenerateRepaints() qApp->processEvents(); qApp->processEvents(); + QTRY_COMPARE(tester->repaints, 1); // Send a hover enter event QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter); @@ -7823,7 +7827,7 @@ void tst_QGraphicsItem::panel() QEvent activate(QEvent::WindowActivate); QEvent deactivate(QEvent::WindowDeactivate); - + QApplication::sendEvent(&scene, &activate); // No previous activation, so the scene is active. diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 8bac29d..9249f6d 100644 --- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -51,7 +51,6 @@ #include <private/qt_x11_p.h> #endif - static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton) { QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, button, 0); @@ -953,6 +952,8 @@ void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent() QGraphicsScene scene; QGraphicsView view(&scene); + //do not let the window manager move the window while we are moving the mouse on it + view.setWindowFlags(Qt::X11BypassWindowManagerHint); view.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&view); @@ -975,7 +976,7 @@ void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent() // in QTest::mouseMove(&view, QPoint(50, 50)); QTest::qWait(250); - // QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), hasWidget ? true : false); + QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), hasWidget ? true : false); // ### this attribute isn't supported QCOMPARE(widget->enterCount, hasWidget ? 1 : 0); QCOMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0); @@ -1288,7 +1289,7 @@ void tst_QGraphicsProxyWidget::paintEvent() w->update(); QTest::qWait(100); - QCOMPARE(proxy.paintCount, 1); //the widget should have been painted now + QTRY_COMPARE(proxy.paintCount, 1); //the widget should have been painted now } @@ -1481,8 +1482,8 @@ void tst_QGraphicsProxyWidget::scrollUpdate() view.paintEventRegion = QRegion(); view.npaints = 0; QTimer::singleShot(0, widget, SLOT(updateScroll())); - QTest::qWait(500); - QCOMPARE(view.npaints, 2); + QTest::qWait(50); + QTRY_COMPARE(view.npaints, 2); // QRect(0, 0, 200, 12) is the first update, expanded (-2, -2, 2, 2) // QRect(0, 12, 102, 10) is the scroll update, expanded (-2, -2, 2, 2), // intersected with the above update. diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 66a91f3..f78c59e 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -1627,7 +1627,7 @@ void tst_QGraphicsScene::hoverEvents_siblings() QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove); mouseEvent.setScenePos(QPointF(-1000, -1000)); QApplication::sendEvent(&scene, &mouseEvent); - + QTest::qWait(50); for (int j = 1; j >= 0; --j) { @@ -2465,7 +2465,7 @@ void tst_QGraphicsScene::dragAndDrop_propagate() QCOMPARE(item1->eventList.at(0), QEvent::GraphicsSceneDragEnter); QCOMPARE(item1->eventList.at(1), QEvent::GraphicsSceneDragMove); } - + { // Move into the intersection item1-item2 QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0); @@ -2875,7 +2875,7 @@ public: QList<QEvent::Type> receivedSceneEvents; QList<QEvent::Type> receivedSceneEventFilters; - + protected: bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) { @@ -2961,10 +2961,10 @@ void tst_QGraphicsScene::exposedRect() scene.addItem(item); QCOMPARE(item->exposed, QRectF()); - + QImage image(100, 100, QImage::Format_ARGB32_Premultiplied); QPainter painter(&image); - + scene.render(&painter); QCOMPARE(item->exposed, item->boundingRect()); @@ -3269,7 +3269,7 @@ void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets() EventSpy focusOutSpy_1_2(widget1_2, QEvent::FocusOut); EventSpy focusInSpy_2(widget2, QEvent::FocusIn); EventSpy focusOutSpy_2(widget2, QEvent::FocusOut); - + QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab); QTest::qWait(125); QVERIFY(widget1->hasFocus()); diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 0115d95..bb0ea70 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -66,6 +66,8 @@ #include <QtGui/QInputContext> #include <private/qgraphicsview_p.h> +#include "../../shared/util.h" + //TESTED_CLASS= //TESTED_FILES= @@ -1383,7 +1385,7 @@ void tst_QGraphicsView::itemsInRect_cosmeticAdjust() else view.viewport()->update(updateRect); qApp->processEvents(); - QCOMPARE(rect->numPaints, numPaints); + QTRY_COMPARE(rect->numPaints, numPaints); } void tst_QGraphicsView::itemsInPoly() @@ -2171,18 +2173,16 @@ void tst_QGraphicsView::viewportUpdateMode() qt_x11_wait_for_window_manager(&view); #endif QTest::qWait(50); + QTRY_VERIFY(!view.lastUpdateRegions.isEmpty()); view.lastUpdateRegions.clear(); // Issue two scene updates. scene.update(QRectF(0, 0, 10, 10)); scene.update(QRectF(20, 0, 10, 10)); -#ifdef Q_WS_X11 - qt_x11_wait_for_window_manager(&view); -#endif QTest::qWait(50); // The view gets two updates for the update scene updates. - QVERIFY(!view.lastUpdateRegions.isEmpty()); + QTRY_VERIFY(!view.lastUpdateRegions.isEmpty()); QCOMPARE(view.lastUpdateRegions.last().rects().size(), 2); QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(15, 15)); QCOMPARE(view.lastUpdateRegions.last().rects().at(1).size(), QSize(15, 15)); @@ -2433,7 +2433,7 @@ void tst_QGraphicsView::optimizationFlags_dontSavePainterState() class LodItem : public QGraphicsRectItem { public: - LodItem(const QRectF &rect) : QGraphicsRectItem(rect), lastLod(1) + LodItem(const QRectF &rect) : QGraphicsRectItem(rect), lastLod(-42) { } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *viewport) @@ -2485,7 +2485,7 @@ void tst_QGraphicsView::levelOfDetail() #endif QTest::qWait(50); - QCOMPARE(item->lastLod, qreal(1)); + QTRY_COMPARE(item->lastLod, qreal(1)); view.setTransform(transform); @@ -2494,7 +2494,7 @@ void tst_QGraphicsView::levelOfDetail() #endif QTest::qWait(50); - QCOMPARE(item->lastLod, lod); + QTRY_COMPARE(item->lastLod, lod); } // Moved to tst_qgraphicsview_2.cpp @@ -2695,10 +2695,13 @@ void tst_QGraphicsView::task172231_untransformableItems() view.scale(2, 1); view.show(); -#ifdef Q_WS_X11 + QApplication::setActiveWindow(&view); +#if defined(Q_WS_X11) qt_x11_wait_for_window_manager(&view); #endif QTest::qWait(50); + QTRY_COMPARE(QApplication::activeWindow(), &view); + QRectF origExposedRect = text->exposedRect; view.resize(int(0.75 * view.width()), view.height()); @@ -2840,14 +2843,14 @@ void tst_QGraphicsView::task207546_focusCrash() widget.layout()->addWidget(gr1); widget.layout()->addWidget(gr2); widget.show(); -#if defined(Q_OS_IRIX) - QTest::qWait(200); + QTest::qWait(20); widget.activateWindow(); - QTest::qWait(200); -#elif defined(Q_WS_X11) + QApplication::setActiveWindow(&widget); +#if defined(Q_WS_X11) qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(50); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&widget)); widget.focusNextPrevChild(true); QCOMPARE(static_cast<QWidget *>(gr2), widget.focusWidget()); } @@ -3187,7 +3190,8 @@ void tst_QGraphicsView::centerOnDirtyItem() #endif QTest::qWait(50); - QPixmap before = QPixmap::grabWindow(view.viewport()->winId()); + QImage before(view.viewport()->size(), QImage::Format_ARGB32); + view.viewport()->render(&before); item->setPos(20, 0); view.centerOn(item); @@ -3197,7 +3201,8 @@ void tst_QGraphicsView::centerOnDirtyItem() #endif QTest::qWait(50); - QPixmap after = QPixmap::grabWindow(view.viewport()->winId()); + QImage after(view.viewport()->size(), QImage::Format_ARGB32); + view.viewport()->render(&after); QCOMPARE(before, after); } @@ -3470,6 +3475,10 @@ void tst_QGraphicsView::update() QCOMPARE(viewportRect, QRect(0, 0, 200, 200)); #if defined QT_BUILD_INTERNAL + QApplication::setActiveWindow(&view); + QTest::qWait(50); + QTRY_COMPARE(QApplication::activeWindow(), &view); + const bool intersects = updateRect.intersects(viewportRect); QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view)); QCOMPARE(viewPrivate->updateRect(updateRect), intersects); diff --git a/tests/auto/qlocalsocket/lackey/lackey.pro b/tests/auto/qlocalsocket/lackey/lackey.pro index 7bb6bc3..efb2f52 100644 --- a/tests/auto/qlocalsocket/lackey/lackey.pro +++ b/tests/auto/qlocalsocket/lackey/lackey.pro @@ -2,6 +2,8 @@ include(../src/src.pri) QT = core script network +requires(contains(QT_CONFIG,script)) + CONFIG += qtestlib DESTDIR = ./ diff --git a/tests/auto/qlocalsocket/test/test.pro b/tests/auto/qlocalsocket/test/test.pro index 503f769..cfdc89b 100644 --- a/tests/auto/qlocalsocket/test/test.pro +++ b/tests/auto/qlocalsocket/test/test.pro @@ -44,5 +44,7 @@ wince*|symbian { scriptFiles.path = lackey/scripts DEPLOYMENT = additionalFiles scriptFiles QT += script # for easy deployment of QtScript + + requires(contains(QT_CONFIG,script)) } diff --git a/tests/auto/qwswindowsystem/tst_qwswindowsystem.cpp b/tests/auto/qwswindowsystem/tst_qwswindowsystem.cpp index 3a2e79b..014074a 100644 --- a/tests/auto/qwswindowsystem/tst_qwswindowsystem.cpp +++ b/tests/auto/qwswindowsystem/tst_qwswindowsystem.cpp @@ -239,6 +239,7 @@ void tst_QWSWindowSystem::windowOpacity() QColor(255, 255, 255, 0)); w2.setPalette(palette); QApplication::processEvents(); + QApplication::processEvents(); QCOMPARE(win1->allocatedRegion(), QRegion(rect)); QCOMPARE(win2->allocatedRegion(), QRegion(rect)); VERIFY_COLOR(rect, w1.color()); diff --git a/tools/designer/src/uitools/uitools.pro b/tools/designer/src/uitools/uitools.pro index 38b7add..7b94587 100644 --- a/tools/designer/src/uitools/uitools.pro +++ b/tools/designer/src/uitools/uitools.pro @@ -5,6 +5,11 @@ CONFIG += qt staticlib DESTDIR = ../../../../lib DLLDESTDIR = ../../../../bin +symbian { + TARGET.UID3 = 0x2001E628 + load(armcc_warnings) +} + win32|mac:!macx-xcode:CONFIG += debug_and_release build_all DEFINES += QFORMINTERNAL_NAMESPACE QT_DESIGNER_STATIC QT_FORMBUILDER_NO_SCRIPT @@ -38,5 +43,3 @@ unix { QMAKE_PKGCONFIG_DESTDIR = pkgconfig QMAKE_PKGCONFIG_REQUIRES += QtXml } - -symbian: TARGET.UID3 = 0x2001E628 |