From 8102b75ee85a4cf0c2af2eea3787ff0209e01998 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Tue, 18 Feb 2014 09:22:11 +0100 Subject: [PATCH 001/124] Remove qSort usages from widgets tests QtAlgorithms is getting deprecated, see http://www.mail-archive.com/development@qt-project.org/msg01603.html Change-Id: Ica7639d16f52b4ffcd2c00cc806fed1378a7948b Reviewed-by: Stephen Kelly --- .../dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp | 6 ++++-- tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 9cb391d5f4..eac3f9c9ae 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -57,6 +57,8 @@ # include // for SetFileAttributes #endif +#include + #define WAITTIME 1000 // Will try to wait for the condition while allowing event processing @@ -710,8 +712,8 @@ void tst_QFileSystemModel::filters() for (int i = 0; i < rowCount; ++i) modelEntries.append(model->data(model->index(i, 0, root), QFileSystemModel::FileNameRole).toString()); - qSort(dirEntries); - qSort(modelEntries); + std::sort(dirEntries.begin(), dirEntries.end()); + std::sort(modelEntries.begin(), modelEntries.end()); QCOMPARE(dirEntries, modelEntries); #ifdef Q_OS_LINUX diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index dfb780c8fa..4afe80b087 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -46,6 +46,8 @@ #include #include "private/qapplication_p.h" +#include + #ifdef QT_BUILD_INTERNAL #define VERIFY_SPANS_CONSISTENCY(TEST_VIEW_) \ QVERIFY(static_cast(QObjectPrivate::get(TEST_VIEW_))->spans.checkConsistency()) @@ -3921,8 +3923,8 @@ void tst_QTableView::task234926_setHeaderSorting() data << "orange" << "apple" << "banana" << "lemon" << "pumpkin"; QStringList sortedDataA = data; QStringList sortedDataD = data; - qSort(sortedDataA); - qSort(sortedDataD.begin(), sortedDataD.end(), qGreater()); + std::sort(sortedDataA.begin(), sortedDataA.end()); + std::sort(sortedDataD.begin(), sortedDataD.end(), qGreater()); model.setStringList(data); QTableView view; view.setModel(&model); From 0702418c8134876577033b88fe10cc6faf1663ee Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 13 Feb 2014 15:11:56 +0100 Subject: [PATCH 002/124] Mac: Fix file dialog filters when filter doesn't start with '*' Task-number: QTBUG-17326 Change-Id: I3e6ed40fdb0e04367bb031b2c674424a4b74af2f Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index f401459cc3..8728ab8764 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -318,7 +318,7 @@ static QString strippedText(QString s) } } - QString qtFileName = QCFString::toQString(filename); + QString qtFileName = QFileInfo(QCFString::toQString(filename)).fileName(); // No filter means accept everything bool nameMatches = mSelectedNameFilter->isEmpty(); // Check if the current file name filter accepts the file: From d7b0581c1c2ef60c08d238dae39298af6904918f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 12 Feb 2014 21:51:58 -0800 Subject: [PATCH 003/124] Make sure that the compiler is strict in QtCore ICC defaults to "fast math" mode, which allows it to do non-compliant operations that may or may not result in unexpected values. Generally, it's ok, but apparently the code in qlocale_tools.cpp is too complex, so we're not taking chances. I can't rule out an issue in the code, though. Task-number: QTBUG-36795 Change-Id: Ica5cb77fb3a65d22ae8ad22e13b4ba78f1b5dadf Reviewed-by: Lars Knoll --- src/corelib/tools/tools.pri | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index cac596f0bc..52bb987506 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -1,5 +1,7 @@ # Qt tools module +intel_icc: QMAKE_CXXFLAGS += -fp-model strict + HEADERS += \ tools/qalgorithms.h \ tools/qarraydata.h \ From 3a84d92f5736da3dc3f6a385bf3723984a5640ed Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 18 Feb 2014 14:03:05 +0100 Subject: [PATCH 004/124] Make unicode ranges in font take precedence over codepage Change 4b2c73b4767bcb512cbc17f65186eac5d004db07 triggered a regression on Android, because the DroidSansFallback.ttf font has codepage ranges that list Arabic as a supported codepage despite the fact that the font has no glyphs for Arabic. If a font has valid unicode ranges which does not specify support for e.g. Arabic, then the code page ranges for the same script should be ignored. [ChangeLog][Android][Fonts] Fixed support for Arabic text. Task-number: QTBUG-36789 Change-Id: I7c5a0e303fd9ed2733275814fe752ae0fb54a207 Reviewed-by: Konstantin Ritt --- src/gui/text/qplatformfontdatabase.cpp | 104 +++++++++++++------------ 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index 37610a9099..a25c814d4a 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -502,58 +502,60 @@ QSupportedWritingSystems QPlatformFontDatabase::writingSystemsFromTrueTypeBits(q } } } - if (codePageRange[0] & ((1 << Latin1CsbBit) | (1 << CentralEuropeCsbBit) | (1 << TurkishCsbBit) | (1 << BalticCsbBit))) { - writingSystems.setSupported(QFontDatabase::Latin); - hasScript = true; - //qDebug("font %s supports Latin", familyName.latin1()); + if (!hasScript) { + if (codePageRange[0] & ((1 << Latin1CsbBit) | (1 << CentralEuropeCsbBit) | (1 << TurkishCsbBit) | (1 << BalticCsbBit))) { + writingSystems.setSupported(QFontDatabase::Latin); + hasScript = true; + //qDebug("font %s supports Latin", familyName.latin1()); + } + if (codePageRange[0] & (1 << CyrillicCsbBit)) { + writingSystems.setSupported(QFontDatabase::Cyrillic); + hasScript = true; + //qDebug("font %s supports Cyrillic", familyName.latin1()); + } + if (codePageRange[0] & (1 << GreekCsbBit)) { + writingSystems.setSupported(QFontDatabase::Greek); + hasScript = true; + //qDebug("font %s supports Greek", familyName.latin1()); + } + if (codePageRange[0] & (1 << HebrewCsbBit)) { + writingSystems.setSupported(QFontDatabase::Hebrew); + hasScript = true; + //qDebug("font %s supports Hebrew", familyName.latin1()); + } + if (codePageRange[0] & (1 << ArabicCsbBit)) { + writingSystems.setSupported(QFontDatabase::Arabic); + hasScript = true; + //qDebug("font %s supports Arabic", familyName.latin1()); + } + if (codePageRange[0] & (1 << VietnameseCsbBit)) { + writingSystems.setSupported(QFontDatabase::Vietnamese); + hasScript = true; + //qDebug("font %s supports Vietnamese", familyName.latin1()); + } + if (codePageRange[0] & (1 << SimplifiedChineseCsbBit)) { + writingSystems.setSupported(QFontDatabase::SimplifiedChinese); + hasScript = true; + //qDebug("font %s supports Simplified Chinese", familyName.latin1()); + } + if (codePageRange[0] & (1 << TraditionalChineseCsbBit)) { + writingSystems.setSupported(QFontDatabase::TraditionalChinese); + hasScript = true; + //qDebug("font %s supports Traditional Chinese", familyName.latin1()); + } + if (codePageRange[0] & (1 << JapaneseCsbBit)) { + writingSystems.setSupported(QFontDatabase::Japanese); + hasScript = true; + //qDebug("font %s supports Japanese", familyName.latin1()); + } + if (codePageRange[0] & ((1 << KoreanCsbBit) | (1 << KoreanJohabCsbBit))) { + writingSystems.setSupported(QFontDatabase::Korean); + hasScript = true; + //qDebug("font %s supports Korean", familyName.latin1()); + } + if (!hasScript) + writingSystems.setSupported(QFontDatabase::Symbol); } - if (codePageRange[0] & (1 << CyrillicCsbBit)) { - writingSystems.setSupported(QFontDatabase::Cyrillic); - hasScript = true; - //qDebug("font %s supports Cyrillic", familyName.latin1()); - } - if (codePageRange[0] & (1 << GreekCsbBit)) { - writingSystems.setSupported(QFontDatabase::Greek); - hasScript = true; - //qDebug("font %s supports Greek", familyName.latin1()); - } - if (codePageRange[0] & (1 << HebrewCsbBit)) { - writingSystems.setSupported(QFontDatabase::Hebrew); - hasScript = true; - //qDebug("font %s supports Hebrew", familyName.latin1()); - } - if (codePageRange[0] & (1 << ArabicCsbBit)) { - writingSystems.setSupported(QFontDatabase::Arabic); - hasScript = true; - //qDebug("font %s supports Arabic", familyName.latin1()); - } - if (codePageRange[0] & (1 << VietnameseCsbBit)) { - writingSystems.setSupported(QFontDatabase::Vietnamese); - hasScript = true; - //qDebug("font %s supports Vietnamese", familyName.latin1()); - } - if (codePageRange[0] & (1 << SimplifiedChineseCsbBit)) { - writingSystems.setSupported(QFontDatabase::SimplifiedChinese); - hasScript = true; - //qDebug("font %s supports Simplified Chinese", familyName.latin1()); - } - if (codePageRange[0] & (1 << TraditionalChineseCsbBit)) { - writingSystems.setSupported(QFontDatabase::TraditionalChinese); - hasScript = true; - //qDebug("font %s supports Traditional Chinese", familyName.latin1()); - } - if (codePageRange[0] & (1 << JapaneseCsbBit)) { - writingSystems.setSupported(QFontDatabase::Japanese); - hasScript = true; - //qDebug("font %s supports Japanese", familyName.latin1()); - } - if (codePageRange[0] & ((1 << KoreanCsbBit) | (1 << KoreanJohabCsbBit))) { - writingSystems.setSupported(QFontDatabase::Korean); - hasScript = true; - //qDebug("font %s supports Korean", familyName.latin1()); - } - if (!hasScript) - writingSystems.setSupported(QFontDatabase::Symbol); return writingSystems; } From 08cbbde61778276ccdda73d89fd64d02c623779f Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 3 Jan 2014 16:08:38 +0100 Subject: [PATCH 005/124] QtConcurrent: Extend workaround GCC bug 58800 in median calculation GNU/Linux distributions like Fedora update the __GLIBCXX__ date (e.g. because of applied extra patches on top) and thus make the current workaround useless. As long as no official gcc/libstdc++ version is released, we can increment the "upper bound" date to cover such cases. See also comment #1 at QTCREATORBUG-11129. Change-Id: I1fdf6f312664163f6a99a8eddf490646ff25a87d Reviewed-by: Olivier Goffart Reviewed-by: Marc Mutz --- src/concurrent/qtconcurrentmedian.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/concurrent/qtconcurrentmedian.h b/src/concurrent/qtconcurrentmedian.h index ce2afb9c28..5dd43a015e 100644 --- a/src/concurrent/qtconcurrentmedian.h +++ b/src/concurrent/qtconcurrentmedian.h @@ -104,8 +104,10 @@ public: dirty = false; // This is a workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800 -// Avoid using std::nth_element for stdlibc++ <= 4.7.3 || (>= 4.8.0 && <= 4.8.2) -#if defined(__GLIBCXX__) && (__GLIBCXX__ <= 20130411 || (__GLIBCXX__ >= 20130322 && __GLIBCXX__ <= 20131016)) +// Avoid using std::nth_element for the affected stdlibc++ releases 4.7.3 and 4.8.2. +// Note that the official __GLIBCXX__ value of the releases is not used since that +// one might be patched on some GNU/Linux distributions. +#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20140107 QVector sorted = values; std::sort(sorted.begin(), sorted.end()); currentMedian = sorted.at(bufferSize / 2); From 4de3c5db238f45404feb6c6ce60810a3e11eae84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 10 Feb 2014 13:59:44 +0100 Subject: [PATCH 006/124] Unify glyph format between QFontEngine and QFontEngineGlyphCache Instead of the glyph cache having its own cache type that always mapped one to one to a font engine glyph format, causing confusion and needless conversions, the glyph caches now use QFontEngine's glyph format enum. This also removes the iffy use of an int for the glyphFormat in the font engines. Change-Id: I529bad5c179e004f63e152f7dcc311d298c3db98 Reviewed-by: Simon Hausmann --- src/gui/opengl/qopenglpaintengine.cpp | 53 +++++++++---------- src/gui/opengl/qopenglpaintengine_p.h | 4 +- src/gui/opengl/qopengltextureglyphcache.cpp | 6 +-- src/gui/opengl/qopengltextureglyphcache_p.h | 2 +- src/gui/painting/qpaintengine_raster.cpp | 20 +++---- src/gui/painting/qpaintengine_raster_p.h | 2 +- src/gui/painting/qpaintengineex.cpp | 2 +- src/gui/painting/qtextureglyphcache.cpp | 43 +++++++-------- src/gui/painting/qtextureglyphcache_p.h | 8 +-- src/gui/text/qfontengine.cpp | 29 ++++++++-- src/gui/text/qfontengine_ft.cpp | 8 ++- src/gui/text/qfontengine_ft_p.h | 2 +- src/gui/text/qfontengine_p.h | 15 ++++-- src/gui/text/qfontengineglyphcache_p.h | 17 +++--- .../qpaintengineex_opengl2.cpp | 46 ++++++++-------- .../qpaintengineex_opengl2_p.h | 4 +- .../qtextureglyphcache_gl.cpp | 6 +-- .../qtextureglyphcache_gl_p.h | 2 +- .../mac/qcoretextfontdatabase.mm | 6 +-- .../fontdatabases/mac/qfontengine_coretext.mm | 8 +-- .../mac/qfontengine_coretext_p.h | 4 +- .../windows/qwindowsfontdatabase.cpp | 2 +- .../platforms/windows/qwindowsfontengine.cpp | 4 +- .../windows/qwindowsfontenginedirectwrite.cpp | 2 +- 24 files changed, 156 insertions(+), 139 deletions(-) diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp index e91ada7b3a..63127668a5 100644 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ b/src/gui/opengl/qopenglpaintengine.cpp @@ -1434,19 +1434,18 @@ void QOpenGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) QFontEngine *fontEngine = textItem->fontEngine(); if (shouldDrawCachedGlyphs(fontEngine, s->matrix)) { - QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 - ? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat) - : d->glyphCacheType; - if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { + QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None + ? fontEngine->glyphFormat : d->glyphCacheFormat; + if (glyphFormat == QFontEngine::Format_A32) { if (d->device->context()->format().alphaBufferSize() > 0 || s->matrix.type() > QTransform::TxTranslate || (s->composition_mode != QPainter::CompositionMode_Source && s->composition_mode != QPainter::CompositionMode_SourceOver)) { - glyphType = QFontEngineGlyphCache::Raster_A8; + glyphFormat = QFontEngine::Format_A8; } } - d->drawCachedGlyphs(glyphType, textItem); + d->drawCachedGlyphs(glyphFormat, textItem); } else { QPaintEngineEx::drawStaticTextItem(textItem); } @@ -1483,17 +1482,15 @@ void QOpenGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &text QTransform::TransformationType txtype = s->matrix.type(); - QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0 - ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat) - : d->glyphCacheType; + QFontEngine::GlyphFormat glyphFormat = ti.fontEngine->glyphFormat != QFontEngine::Format_None + ? ti.fontEngine->glyphFormat : d->glyphCacheFormat; - - if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { + if (glyphFormat == QFontEngine::Format_A32) { if (d->device->context()->format().alphaBufferSize() > 0 || txtype > QTransform::TxTranslate || (state()->composition_mode != QPainter::CompositionMode_Source && state()->composition_mode != QPainter::CompositionMode_SourceOver)) { - glyphType = QFontEngineGlyphCache::Raster_A8; + glyphFormat = QFontEngine::Format_A8; } } @@ -1512,7 +1509,7 @@ void QOpenGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &text staticTextItem.numGlyphs = glyphs.size(); staticTextItem.glyphPositions = positions.data(); - d->drawCachedGlyphs(glyphType, &staticTextItem); + d->drawCachedGlyphs(glyphFormat, &staticTextItem); } return; } @@ -1537,7 +1534,7 @@ namespace { QSize cacheSize; QOpenGL2PEXVertexArray vertexCoordinateArray; QOpenGL2PEXVertexArray textureCoordinateArray; - QFontEngineGlyphCache::Type glyphType; + QFontEngine::GlyphFormat glyphFormat; int cacheSerialNumber; }; @@ -1572,7 +1569,7 @@ bool QOpenGL2PaintEngineEx::shouldDrawCachedGlyphs(QFontEngine *fontEngine, cons return QPaintEngineEx::shouldDrawCachedGlyphs(fontEngine, t); } -void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, +void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, QStaticTextItem *staticTextItem) { Q_Q(QOpenGL2PaintEngineEx); @@ -1596,9 +1593,9 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type } QOpenGLTextureGlyphCache *cache = - (QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, glyphCacheTransform); - if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) { - cache = new QOpenGLTextureGlyphCache(glyphType, glyphCacheTransform); + (QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphFormat, glyphCacheTransform); + if (!cache || cache->glyphFormat() != glyphFormat || cache->contextGroup() == 0) { + cache = new QOpenGLTextureGlyphCache(glyphFormat, glyphCacheTransform); fe->setGlyphCache(cacheKey, cache); recreateVertexArrays = true; } @@ -1611,7 +1608,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type recreateVertexArrays = true; } else { QOpenGLStaticTextUserData *userData = static_cast(staticTextItem->userData()); - if (userData->glyphType != glyphType) { + if (userData->glyphFormat != glyphFormat) { recreateVertexArrays = true; } else if (userData->cacheSerialNumber != cache->serialNumber()) { recreateVertexArrays = true; @@ -1636,12 +1633,12 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type if (cache->width() == 0 || cache->height() == 0) return; - if (glyphType == QFontEngineGlyphCache::Raster_ARGB) + if (glyphFormat == QFontEngine::Format_ARGB) transferMode(ImageArrayDrawingMode); else transferMode(TextDrawingMode); - int margin = fe->glyphMargin(glyphType); + int margin = fe->glyphMargin(glyphFormat); GLfloat dx = 1.0 / cache->width(); GLfloat dy = 1.0 / cache->height(); @@ -1663,7 +1660,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type userData = static_cast(staticTextItem->userData()); } - userData->glyphType = glyphType; + userData->glyphFormat = glyphFormat; userData->cacheSerialNumber = cache->serialNumber(); // Use cache if backend optimizations is turned on @@ -1735,7 +1732,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type #endif } - if (glyphType != QFontEngineGlyphCache::Raster_ARGB || recreateVertexArrays) { + if (glyphFormat != QFontEngine::Format_ARGB || recreateVertexArrays) { setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data()); setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data()); } @@ -1748,7 +1745,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type QBrush pensBrush = q->state()->pen.brush(); setBrush(pensBrush); - if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { + if (glyphFormat == QFontEngine::Format_A32) { // Subpixel antialiasing without gamma correction @@ -1821,7 +1818,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glBlendFunc(GL_ONE, GL_ONE); } compositionModeDirty = true; - } else if (glyphType == QFontEngineGlyphCache::Raster_ARGB) { + } else if (glyphFormat == QFontEngine::Format_ARGB) { currentBrush = noBrush; shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); if (prepareForCachedGlyphDraw(*cache)) @@ -1836,7 +1833,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type QOpenGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QOpenGLTextureGlyphCache::Linear:QOpenGLTextureGlyphCache::Nearest; if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) { - if (glyphType == QFontEngineGlyphCache::Raster_ARGB) + if (glyphFormat == QFontEngine::Format_ARGB) funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); else funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); @@ -2012,12 +2009,12 @@ bool QOpenGL2PaintEngineEx::begin(QPaintDevice *pdev) glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; + d->glyphCacheFormat = QFontEngine::Format_A8; #ifndef QT_OPENGL_ES_2 if (!QOpenGLFunctions::isES()) { glDisable(GL_MULTISAMPLE); - d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; + d->glyphCacheFormat = QFontEngine::Format_A32; d->multisamplingAlwaysEnabled = false; } else #endif // QT_OPENGL_ES_2 diff --git a/src/gui/opengl/qopenglpaintengine_p.h b/src/gui/opengl/qopenglpaintengine_p.h index d51f0e5256..4f0e2e52a4 100644 --- a/src/gui/opengl/qopenglpaintengine_p.h +++ b/src/gui/opengl/qopenglpaintengine_p.h @@ -212,7 +212,7 @@ public: void drawTexture(const QOpenGLRect& dest, const QOpenGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::PixmapFragmentHints hints); - void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem); + void drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, QStaticTextItem *staticTextItem); // Calls glVertexAttributePointer if the pointer has changed inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer); @@ -267,7 +267,7 @@ public: int width, height; QOpenGLContext *ctx; EngineMode mode; - QFontEngineGlyphCache::Type glyphCacheType; + QFontEngine::GlyphFormat glyphCacheFormat; bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT]; diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp index 0d9a2359bd..ba1fa8f486 100644 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ b/src/gui/opengl/qopengltextureglyphcache.cpp @@ -51,8 +51,8 @@ QT_BEGIN_NAMESPACE QBasicAtomicInt qopengltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); -QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) - : QImageTextureGlyphCache(type, matrix) +QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) + : QImageTextureGlyphCache(format, matrix) , m_textureResource(0) , pex(0) , m_blitProgram(0) @@ -122,7 +122,7 @@ void QOpenGLTextureGlyphCache::createTextureData(int width, int height) m_textureResource->m_width = width; m_textureResource->m_height = height; - if (m_type == QFontEngineGlyphCache::Raster_RGBMask || m_type == QFontEngineGlyphCache::Raster_ARGB) { + if (m_format == QFontEngine::Format_A32 || m_format == QFontEngine::Format_ARGB) { QVarLengthArray data(width * height * 4); for (int i = 0; i < data.size(); ++i) data[i] = 0; diff --git a/src/gui/opengl/qopengltextureglyphcache_p.h b/src/gui/opengl/qopengltextureglyphcache_p.h index d9456db6ed..a361a79de2 100644 --- a/src/gui/opengl/qopengltextureglyphcache_p.h +++ b/src/gui/opengl/qopengltextureglyphcache_p.h @@ -109,7 +109,7 @@ public: class Q_GUI_EXPORT QOpenGLTextureGlyphCache : public QImageTextureGlyphCache { public: - QOpenGLTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix); + QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat glyphFormat, const QTransform &matrix); ~QOpenGLTextureGlyphCache(); virtual void createTextureData(int width, int height); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 9a2e49618c..67896f786d 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -523,7 +523,7 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) #endif if (d->mono_surface) - d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono; + d->glyphCacheFormat = QFontEngine::Format_Mono; #if defined(Q_OS_WIN) else if (clearTypeFontsEnabled()) #else @@ -532,11 +532,11 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) { QImage::Format format = static_cast(d->device)->format(); if (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32) - d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; + d->glyphCacheFormat = QFontEngine::Format_A32; else - d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; + d->glyphCacheFormat = QFontEngine::Format_A8; } else - d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; + d->glyphCacheFormat = QFontEngine::Format_A8; setActive(true); return true; @@ -2819,12 +2819,12 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, } } else { - QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType; + QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None ? fontEngine->glyphFormat : d->glyphCacheFormat; QImageTextureGlyphCache *cache = - static_cast(fontEngine->glyphCache(0, glyphType, s->matrix)); + static_cast(fontEngine->glyphCache(0, glyphFormat, s->matrix)); if (!cache) { - cache = new QImageTextureGlyphCache(glyphType, s->matrix); + cache = new QImageTextureGlyphCache(glyphFormat, s->matrix); fontEngine->setGlyphCache(0, cache); } @@ -2842,7 +2842,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, else if (depth == 1) rightShift = 3; // divide by 8 - int margin = fontEngine->glyphMargin(glyphType); + int margin = fontEngine->glyphMargin(glyphFormat); const uchar *bits = image.bits(); for (int i=0; i> rightShift) + c.y * bpl; - if (glyphType == QFontEngineGlyphCache::Raster_ARGB) { + if (glyphFormat == QFontEngine::Format_ARGB) { // The current state transform has already been applied to the positions, // so we prevent drawImage() from re-applying the transform by clearing // the state for the duration of the call. @@ -3064,7 +3064,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte Q_D(QRasterPaintEngine); fprintf(stderr," - QRasterPaintEngine::drawTextItem(), (%.2f,%.2f), string=%s ct=%d\n", p.x(), p.y(), QString::fromRawData(ti.chars, ti.num_chars).toLatin1().data(), - d->glyphCacheType); + d->glyphCacheFormat); #endif if (ti.glyphs.numGlyphs == 0) diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 00a9ae750c..4bfdbd91e0 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -336,7 +336,7 @@ public: QSpanData solid_color_filler; - QFontEngineGlyphCache::Type glyphCacheType; + QFontEngine::GlyphFormat glyphCacheFormat; QScopedPointer baseClip; diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 6e72b5db7f..e75a59cc91 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -1088,7 +1088,7 @@ bool QPaintEngineEx::requiresPretransformedGlyphPositions(QFontEngine *, const Q bool QPaintEngineEx::shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &m) const { - if (fontEngine->glyphFormat == QFontEngineGlyphCache::Raster_ARGB) + if (fontEngine->glyphFormat == QFontEngine::Format_ARGB) return true; qreal pixelSize = fontEngine->fontDef.pixelSize; diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index e340c1e613..83edeb41a6 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -130,14 +130,6 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const QHash listItemCoordinates; int rowHeight = 0; - QFontEngine::GlyphFormat format; - switch (m_type) { - case Raster_A8: format = QFontEngine::Format_A8; break; - case Raster_RGBMask: format = QFontEngine::Format_A32; break; - case Raster_ARGB: format = QFontEngine::Format_ARGB; break; - default: format = QFontEngine::Format_Mono; break; - } - // check each glyph for its metrics and get the required rowHeight. for (int i=0; i < numGlyphs; ++i) { const glyph_t glyph = glyphs[i]; @@ -159,12 +151,12 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const // we ask for the alphaMapBoundingBox(), the glyph will be loaded, rasterized and its // proper metrics will be cached and used later. if (fontEngine->hasInternalCaching()) { - QImage *locked = fontEngine->lockedAlphaMapForGlyph(glyph, subPixelPosition, format); + QImage *locked = fontEngine->lockedAlphaMapForGlyph(glyph, subPixelPosition, m_format); if (locked && !locked->isNull()) fontEngine->unlockAlphaMapForGlyph(); } - glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, subPixelPosition, m_transform, format); + glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, subPixelPosition, m_transform, m_format); #ifdef CACHE_DEBUG printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n", @@ -186,7 +178,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const continue; } // align to 8-bit boundary - if (m_type == QFontEngineGlyphCache::Raster_Mono) + if (m_format == QFontEngine::Format_Mono) glyph_width = (glyph_width+7)&~7; Coord c = { 0, 0, // will be filled in later @@ -289,11 +281,14 @@ void QTextureGlyphCache::fillInPendingGlyphs() QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const { - if (m_type == QFontEngineGlyphCache::Raster_RGBMask) + switch (m_format) { + case QFontEngine::Format_A32: return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, m_transform); - else if (m_type == QFontEngineGlyphCache::Raster_ARGB) + case QFontEngine::Format_ARGB: return m_current_fontengine->bitmapForGlyph(g, subPixelPosition, m_transform); - return m_current_fontengine->alphaMapForGlyph(g, subPixelPosition, m_transform); + default: + return m_current_fontengine->alphaMapForGlyph(g, subPixelPosition, m_transform); + } } /************************************************************************ @@ -307,11 +302,11 @@ void QImageTextureGlyphCache::resizeTextureData(int width, int height) void QImageTextureGlyphCache::createTextureData(int width, int height) { - switch (m_type) { - case QFontEngineGlyphCache::Raster_Mono: + switch (m_format) { + case QFontEngine::Format_Mono: m_image = QImage(width, height, QImage::Format_Mono); break; - case QFontEngineGlyphCache::Raster_A8: { + case QFontEngine::Format_A8: { m_image = QImage(width, height, QImage::Format_Indexed8); m_image.fill(0); QVector colors(256); @@ -320,12 +315,14 @@ void QImageTextureGlyphCache::createTextureData(int width, int height) *it = 0xff000000 | i | (i<<8) | (i<<16); m_image.setColorTable(colors); break; } - case QFontEngineGlyphCache::Raster_RGBMask: + case QFontEngine::Format_A32: m_image = QImage(width, height, QImage::Format_RGB32); break; - case QFontEngineGlyphCache::Raster_ARGB: + case QFontEngine::Format_ARGB: m_image = QImage(width, height, QImage::Format_ARGB32_Premultiplied); break; + default: + Q_UNREACHABLE(); } } @@ -341,8 +338,8 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP } #endif - if (m_type == QFontEngineGlyphCache::Raster_RGBMask - || m_type == QFontEngineGlyphCache::Raster_ARGB) { + if (m_format == QFontEngine::Format_A32 + || m_format == QFontEngine::Format_ARGB) { QImage ref(m_image.bits() + (c.x * 4 + c.y * m_image.bytesPerLine()), qMax(mask.width(), c.w), qMax(mask.height(), c.h), m_image.bytesPerLine(), m_image.format()); @@ -351,7 +348,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP p.fillRect(0, 0, c.w, c.h, QColor(0,0,0,0)); // TODO optimize this p.drawImage(0, 0, mask); p.end(); - } else if (m_type == QFontEngineGlyphCache::Raster_Mono) { + } else if (m_format == QFontEngine::Format_Mono) { if (mask.depth() > 1) { // TODO optimize this mask = mask.alphaChannel(); @@ -414,7 +411,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP #ifdef CACHE_DEBUG // QPainter p(&m_image); // p.drawLine( - int margin = m_current_fontengine ? m_current_fontengine->glyphMargin(m_type) : 0; + int margin = m_current_fontengine ? m_current_fontengine->glyphMargin(m_format) : 0; QPoint base(c.x + margin, c.y + margin + c.baseLineY-1); if (m_image.rect().contains(base)) m_image.setPixel(base, 255); diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index d93f57ad80..84f62717f6 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -75,8 +75,8 @@ class QTextItemInt; class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache { public: - QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) - : QFontEngineGlyphCache(matrix, type), m_current_fontengine(0), + QTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) + : QFontEngineGlyphCache(format, matrix), m_current_fontengine(0), m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0) { } @@ -163,8 +163,8 @@ inline uint qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g) class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache { public: - QImageTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) - : QTextureGlyphCache(type, matrix) { } + QImageTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) + : QTextureGlyphCache(format, matrix) { } virtual void createTextureData(int width, int height); virtual void resizeTextureData(int width, int height); virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition); diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 14ce5d2396..83e64a51a6 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -41,6 +41,7 @@ #include #include +#include #include "qbitmap.h" #include "qpainter.h" @@ -253,7 +254,7 @@ QFontEngine::QFontEngine() fsType = 0; symbol = false; - glyphFormat = -1; + glyphFormat = Format_None; m_subPixelPositionCount = 0; #ifdef QT_BUILD_INTERNAL @@ -979,12 +980,12 @@ void QFontEngine::setGlyphCache(const void *key, QFontEngineGlyphCache *data) } -QFontEngineGlyphCache *QFontEngine::glyphCache(const void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const +QFontEngineGlyphCache *QFontEngine::glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const { for (QLinkedList::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) { QFontEngineGlyphCache *c = it->cache.data(); if (key == it->context - && type == c->cacheType() + && format == c->glyphFormat() && qtransform_equals_no_translate(c->m_transform, transform)) { return c; } @@ -1354,6 +1355,28 @@ QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round) return 0; } + +QFontEngine::GlyphCacheEntry::GlyphCacheEntry() + : context(0) +{ +} + +QFontEngine::GlyphCacheEntry::GlyphCacheEntry(const GlyphCacheEntry &o) + : context(o.context), cache(o.cache) +{ +} + +QFontEngine::GlyphCacheEntry::~GlyphCacheEntry() +{ +} + +QFontEngine::GlyphCacheEntry &QFontEngine::GlyphCacheEntry::operator=(const GlyphCacheEntry &o) +{ + context = o.context; + cache = o.cache; + return *this; +} + // ------------------------------------------------------------------ // The box font engine // ------------------------------------------------------------------ diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 665932e4a5..242c1d8d32 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -690,11 +690,9 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, this->antialias = antialias; if (!antialias) - glyphFormat = QFontEngineGlyphCache::Raster_Mono; - else if (format == Format_A8) - glyphFormat = QFontEngineGlyphCache::Raster_A8; - else if (format == Format_A32) - glyphFormat = QFontEngineGlyphCache::Raster_RGBMask; + glyphFormat = QFontEngine::Format_Mono; + else + glyphFormat = defaultFormat; face_id = faceId; diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 7df66b9678..ad1598ba6d 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -264,7 +264,7 @@ private: virtual void unlockAlphaMapForGlyph(); virtual void removeGlyphFromCache(glyph_t glyph); - virtual int glyphMargin(QFontEngineGlyphCache::Type /* type */) { return 0; } + virtual int glyphMargin(QFontEngine::GlyphFormat /* format */) { return 0; } virtual int glyphCount() const; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 532ebaf8ff..0bfb9e70e2 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -60,11 +60,10 @@ #include "private/qtextengine_p.h" #include "private/qfont_p.h" -#include - QT_BEGIN_NAMESPACE class QPainterPath; +class QFontEngineGlyphCache; struct QGlyphLayout; @@ -246,7 +245,7 @@ public: virtual Type type() const = 0; virtual int glyphCount() const; - virtual int glyphMargin(QFontEngineGlyphCache::Type type) { return type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0; } + virtual int glyphMargin(GlyphFormat format) { return format == Format_A32 ? 2 : 0; } virtual QFontEngine *cloneWithSize(qreal /*pixelSize*/) const { return 0; } @@ -258,7 +257,7 @@ public: void clearGlyphCache(const void *key); void setGlyphCache(const void *key, QFontEngineGlyphCache *data); - QFontEngineGlyphCache *glyphCache(const void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const; + QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const; static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize); static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode); @@ -300,7 +299,7 @@ public: QVector kerning_pairs; void loadKerningPairs(QFixed scalingFactor); - int glyphFormat; + GlyphFormat glyphFormat; QImage currentlyLockedAlphaMap; int m_subPixelPositionCount; // Number of positions within a single pixel for this cache @@ -313,6 +312,12 @@ protected: private: struct GlyphCacheEntry { + GlyphCacheEntry(); + GlyphCacheEntry(const GlyphCacheEntry &); + ~GlyphCacheEntry(); + + GlyphCacheEntry &operator=(const GlyphCacheEntry &); + const void *context; QExplicitlySharedDataPointer cache; bool operator==(const GlyphCacheEntry &other) const { return context == other.context && cache == other.cache; } diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h index ac01c78399..65be14b90f 100644 --- a/src/gui/text/qfontengineglyphcache_p.h +++ b/src/gui/text/qfontengineglyphcache_p.h @@ -58,6 +58,7 @@ #include "QtCore/qatomic.h" #include #include "private/qfont_p.h" +#include "private/qfontengine_p.h" @@ -66,22 +67,18 @@ QT_BEGIN_NAMESPACE class QFontEngineGlyphCache: public QSharedData { public: - enum Type { - Raster_RGBMask, - Raster_A8, - Raster_Mono, - Raster_ARGB - }; - - QFontEngineGlyphCache(const QTransform &matrix, Type type) : m_transform(matrix), m_type(type) { } + QFontEngineGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) : m_format(format), m_transform(matrix) + { + Q_ASSERT(m_format != QFontEngine::Format_None); + } virtual ~QFontEngineGlyphCache() { } - Type cacheType() const { return m_type; } + QFontEngine::GlyphFormat glyphFormat() const { return m_format; } const QTransform &transform() const { return m_transform; } + QFontEngine::GlyphFormat m_format; QTransform m_transform; - QFontEngineGlyphCache::Type m_type; }; typedef QHash > GlyphPointerHash; typedef QHash > GlyphIntHash; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 32dd7be7ba..ec4ff5a2b2 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1482,20 +1482,20 @@ void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) // don't try to cache huge fonts or vastly transformed fonts QFontEngine *fontEngine = textItem->fontEngine(); if (shouldDrawCachedGlyphs(fontEngine, s->matrix)) { - QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 - ? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat) - : d->glyphCacheType; - if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { + QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat >= 0 + ? QFontEngine::GlyphFormat(textItem->fontEngine()->glyphFormat) + : d->glyphCacheFormat; + if (glyphFormat == QFontEngine::Format_A32) { if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || d->device->alphaRequested() || s->matrix.type() > QTransform::TxTranslate || (s->composition_mode != QPainter::CompositionMode_Source && s->composition_mode != QPainter::CompositionMode_SourceOver)) { - glyphType = QFontEngineGlyphCache::Raster_A8; + glyphFormat = QFontEngine::Format_A8; } } - d->drawCachedGlyphs(glyphType, textItem); + d->drawCachedGlyphs(glyphFormat, textItem); } else { QPaintEngineEx::drawStaticTextItem(textItem); } @@ -1532,18 +1532,18 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem QTransform::TransformationType txtype = s->matrix.type(); - QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0 - ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat) - : d->glyphCacheType; + QFontEngine::GlyphFormat glyphFormat = ti.fontEngine->glyphFormat >= 0 + ? ti.fontEngine->glyphFormat + : d->glyphCacheFormat; - if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { + if (glyphFormat == QFontEngine::Format_A32) { if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || d->device->alphaRequested() || txtype > QTransform::TxTranslate || (state()->composition_mode != QPainter::CompositionMode_Source && state()->composition_mode != QPainter::CompositionMode_SourceOver)) { - glyphType = QFontEngineGlyphCache::Raster_A8; + glyphFormat = QFontEngine::Format_A8; } } @@ -1562,7 +1562,7 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem staticTextItem.numGlyphs = glyphs.size(); staticTextItem.glyphPositions = positions.data(); - d->drawCachedGlyphs(glyphType, &staticTextItem); + d->drawCachedGlyphs(glyphFormat, &staticTextItem); } return; } @@ -1587,7 +1587,7 @@ namespace { QSize cacheSize; QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; - QFontEngineGlyphCache::Type glyphType; + QFontEngine::GlyphFormat glyphFormat; int cacheSerialNumber; }; @@ -1596,7 +1596,7 @@ namespace { // #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO -void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, +void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, QStaticTextItem *staticTextItem) { Q_Q(QGL2PaintEngineEx); @@ -1620,9 +1620,9 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp } QGLTextureGlyphCache *cache = - (QGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, glyphCacheTransform); - if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) { - cache = new QGLTextureGlyphCache(glyphType, glyphCacheTransform); + (QGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphFormat, glyphCacheTransform); + if (!cache || cache->glyphFormat() != glyphFormat || cache->contextGroup() == 0) { + cache = new QGLTextureGlyphCache(glyphFormat, glyphCacheTransform); fe->setGlyphCache(cacheKey, cache); recreateVertexArrays = true; } @@ -1635,7 +1635,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp recreateVertexArrays = true; } else { QOpenGLStaticTextUserData *userData = static_cast(staticTextItem->userData()); - if (userData->glyphType != glyphType) { + if (userData->glyphFormat != glyphFormat) { recreateVertexArrays = true; } else if (userData->cacheSerialNumber != cache->serialNumber()) { recreateVertexArrays = true; @@ -1662,7 +1662,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp transferMode(TextDrawingMode); - int margin = fe->glyphMargin(glyphType); + int margin = fe->glyphMargin(glyphFormat); GLfloat dx = 1.0 / cache->width(); GLfloat dy = 1.0 / cache->height(); @@ -1684,7 +1684,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp userData = static_cast(staticTextItem->userData()); } - userData->glyphType = glyphType; + userData->glyphFormat = glyphFormat; userData->cacheSerialNumber = cache->serialNumber(); // Use cache if backend optimizations is turned on @@ -1767,7 +1767,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp QBrush pensBrush = q->state()->pen.brush(); setBrush(pensBrush); - if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { + if (glyphFormat == QFontEngine::Format_A32) { // Subpixel antialiasing without gamma correction @@ -2037,11 +2037,11 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) glDisable(GL_MULTISAMPLE); #endif - d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; + d->glyphCacheFormat = QFontEngine::Format_A8; #if !defined(QT_OPENGL_ES_2) if (!QOpenGLFunctions::isES()) { - d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; + d->glyphCacheFormat = QFontEngine::Format_A32; d->multisamplingAlwaysEnabled = false; } else { d->multisamplingAlwaysEnabled = d->device->format().sampleBuffers(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 76ef3aa55a..33a8869ecf 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -203,7 +203,7 @@ public: void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::PixmapFragmentHints hints); - void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem); + void drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, QStaticTextItem *staticTextItem); // Calls glVertexAttributePointer if the pointer has changed inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer); @@ -255,7 +255,7 @@ public: int width, height; QGLContext *ctx; EngineMode mode; - QFontEngineGlyphCache::Type glyphCacheType; + QFontEngine::GlyphFormat glyphCacheFormat; QOpenGLExtensions funcs; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index d506b7e4b9..f9f2670375 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -49,8 +49,8 @@ QT_BEGIN_NAMESPACE QBasicAtomicInt qgltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); -QGLTextureGlyphCache::QGLTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) - : QImageTextureGlyphCache(type, matrix) +QGLTextureGlyphCache::QGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) + : QImageTextureGlyphCache(format, matrix) , m_textureResource(0) , pex(0) , m_blitProgram(0) @@ -123,7 +123,7 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) m_textureResource->m_width = width; m_textureResource->m_height = height; - if (m_type == QFontEngineGlyphCache::Raster_RGBMask) { + if (m_format == QFontEngine::Format_A32) { QVarLengthArray data(width * height * 4); for (int i = 0; i < data.size(); ++i) data[i] = 0; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 8f43a906c0..5ffbea8708 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -112,7 +112,7 @@ struct QGLGlyphTexture : public QOpenGLSharedResource class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache { public: - QGLTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix); + QGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix); ~QGLTextureGlyphCache(); virtual void createTextureData(int width, int height); diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index ab2e9c1f1a..76506d12e9 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -163,10 +163,10 @@ QCoreTextFontDatabase::QCoreTextFontDatabase() [fontImage release]; } QCoreTextFontEngine::defaultGlyphFormat = (font_smoothing > 0 - ? QFontEngineGlyphCache::Raster_RGBMask - : QFontEngineGlyphCache::Raster_A8); + ? QFontEngine::Format_A32 + : QFontEngine::Format_A8); #else - QCoreTextFontEngine::defaultGlyphFormat = QFontEngineGlyphCache::Raster_A8; + QCoreTextFontEngine::defaultGlyphFormat = QFontEngine::Format_A8; #endif } diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 31a015ae9f..7742733a01 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -74,7 +74,7 @@ static void loadAdvancesForGlyphs(CTFontRef ctfont, int QCoreTextFontEngine::antialiasingThreshold = 0; -QFontEngineGlyphCache::Type QCoreTextFontEngine::defaultGlyphFormat = QFontEngineGlyphCache::Raster_RGBMask; +QFontEngine::GlyphFormat QCoreTextFontEngine::defaultGlyphFormat = QFontEngine::Format_A32; CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef) { @@ -155,7 +155,7 @@ void QCoreTextFontEngine::init() #if defined(Q_OS_IOS) || MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (supportsColorGlyphs() && (traits & kCTFontColorGlyphsTrait)) - glyphFormat = QFontEngineGlyphCache::Raster_ARGB; + glyphFormat = QFontEngine::Format_ARGB; else #endif glyphFormat = defaultGlyphFormat; @@ -424,7 +424,7 @@ static void convertCGPathToQPainterPath(void *info, const CGPathElement *element void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs, QPainterPath *path, QTextItem::RenderFlags) { - if (glyphFormat == QFontEngineGlyphCache::Raster_ARGB) + if (glyphFormat == QFontEngine::Format_ARGB) return; // We can't convert color-glyphs to path CGAffineTransform cgMatrix = CGAffineTransformIdentity; @@ -473,7 +473,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition glyph_metrics_t br = boundingBox(glyph); qcoretextfontengine_scaleMetrics(br, m); - bool isColorGlyph = glyphFormat == QFontEngineGlyphCache::Raster_ARGB; + bool isColorGlyph = glyphFormat == QFontEngine::Format_ARGB; QImage::Format format = isColorGlyph ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; QImage im(qAbs(qRound(br.width)) + 2, qAbs(qRound(br.height)) + 2, format); im.fill(0); diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 7ef9f0dfbb..1cdac820b6 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -104,7 +104,7 @@ public: bool supportsTransformation(const QTransform &transform) const; virtual QFontEngine *cloneWithSize(qreal pixelSize) const; - virtual int glyphMargin(QFontEngineGlyphCache::Type type) { Q_UNUSED(type); return 0; } + virtual int glyphMargin(QFontEngine::GlyphFormat format) { Q_UNUSED(format); return 0; } static bool supportsColorGlyphs() { @@ -122,7 +122,7 @@ public: } static int antialiasingThreshold; - static QFontEngineGlyphCache::Type defaultGlyphFormat; + static QFontEngine::GlyphFormat defaultGlyphFormat; private: friend class QRawFontPrivate; diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 96659c505f..854444b254 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1745,7 +1745,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(int script, const QFontDef &requ if (!useDirectWrite) { QWindowsFontEngine *few = new QWindowsFontEngine(request.family, hfont, stockFont, lf, data); if (preferClearTypeAA) - few->glyphFormat = QFontEngineGlyphCache::Raster_RGBMask; + few->glyphFormat = QFontEngine::Format_A32; few->initFontInfo(request, fontHdc, dpi); fe = few; } diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 1676b73658..86fcb666b0 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -1148,7 +1148,7 @@ glyph_metrics_t QWindowsFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed, c { int margin = 0; if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB) - margin = glyphMargin(QFontEngineGlyphCache::Raster_RGBMask); + margin = glyphMargin(QFontEngine::Format_A32); glyph_metrics_t gm = boundingBox(glyph, matrix); gm.width += margin * 2; gm.height += margin * 2; @@ -1221,7 +1221,7 @@ QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTra SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &contrast, 0); SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) 1000, 0); - int margin = glyphMargin(QFontEngineGlyphCache::Raster_RGBMask); + int margin = glyphMargin(QFontEngine::Format_A32); QWindowsNativeImage *mask = drawGDIGlyph(font, glyph, margin, t, QImage::Format_RGB32); SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) quintptr(contrast), 0); diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index ce5ea8167f..1c5e4508ac 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -620,7 +620,7 @@ QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t, { QImage mask = imageForGlyph(t, subPixelPosition, - glyphMargin(QFontEngineGlyphCache::Raster_RGBMask), + glyphMargin(QFontEngine::Format_A32), xform); return mask.depth() == 32 From e380a48af72575edd86f6aeb33d55ee49e30fbda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 10 Feb 2014 14:24:18 +0100 Subject: [PATCH 007/124] Unify alpha map padding in CoreText font engine Instead of padding the image size manually, we rely on alphaMapBoundingBox to give use the right glyph metrics. For clarity, a few function arguments were renamed in the affected code. Change-Id: I84c31e613a1048ea839a390af70342e5388ed0cb Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qfontengine_coretext.mm | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 7742733a01..1036a95a92 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -452,10 +452,10 @@ static void qcoretextfontengine_scaleMetrics(glyph_metrics_t &br, const QTransfo } } -glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format) +glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, GlyphFormat format) { if (matrix.type() > QTransform::TxScale) - return QFontEngine::alphaMapBoundingBox(glyph, pos, matrix, format); + return QFontEngine::alphaMapBoundingBox(glyph, subPixelPosition, matrix, format); glyph_metrics_t br = boundingBox(glyph); qcoretextfontengine_scaleMetrics(br, matrix); @@ -467,15 +467,14 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed p } -QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &m) +QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &matrix) { - glyph_metrics_t br = boundingBox(glyph); - qcoretextfontengine_scaleMetrics(br, m); + glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat); bool isColorGlyph = glyphFormat == QFontEngine::Format_ARGB; - QImage::Format format = isColorGlyph ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; - QImage im(qAbs(qRound(br.width)) + 2, qAbs(qRound(br.height)) + 2, format); + QImage::Format imageFormat = isColorGlyph ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; + QImage im(br.width.toInt(), br.height.toInt(), imageFormat); im.fill(0); #ifndef Q_OS_IOS @@ -503,8 +502,8 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition if (!isColorGlyph) // CTFontDrawGlyphs incorporates the font's matrix already cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - if (m.isScaling()) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMakeScale(m.m11(), m.m22())); + if (matrix.isScaling()) + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMakeScale(matrix.m11(), matrix.m22())); CGGlyph cgGlyph = glyph; qreal pos_x = -br.x.truncate() + subPixelPosition.toReal(); From d0784ae43bafbb577ce1d30dcd3327e9271ead2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 11 Feb 2014 13:50:38 +0100 Subject: [PATCH 008/124] Prevent top/left clipping of anti-aliased glyphs in CoreText font engine Padding the bounding rect was not enough, as we failed to shift the glyph accordingly so that it would end up in the center of the bounding rect. We also didn't take subpixel-positioning into account, which may shift the position of the glyph too far to the right to be within the image size that we reserve. There are still cases where the glyphs seem clipped compared to the same text rendered with CoreText, but that's because we end up shaping the text slightly differently, resulting in different subpixel positions than what CoreText chooses. Change-Id: Icb88c829f86457b16bdecbc4c24b3f1c23448261 Reviewed-by: Simon Hausmann --- .../fontdatabases/mac/qfontengine_coretext.mm | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 1036a95a92..4fe78cb568 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -460,8 +460,46 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed s glyph_metrics_t br = boundingBox(glyph); qcoretextfontengine_scaleMetrics(br, matrix); - br.width = qAbs(qRound(br.width)) + 2; - br.height = qAbs(qRound(br.height)) + 2; + // Normalize width and height + if (br.width < 0) + br.width = -br.width; + if (br.height < 0) + br.height = -br.height; + + if (format == QFontEngine::Format_A8 || format == QFontEngine::Format_A32) { + // Drawing a glyph at x-position 0 with anti-aliasing enabled + // will potentially fill the pixel to the left of 0, as the + // coordinates are not aligned to the center of pixels. To + // prevent clipping of this pixel we need to shift the glyph + // in the bitmap one pixel to the right. The shift needs to + // be reflected in the glyph metrics as well, so that the final + // position of the glyph is correct, which is why doing the + // shift in imageForGlyph() is not enough. + br.x -= 1; + + // As we've shifted the glyph one pixel to the right, we need + // to expand the width of the alpha map bounding box as well. + br.width += 1; + + // But we have the same anti-aliasing problem on the right + // hand side of the glyph, eg. if the width of the glyph + // results in the bounding rect landing between two pixels. + // We pad the bounding rect again to account for the possible + // anti-aliased drawing. + br.width += 1; + + // We also shift the glyph to right right based on the subpixel + // position, so we pad the bounding box to take account for the + // subpixel positions that may result in the glyph being drawn + // one pixel to the right of the 0-subpixel position. + br.width += 1; + + // The same same logic as for the x-position needs to be applied + // to the y-position, except we don't need to compensate for + // the subpixel positioning. + br.y -= 1; + br.height += 2; + } return br; } @@ -474,7 +512,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition bool isColorGlyph = glyphFormat == QFontEngine::Format_ARGB; QImage::Format imageFormat = isColorGlyph ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; - QImage im(br.width.toInt(), br.height.toInt(), imageFormat); + QImage im(br.width.ceil().toInt(), br.height.ceil().toInt(), imageFormat); im.fill(0); #ifndef Q_OS_IOS From 42789d04a3078652594b8e06f520d7dd5e8021c5 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Tue, 18 Feb 2014 10:02:26 +0100 Subject: [PATCH 009/124] Use QMAKE_TARGET_BUNDLE_PREFIX to build bundle identifier Currently the bundle identifier is build using com.yourcompany + QMAKE_BUNDLE. This patch adds the handling of QMAKE_TARGET_BUNDLE_PREFIX to build the bundle prefix. Task-number: QTBUG-19006 Change-Id: I014279da6dbef393b0df36f6d4995e40ab105316 Reviewed-by: Oswald Buddenhagen Reviewed-by: Liang Qi Reviewed-by: Gabriel de Dietrich --- qmake/generators/unix/unixmake2.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 8959305238..6e08c138ed 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -729,7 +729,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" "; if(project->first("TEMPLATE") == "app") { QString icon = fileFixify(var("ICON")); - QString bundleIdentifier = "com.yourcompany." + var("QMAKE_BUNDLE"); + QString bundlePrefix = project->first("QMAKE_TARGET_BUNDLE_PREFIX").toQString(); + if (bundlePrefix.isEmpty()) + bundlePrefix = "com.yourcompany."; + QString bundleIdentifier = bundlePrefix + var("QMAKE_BUNDLE"); if (bundleIdentifier.endsWith(".app")) bundleIdentifier.chop(4); t << "@$(DEL_FILE) " << info_plist_out << "\n\t" From 1de244ea65f1b40c488fe92b29170c1b1d447233 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Wed, 22 Jan 2014 14:54:21 +0100 Subject: [PATCH 010/124] network: add support for the SPDY protocol Currently the only supported SPDY version is 3.0. The feature needs to be enabled explicitly via QNetworkRequest::SpdyAllowedAttribute. Whether SPDY actually was used can be determined via QNetworkRequest::SpdyWasUsedAttribute from a QNetworkReply once it has been started (i.e. after the encrypted() signal has been received). Whether SPDY can be used will be determined during the SSL handshake through the TLS NPN extension (see separate commit). The following things from SPDY have not been enabled currently: * server push is not implemented, it has never been seen in the wild; in that case we just reject a stream pushed by the server, which is legit. * settings are not persisted across SPDY sessions. In practice this means that the server sends a small message upon session start telling us e.g. the number of concurrent connections. * SSL client certificates are not supported. Task-number: QTBUG-18714 [ChangeLog][QtNetwork] Added support for the SPDY protocol (version 3.0). Change-Id: I81bbe0495c24ed84e9cf8af3a9dbd63ca1e93d0d Reviewed-by: Richard J. Moore --- src/network/access/access.pri | 2 + src/network/access/qhttpnetworkconnection.cpp | 154 +- src/network/access/qhttpnetworkconnection_p.h | 37 +- .../access/qhttpnetworkconnectionchannel.cpp | 130 +- .../access/qhttpnetworkconnectionchannel_p.h | 8 +- src/network/access/qhttpnetworkreply.cpp | 50 +- src/network/access/qhttpnetworkreply_p.h | 16 +- src/network/access/qhttpnetworkrequest.cpp | 16 +- src/network/access/qhttpnetworkrequest_p.h | 5 + src/network/access/qhttpthreaddelegate.cpp | 38 +- src/network/access/qhttpthreaddelegate_p.h | 4 +- src/network/access/qnetworkaccessmanager.cpp | 13 + src/network/access/qnetworkreplyhttpimpl.cpp | 20 +- src/network/access/qnetworkreplyhttpimpl_p.h | 7 +- src/network/access/qnetworkrequest.cpp | 11 + src/network/access/qnetworkrequest.h | 2 + src/network/access/qspdyprotocolhandler.cpp | 1272 +++++++++++++++++ src/network/access/qspdyprotocolhandler_p.h | 228 +++ tests/auto/network/access/access.pro | 1 + tests/auto/network/access/spdy/spdy.pro | 7 + tests/auto/network/access/spdy/tst_spdy.cpp | 690 +++++++++ .../qnetworkreply/tst_qnetworkreply.cpp | 43 +- tests/manual/qnetworkreply/main.cpp | 220 +++ 23 files changed, 2888 insertions(+), 86 deletions(-) create mode 100644 src/network/access/qspdyprotocolhandler.cpp create mode 100644 src/network/access/qspdyprotocolhandler_p.h create mode 100644 tests/auto/network/access/spdy/spdy.pro create mode 100644 tests/auto/network/access/spdy/tst_spdy.cpp diff --git a/src/network/access/access.pri b/src/network/access/access.pri index 3017417da8..e829d52cbe 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -9,6 +9,7 @@ HEADERS += \ access/qhttpnetworkconnectionchannel_p.h \ access/qabstractprotocolhandler_p.h \ access/qhttpprotocolhandler_p.h \ + access/qspdyprotocolhandler_p.h \ access/qnetworkaccessauthenticationmanager_p.h \ access/qnetworkaccessmanager.h \ access/qnetworkaccessmanager_p.h \ @@ -47,6 +48,7 @@ SOURCES += \ access/qhttpnetworkconnectionchannel.cpp \ access/qabstractprotocolhandler.cpp \ access/qhttpprotocolhandler.cpp \ + access/qspdyprotocolhandler.cpp \ access/qnetworkaccessauthenticationmanager.cpp \ access/qnetworkaccessmanager.cpp \ access/qnetworkaccesscache.cpp \ diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 66c97f7485..6d568220e2 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE -const int QHttpNetworkConnectionPrivate::defaultChannelCount = 6; +const int QHttpNetworkConnectionPrivate::defaultHttpChannelCount = 6; // The pipeline length. So there will be 4 requests in flight. const int QHttpNetworkConnectionPrivate::defaultPipelineLength = 3; @@ -77,20 +77,29 @@ const int QHttpNetworkConnectionPrivate::defaultPipelineLength = 3; const int QHttpNetworkConnectionPrivate::defaultRePipelineLength = 2; -QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt) +QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, + quint16 port, bool encrypt, + QHttpNetworkConnection::ConnectionType type) : state(RunningState), networkLayerState(Unknown), - hostName(hostName), port(port), encrypt(encrypt), delayIpv4(true), - channelCount(defaultChannelCount) + hostName(hostName), port(port), encrypt(encrypt), delayIpv4(true) +#ifndef QT_NO_SSL +, channelCount((type == QHttpNetworkConnection::ConnectionTypeSPDY) ? 1 : defaultHttpChannelCount) +#else +, channelCount(defaultHttpChannelCount) +#endif // QT_NO_SSL #ifndef QT_NO_NETWORKPROXY , networkProxy(QNetworkProxy::NoProxy) #endif , preConnectRequests(0) + , connectionType(type) { channels = new QHttpNetworkConnectionChannel[channelCount]; } -QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt) +QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, + quint16 port, bool encrypt, + QHttpNetworkConnection::ConnectionType type) : state(RunningState), networkLayerState(Unknown), hostName(hostName), port(port), encrypt(encrypt), delayIpv4(true), channelCount(channelCount) @@ -98,6 +107,7 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCoun , networkProxy(QNetworkProxy::NoProxy) #endif , preConnectRequests(0) + , connectionType(type) { channels = new QHttpNetworkConnectionChannel[channelCount]; } @@ -546,15 +556,24 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor if (request.isPreConnect()) preConnectRequests++; - switch (request.priority()) { - case QHttpNetworkRequest::HighPriority: - highPriorityQueue.prepend(pair); - break; - case QHttpNetworkRequest::NormalPriority: - case QHttpNetworkRequest::LowPriority: - lowPriorityQueue.prepend(pair); - break; + if (connectionType == QHttpNetworkConnection::ConnectionTypeHTTP) { + switch (request.priority()) { + case QHttpNetworkRequest::HighPriority: + highPriorityQueue.prepend(pair); + break; + case QHttpNetworkRequest::NormalPriority: + case QHttpNetworkRequest::LowPriority: + lowPriorityQueue.prepend(pair); + break; + } } +#ifndef QT_NO_SSL + else { // SPDY + if (!pair.second->d_func()->requestIsPrepared) + prepareRequest(pair); + channels[0].spdyRequestsToSend.insertMulti(request.priority(), pair); + } +#endif // QT_NO_SSL // For Happy Eyeballs the networkLayerState is set to Unknown // untill we have started the first connection attempt. So no @@ -900,17 +919,39 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() // dequeue new ones - // return fast if there is nothing to do - if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) - return; - // try to get a free AND connected socket - for (int i = 0; i < channelCount; ++i) { - if (channels[i].socket) { - if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { - if (dequeueRequest(channels[i].socket)) - channels[i].sendRequest(); + switch (connectionType) { + case QHttpNetworkConnection::ConnectionTypeHTTP: { + // return fast if there is nothing to do + if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) + return; + + // try to get a free AND connected socket + for (int i = 0; i < channelCount; ++i) { + if (channels[i].socket) { + if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { + if (dequeueRequest(channels[i].socket)) + channels[i].sendRequest(); + } } } + break; + } + case QHttpNetworkConnection::ConnectionTypeSPDY: { +#ifndef QT_NO_SSL + if (channels[0].spdyRequestsToSend.isEmpty()) + return; + + if (networkLayerState == IPv4) + channels[0].networkLayerPreference = QAbstractSocket::IPv4Protocol; + else if (networkLayerState == IPv6) + channels[0].networkLayerPreference = QAbstractSocket::IPv6Protocol; + channels[0].ensureConnection(); + if (channels[0].socket && channels[0].socket->state() == QAbstractSocket::ConnectedState + && !channels[0].pendingEncrypt) + channels[0].sendRequest(); +#endif // QT_NO_SSL + break; + } } // try to push more into all sockets @@ -1059,7 +1100,19 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(QHostInfo info) if (dequeueRequest(channels[0].socket)) { emitReplyError(channels[0].socket, channels[0].reply, QNetworkReply::HostNotFoundError); networkLayerState = QHttpNetworkConnectionPrivate::Unknown; - } else { + } +#ifndef QT_NO_SSL + else if (connectionType == QHttpNetworkConnection::ConnectionTypeSPDY) { + QList spdyPairs = channels[0].spdyRequestsToSend.values(); + for (int a = 0; a < spdyPairs.count(); ++a) { + // emit error for all replies + QHttpNetworkReply *currentReply = spdyPairs.at(a).second; + Q_ASSERT(currentReply); + emitReplyError(channels[0].socket, currentReply, QNetworkReply::HostNotFoundError); + } + } +#endif // QT_NO_SSL + else { // Should not happen qWarning() << "QHttpNetworkConnectionPrivate::_q_hostLookupFinished could not dequeu request"; networkLayerState = QHttpNetworkConnectionPrivate::Unknown; @@ -1127,31 +1180,41 @@ void QHttpNetworkConnectionPrivate::_q_connectDelayedChannel() } #ifndef QT_NO_BEARERMANAGEMENT -QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent, QSharedPointer networkSession) - : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent) +QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, + QHttpNetworkConnection::ConnectionType connectionType, + QObject *parent, QSharedPointer networkSession) + : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt, connectionType)), parent) { Q_D(QHttpNetworkConnection); d->networkSession = networkSession; d->init(); } -QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt, QObject *parent, QSharedPointer networkSession) - : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt)), parent) +QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, + quint16 port, bool encrypt, QObject *parent, + QSharedPointer networkSession, + QHttpNetworkConnection::ConnectionType connectionType) + : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt, + connectionType)), parent) { Q_D(QHttpNetworkConnection); d->networkSession = networkSession; d->init(); } #else -QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent) - : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent) +QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent, + QHttpNetworkConnection::ConnectionType connectionType) + : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt , connectionType)), parent) { Q_D(QHttpNetworkConnection); d->init(); } -QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt, QObject *parent) - : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt)), parent) +QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, + quint16 port, bool encrypt, QObject *parent, + QHttpNetworkConnection::ConnectionType connectionType) + : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt, + connectionType)), parent) { Q_D(QHttpNetworkConnection); d->init(); @@ -1225,6 +1288,17 @@ QNetworkProxy QHttpNetworkConnection::transparentProxy() const } #endif +QHttpNetworkConnection::ConnectionType QHttpNetworkConnection::connectionType() +{ + Q_D(QHttpNetworkConnection); + return d->connectionType; +} + +void QHttpNetworkConnection::setConnectionType(ConnectionType type) +{ + Q_D(QHttpNetworkConnection); + d->connectionType = type; +} // SSL support below #ifndef QT_NO_SSL @@ -1299,7 +1373,23 @@ void QHttpNetworkConnectionPrivate::emitProxyAuthenticationRequired(const QHttpN // Also pause the connection because socket notifiers may fire while an user // dialog is displaying pauseConnection(); - emit chan->reply->proxyAuthenticationRequired(proxy, auth); + QHttpNetworkReply *reply; +#ifndef QT_NO_SSL + if (connectionType == QHttpNetworkConnection::ConnectionTypeSPDY) { + // we choose the reply to emit the proxyAuth signal from somewhat arbitrarily, + // but that does not matter because the signal will ultimately be emitted + // by the QNetworkAccessManager. + Q_ASSERT(chan->spdyRequestsToSend.count() > 0); + reply = chan->spdyRequestsToSend.values().first().second; + } else { // HTTP +#endif // QT_NO_SSL + reply = chan->reply; +#ifndef QT_NO_SSL + } +#endif // QT_NO_SSL + + Q_ASSERT(reply); + emit reply->proxyAuthenticationRequired(proxy, auth); resumeConnection(); int i = indexOf(chan->socket); copyCredentials(i, auth, true); diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 526326c3fd..9d4257e217 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -94,12 +94,27 @@ class Q_AUTOTEST_EXPORT QHttpNetworkConnection : public QObject Q_OBJECT public: + enum ConnectionType { + ConnectionTypeHTTP, + ConnectionTypeSPDY + }; + #ifndef QT_NO_BEARERMANAGEMENT - explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0, QSharedPointer networkSession = QSharedPointer()); - QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0, QSharedPointer networkSession = QSharedPointer()); + explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, + ConnectionType connectionType = ConnectionTypeHTTP, + QObject *parent = 0, QSharedPointer networkSession + = QSharedPointer()); + QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, + bool encrypt = false, QObject *parent = 0, + QSharedPointer networkSession = QSharedPointer(), + ConnectionType connectionType = ConnectionTypeHTTP); #else - explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0); - QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0); + explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, + QObject *parent = 0, + ConnectionType connectionType = ConnectionTypeHTTP); + QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, + bool encrypt = false, QObject *parent = 0, + ConnectionType connectionType = ConnectionTypeHTTP); #endif ~QHttpNetworkConnection(); @@ -123,6 +138,9 @@ public: QHttpNetworkConnectionChannel *channels() const; + ConnectionType connectionType(); + void setConnectionType(ConnectionType type); + #ifndef QT_NO_SSL void setSslConfiguration(const QSslConfiguration &config); void ignoreSslErrors(int channel = -1); @@ -140,6 +158,7 @@ private: friend class QHttpNetworkReplyPrivate; friend class QHttpNetworkConnectionChannel; friend class QHttpProtocolHandler; + friend class QSpdyProtocolHandler; Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest()) Q_PRIVATE_SLOT(d_func(), void _q_hostLookupFinished(QHostInfo)) @@ -155,7 +174,7 @@ class QHttpNetworkConnectionPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QHttpNetworkConnection) public: - static const int defaultChannelCount; + static const int defaultHttpChannelCount; static const int defaultPipelineLength; static const int defaultRePipelineLength; @@ -172,8 +191,10 @@ public: IPv4or6 }; - QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt); - QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt); + QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt, + QHttpNetworkConnection::ConnectionType type); + QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt, + QHttpNetworkConnection::ConnectionType type); ~QHttpNetworkConnectionPrivate(); void init(); @@ -245,6 +266,8 @@ public: int preConnectRequests; + QHttpNetworkConnection::ConnectionType connectionType; + #ifndef QT_NO_SSL QSharedPointer sslContext; #endif diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 6f06c18732..fb40958178 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -50,6 +50,7 @@ #ifndef QT_NO_HTTP #include +#include #ifndef QT_NO_SSL # include @@ -166,9 +167,12 @@ void QHttpNetworkConnectionChannel::init() if (!sslConfiguration.isNull()) sslSocket->setSslConfiguration(sslConfiguration); + } else { +#endif // QT_NO_SSL + protocolHandler.reset(new QHttpProtocolHandler(this)); +#ifndef QT_NO_SSL } #endif - protocolHandler.reset(new QHttpProtocolHandler(this)); #ifndef QT_NO_NETWORKPROXY if (proxy.type() != QNetworkProxy::NoProxy) @@ -879,6 +883,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket if (protocolHandler) protocolHandler->setReply(0); } +#ifndef QT_NO_SSL + else if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY) { + QList spdyPairs = spdyRequestsToSend.values(); + for (int a = 0; a < spdyPairs.count(); ++a) { + // emit error for all replies + QHttpNetworkReply *currentReply = spdyPairs.at(a).second; + Q_ASSERT(currentReply); + emit currentReply->finishedWithError(errorCode, errorString); + } + } +#endif // QT_NO_SSL + // send the next request QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); @@ -889,11 +905,19 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket #ifndef QT_NO_NETWORKPROXY void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth) { - // Need to dequeue the request before we can emit the error. - if (!reply) - connection->d_func()->dequeueRequest(socket); - if (reply) +#ifndef QT_NO_SSL + if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY) { connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth); + } else { // HTTP +#endif // QT_NO_SSL + // Need to dequeue the request before we can emit the error. + if (!reply) + connection->d_func()->dequeueRequest(socket); + if (reply) + connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth); +#ifndef QT_NO_SSL + } +#endif // QT_NO_SSL } #endif @@ -905,16 +929,85 @@ void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead() #ifndef QT_NO_SSL void QHttpNetworkConnectionChannel::_q_encrypted() { + QSslSocket *sslSocket = qobject_cast(socket); + Q_ASSERT(sslSocket); + + if (!protocolHandler) { + switch (sslSocket->sslConfiguration().nextProtocolNegotiationStatus()) { + case QSslConfiguration::NextProtocolNegotiationNegotiated: { + QByteArray nextProtocol = sslSocket->sslConfiguration().nextNegotiatedProtocol(); + if (nextProtocol == QSslConfiguration::NextProtocolHttp1_1) { + // fall through to create a QHttpProtocolHandler + } else if (nextProtocol == QSslConfiguration::NextProtocolSpdy3_0) { + protocolHandler.reset(new QSpdyProtocolHandler(this)); + connection->setConnectionType(QHttpNetworkConnection::ConnectionTypeSPDY); + // no need to re-queue requests, if SPDY was enabled on the request it + // has gone to the SPDY queue already + break; + } else { + emitFinishedWithError(QNetworkReply::SslHandshakeFailedError, + "detected unknown Next Protocol Negotiation protocol"); + break; + } + } + case QSslConfiguration::NextProtocolNegotiationNone: + protocolHandler.reset(new QHttpProtocolHandler(this)); + connection->setConnectionType(QHttpNetworkConnection::ConnectionTypeHTTP); + // re-queue requests from SPDY queue to HTTP queue, if any + requeueSpdyRequests(); + break; + case QSslConfiguration::NextProtocolNegotiationUnsupported: + emitFinishedWithError(QNetworkReply::SslHandshakeFailedError, + "chosen Next Protocol Negotiation value unsupported"); + break; + default: + emitFinishedWithError(QNetworkReply::SslHandshakeFailedError, + "detected unknown Next Protocol Negotiation protocol"); + } + } + if (!socket) return; // ### error state = QHttpNetworkConnectionChannel::IdleState; pendingEncrypt = false; - if (!reply) - connection->d_func()->dequeueRequest(socket); + + if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY) { + // we call setSpdyWasUsed(true) on the replies in the SPDY handler when the request is sent + if (spdyRequestsToSend.count() > 0) + // wait for data from the server first (e.g. initial window, max concurrent requests) + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } else { // HTTP + if (!reply) + connection->d_func()->dequeueRequest(socket); + if (reply) { + reply->setSpdyWasUsed(false); + emit reply->encrypted(); + } + if (reply) + sendRequest(); + } +} + +void QHttpNetworkConnectionChannel::requeueSpdyRequests() +{ + QList spdyPairs = spdyRequestsToSend.values(); + for (int a = 0; a < spdyPairs.count(); ++a) { + connection->d_func()->requeueRequest(spdyPairs.at(a)); + } + spdyRequestsToSend.clear(); +} + +void QHttpNetworkConnectionChannel::emitFinishedWithError(QNetworkReply::NetworkError error, + const char *message) +{ if (reply) - emit reply->encrypted(); - if (reply) - sendRequest(); + emit reply->finishedWithError(error, QHttpNetworkConnectionChannel::tr(message)); + QList spdyPairs = spdyRequestsToSend.values(); + for (int a = 0; a < spdyPairs.count(); ++a) { + QHttpNetworkReply *currentReply = spdyPairs.at(a).second; + Q_ASSERT(currentReply); + emit currentReply->finishedWithError(error, QHttpNetworkConnectionChannel::tr(message)); + } } void QHttpNetworkConnectionChannel::_q_sslErrors(const QList &errors) @@ -927,8 +1020,21 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList &errors) connection->d_func()->pauseConnection(); if (pendingEncrypt && !reply) connection->d_func()->dequeueRequest(socket); - if (reply) - emit reply->sslErrors(errors); + if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) { + if (reply) + emit reply->sslErrors(errors); + } +#ifndef QT_NO_SSL + else { // SPDY + QList spdyPairs = spdyRequestsToSend.values(); + for (int a = 0; a < spdyPairs.count(); ++a) { + // emit SSL errors for all replies + QHttpNetworkReply *currentReply = spdyPairs.at(a).second; + Q_ASSERT(currentReply); + emit currentReply->sslErrors(errors); + } + } +#endif // QT_NO_SSL connection->d_func()->resumeConnection(); } diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 7230eb2543..450b6fc419 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -104,8 +104,8 @@ public: bool ssl; bool isInitialized; ChannelState state; - QHttpNetworkRequest request; // current request - QHttpNetworkReply *reply; // current reply for this request + QHttpNetworkRequest request; // current request, only used for HTTP + QHttpNetworkReply *reply; // current reply for this request, only used for HTTP qint64 written; qint64 bytesTotal; bool resendCurrent; @@ -123,9 +123,13 @@ public: bool ignoreAllSslErrors; QList ignoreSslErrorsList; QSslConfiguration sslConfiguration; + QMultiMap spdyRequestsToSend; // sorted by priority void ignoreSslErrors(); void ignoreSslErrors(const QList &errors); void setSslConfiguration(const QSslConfiguration &config); + void requeueSpdyRequests(); // when we wanted SPDY but got HTTP + // to emit the signal for all in-flight replies: + void emitFinishedWithError(QNetworkReply::NetworkError error, const char *message); #endif #ifndef QT_NO_BEARERMANAGEMENT QSharedPointer networkSession; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 1b9e1f5a53..2a7e6ed638 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -265,6 +265,16 @@ bool QHttpNetworkReply::isPipeliningUsed() const return d_func()->pipeliningUsed; } +bool QHttpNetworkReply::isSpdyUsed() const +{ + return d_func()->spdyUsed; +} + +void QHttpNetworkReply::setSpdyWasUsed(bool spdy) +{ + d_func()->spdyUsed = spdy; +} + QHttpNetworkConnection* QHttpNetworkReply::connection() { return d_func()->connection; @@ -281,9 +291,15 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) connectionCloseEnabled(true), forceConnectionCloseEnabled(false), lastChunkRead(false), - currentChunkSize(0), currentChunkRead(0), readBufferMaxSize(0), connection(0), + currentChunkSize(0), currentChunkRead(0), readBufferMaxSize(0), + windowSizeDownload(65536), // 64K initial window size according to SPDY standard + windowSizeUpload(65536), // 64K initial window size according to SPDY standard + currentlyReceivedDataInWindow(0), + currentlyUploadedDataInWindow(0), + totallyUploadedData(0), + connection(0), autoDecompress(false), responseData(), requestIsPrepared(false) - ,pipeliningUsed(false), downstreamLimited(false) + ,pipeliningUsed(false), spdyUsed(false), downstreamLimited(false) ,userProvidedDownloadBuffer(0) #ifndef QT_NO_COMPRESS ,inflateStrm(0) @@ -550,15 +566,7 @@ qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) // allocate inflate state if (!inflateStrm) inflateStrm = new z_stream; - inflateStrm->zalloc = Z_NULL; - inflateStrm->zfree = Z_NULL; - inflateStrm->opaque = Z_NULL; - inflateStrm->avail_in = 0; - inflateStrm->next_in = Z_NULL; - // "windowBits can also be greater than 15 for optional gzip decoding. - // Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection" - // http://www.zlib.net/manual.html - int ret = inflateInit2(inflateStrm, MAX_WBITS+32); + int ret = initializeInflateStream(); if (ret != Z_OK) return -1; } @@ -703,8 +711,28 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuff } #ifndef QT_NO_COMPRESS +int QHttpNetworkReplyPrivate::initializeInflateStream() +{ + inflateStrm->zalloc = Z_NULL; + inflateStrm->zfree = Z_NULL; + inflateStrm->opaque = Z_NULL; + inflateStrm->avail_in = 0; + inflateStrm->next_in = Z_NULL; + // "windowBits can also be greater than 15 for optional gzip decoding. + // Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection" + // http://www.zlib.net/manual.html + int ret = inflateInit2(inflateStrm, MAX_WBITS+32); + Q_ASSERT(ret == Z_OK); + return ret; +} + qint64 QHttpNetworkReplyPrivate::uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out) { + if (!inflateStrm) { // happens when called from the SPDY protocol handler + inflateStrm = new z_stream; + initializeInflateStream(); + } + if (!inflateStrm) return -1; diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 583c3e426f..e15ace0072 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -132,6 +132,8 @@ public: bool isFinished() const; bool isPipeliningUsed() const; + bool isSpdyUsed() const; + void setSpdyWasUsed(bool spdy); QHttpNetworkConnection* connection(); @@ -165,6 +167,7 @@ private: friend class QHttpNetworkConnectionPrivate; friend class QHttpNetworkConnectionChannel; friend class QHttpProtocolHandler; + friend class QSpdyProtocolHandler; }; @@ -205,7 +208,11 @@ public: ReadingStatusState, ReadingHeaderState, ReadingDataState, - AllDoneState + AllDoneState, + SPDYSYNSent, + SPDYUploading, + SPDYHalfClosed, + SPDYClosed } state; QHttpNetworkRequest request; @@ -226,6 +233,11 @@ public: qint64 currentChunkSize; qint64 currentChunkRead; qint64 readBufferMaxSize; + qint32 windowSizeDownload; // only for SPDY + qint32 windowSizeUpload; // only for SPDY + qint32 currentlyReceivedDataInWindow; // only for SPDY + qint32 currentlyUploadedDataInWindow; // only for SPDY + qint64 totallyUploadedData; // only for SPDY QPointer connection; QPointer connectionChannel; @@ -236,12 +248,14 @@ public: bool requestIsPrepared; bool pipeliningUsed; + bool spdyUsed; bool downstreamLimited; char* userProvidedDownloadBuffer; #ifndef QT_NO_COMPRESS z_stream_s *inflateStrm; + int initializeInflateStream(); qint64 uncompressBodyData(QByteDataBuffer *in, QByteDataBuffer *out); #endif }; diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 3786f9b992..6e9f1216c3 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -49,8 +49,8 @@ QT_BEGIN_NAMESPACE QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, QHttpNetworkRequest::Priority pri, const QUrl &newUrl) : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0), - autoDecompress(false), pipeliningAllowed(false), withCredentials(true), - preConnect(false) + autoDecompress(false), pipeliningAllowed(false), spdyAllowed(false), + withCredentials(true), preConnect(false) { } @@ -62,6 +62,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest uploadByteDevice = other.uploadByteDevice; autoDecompress = other.autoDecompress; pipeliningAllowed = other.pipeliningAllowed; + spdyAllowed = other.spdyAllowed; customVerb = other.customVerb; withCredentials = other.withCredentials; ssl = other.ssl; @@ -80,6 +81,7 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot && (uploadByteDevice == other.uploadByteDevice) && (autoDecompress == other.autoDecompress) && (pipeliningAllowed == other.pipeliningAllowed) + && (spdyAllowed == other.spdyAllowed) // we do not clear the customVerb in setOperation && (operation != QHttpNetworkRequest::Custom || (customVerb == other.customVerb)) && (withCredentials == other.withCredentials) @@ -299,6 +301,16 @@ void QHttpNetworkRequest::setPipeliningAllowed(bool b) d->pipeliningAllowed = b; } +bool QHttpNetworkRequest::isSPDYAllowed() const +{ + return d->spdyAllowed; +} + +void QHttpNetworkRequest::setSPDYAllowed(bool b) +{ + d->spdyAllowed = b; +} + bool QHttpNetworkRequest::withCredentials() const { return d->withCredentials; diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index f224f7329d..09847d715c 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -114,6 +114,9 @@ public: bool isPipeliningAllowed() const; void setPipeliningAllowed(bool b); + bool isSPDYAllowed() const; + void setSPDYAllowed(bool b); + bool withCredentials() const; void setWithCredentials(bool b); @@ -135,6 +138,7 @@ private: friend class QHttpNetworkConnectionPrivate; friend class QHttpNetworkConnectionChannel; friend class QHttpProtocolHandler; + friend class QSpdyProtocolHandler; }; class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate @@ -154,6 +158,7 @@ public: mutable QNonContiguousByteDevice* uploadByteDevice; bool autoDecompress; bool pipeliningAllowed; + bool spdyAllowed; bool withCredentials; bool ssl; bool preConnect; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index b7e8bb3f72..e03dcb8ead 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -180,11 +180,15 @@ class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection, // Q_OBJECT public: #ifdef QT_NO_BEARERMANAGEMENT - QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt) - : QHttpNetworkConnection(hostName, port, encrypt) + QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt, + QHttpNetworkConnection::ConnectionType connectionType) + : QHttpNetworkConnection(hostName, port, encrypt, connectionType) #else - QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt, QSharedPointer networkSession) - : QHttpNetworkConnection(hostName, port, encrypt, /*parent=*/0, networkSession) + QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt, + QHttpNetworkConnection::ConnectionType connectionType, + QSharedPointer networkSession) + : QHttpNetworkConnection(hostName, port, encrypt, connectionType, /*parent=*/0, + networkSession) #endif { setExpires(true); @@ -230,6 +234,7 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) : , synchronous(false) , incomingStatusCode(0) , isPipeliningUsed(false) + , isSpdyUsed(false) , incomingContentLength(-1) , incomingErrorCode(QNetworkReply::NoError) , downloadBuffer(0) @@ -281,6 +286,19 @@ void QHttpThreadDelegate::startRequest() QUrl urlCopy = httpRequest.url(); urlCopy.setPort(urlCopy.port(ssl ? 443 : 80)); + QHttpNetworkConnection::ConnectionType connectionType + = QHttpNetworkConnection::ConnectionTypeHTTP; +#ifndef QT_NO_SSL + if (httpRequest.isSPDYAllowed() && ssl) { + connectionType = QHttpNetworkConnection::ConnectionTypeSPDY; + urlCopy.setScheme(QStringLiteral("spdy")); // to differentiate SPDY requests from HTTPS requests + QList nextProtocols; + nextProtocols << QSslConfiguration::NextProtocolSpdy3_0 + << QSslConfiguration::NextProtocolHttp1_1; + incomingSslConfiguration.setAllowedNextProtocols(nextProtocols); + } +#endif // QT_NO_SSL + #ifndef QT_NO_NETWORKPROXY if (transparentProxy.type() != QNetworkProxy::NoProxy) cacheKey = makeCacheKey(urlCopy, &transparentProxy); @@ -297,9 +315,12 @@ void QHttpThreadDelegate::startRequest() // no entry in cache; create an object // the http object is actually a QHttpNetworkConnection #ifdef QT_NO_BEARERMANAGEMENT - httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl); + httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl, + connectionType); #else - httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl, networkSession); + httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl, + connectionType, + networkSession); #endif #ifndef QT_NO_SSL // Set the QSslConfiguration from this QNetworkRequest. @@ -575,13 +596,15 @@ void QHttpThreadDelegate::headerChangedSlot() incomingReasonPhrase = httpReply->reasonPhrase(); isPipeliningUsed = httpReply->isPipeliningUsed(); incomingContentLength = httpReply->contentLength(); + isSpdyUsed = httpReply->isSpdyUsed(); emit downloadMetaData(incomingHeaders, incomingStatusCode, incomingReasonPhrase, isPipeliningUsed, downloadBuffer, - incomingContentLength); + incomingContentLength, + isSpdyUsed); } void QHttpThreadDelegate::synchronousHeaderChangedSlot() @@ -597,6 +620,7 @@ void QHttpThreadDelegate::synchronousHeaderChangedSlot() incomingStatusCode = httpReply->statusCode(); incomingReasonPhrase = httpReply->reasonPhrase(); isPipeliningUsed = httpReply->isPipeliningUsed(); + isSpdyUsed = httpReply->isSpdyUsed(); incomingContentLength = httpReply->contentLength(); } diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h index d9ef1a0a55..6e6d3b5797 100644 --- a/src/network/access/qhttpthreaddelegate_p.h +++ b/src/network/access/qhttpthreaddelegate_p.h @@ -111,6 +111,7 @@ public: int incomingStatusCode; QString incomingReasonPhrase; bool isPipeliningUsed; + bool isSpdyUsed; qint64 incomingContentLength; QNetworkReply::NetworkError incomingErrorCode; QString incomingErrorDetail; @@ -139,7 +140,8 @@ signals: void sslErrors(const QList &, bool *, QList *); void sslConfigurationChanged(const QSslConfiguration); #endif - void downloadMetaData(QList >,int,QString,bool,QSharedPointer,qint64); + void downloadMetaData(QList >, int, QString, bool, + QSharedPointer, qint64, bool); void downloadProgress(qint64, qint64); void downloadData(QByteArray); void error(QNetworkReply::NetworkError, const QString); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index c89419091f..473acc5f22 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -977,6 +977,12 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess \a sslConfiguration. This function is useful to complete the TCP and SSL handshake to a host before the HTTPS request is made, resulting in a lower network latency. + \note Preconnecting a SPDY connection can be done by calling setAllowedNextProtocols() + on \a sslConfiguration with QSslConfiguration::NextProtocolSpdy3_0 contained in + the list of allowed protocols. When using SPDY, one single connection per host is + enough, i.e. calling this method multiple times per host will not result in faster + network transactions. + \note This function has no possibility to report errors. \sa connectToHost(), get(), post(), put(), deleteResource() @@ -991,6 +997,13 @@ void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quin QNetworkRequest request(url); if (sslConfiguration != QSslConfiguration::defaultConfiguration()) request.setSslConfiguration(sslConfiguration); + + // There is no way to enable SPDY via a request, so we need to check + // the ssl configuration whether SPDY is allowed here. + if (sslConfiguration.allowedNextProtocols().contains( + QSslConfiguration::NextProtocolSpdy3_0)) + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); + get(request); } #endif diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 29d23bfd8f..de4c8d0964 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -752,6 +752,9 @@ void QNetworkReplyHttpImplPrivate::postRequest() if (request.attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true) httpRequest.setPipeliningAllowed(true); + if (request.attribute(QNetworkRequest::SpdyAllowedAttribute).toBool() == true) + httpRequest.setSPDYAllowed(true); + if (static_cast (request.attribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Manual) @@ -811,8 +814,12 @@ void QNetworkReplyHttpImplPrivate::postRequest() QObject::connect(delegate, SIGNAL(downloadFinished()), q, SLOT(replyFinished()), Qt::QueuedConnection); - QObject::connect(delegate, SIGNAL(downloadMetaData(QList >,int,QString,bool,QSharedPointer,qint64)), - q, SLOT(replyDownloadMetaData(QList >,int,QString,bool,QSharedPointer,qint64)), + QObject::connect(delegate, SIGNAL(downloadMetaData(QList >, + int, QString, bool, + QSharedPointer, qint64, bool)), + q, SLOT(replyDownloadMetaData(QList >, + int, QString, bool, + QSharedPointer, qint64, bool)), Qt::QueuedConnection); QObject::connect(delegate, SIGNAL(downloadProgress(qint64,qint64)), q, SLOT(replyDownloadProgressSlot(qint64,qint64)), @@ -907,7 +914,8 @@ void QNetworkReplyHttpImplPrivate::postRequest() delegate->incomingReasonPhrase, delegate->isPipeliningUsed, QSharedPointer(), - delegate->incomingContentLength); + delegate->incomingContentLength, + delegate->isSpdyUsed); replyDownloadData(delegate->synchronousDownloadData); httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail); } else { @@ -917,7 +925,8 @@ void QNetworkReplyHttpImplPrivate::postRequest() delegate->incomingReasonPhrase, delegate->isPipeliningUsed, QSharedPointer(), - delegate->incomingContentLength); + delegate->incomingContentLength, + delegate->isSpdyUsed); replyDownloadData(delegate->synchronousDownloadData); } @@ -1074,7 +1083,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData (QList > hm, int sc,QString rp,bool pu, QSharedPointer db, - qint64 contentLength) + qint64 contentLength, bool spdyWasUsed) { Q_Q(QNetworkReplyHttpImpl); Q_UNUSED(contentLength); @@ -1091,6 +1100,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData } q->setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, pu); + q->setAttribute(QNetworkRequest::SpdyWasUsedAttribute, spdyWasUsed); // reconstruct the HTTP header QList > headerMap = hm; diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index 15cc0ec476..aa2d6f0ec9 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -111,7 +111,9 @@ public: // From reply Q_PRIVATE_SLOT(d_func(), void replyDownloadData(QByteArray)) Q_PRIVATE_SLOT(d_func(), void replyFinished()) - Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList >,int,QString,bool,QSharedPointer,qint64)) + Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList >, + int, QString, bool, QSharedPointer, + qint64, bool)) Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64)) Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *)) Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &)) @@ -276,7 +278,8 @@ public: // From HTTP thread: void replyDownloadData(QByteArray); void replyFinished(); - void replyDownloadMetaData(QList >,int,QString,bool,QSharedPointer,qint64); + void replyDownloadMetaData(QList >, int, QString, bool, + QSharedPointer, qint64, bool); void replyDownloadProgressSlot(qint64,qint64); void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpError(QNetworkReply::NetworkError error, const QString &errorString); diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 65fd693771..aa1102f9bf 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -246,6 +246,17 @@ QT_BEGIN_NAMESPACE The QNetworkSession ConnectInBackground property will be set according to this attribute. + \value SpdyAllowedAttribute + Requests only, type: QMetaType::Bool (default: false) + Indicates whether the QNetworkAccessManager code is + allowed to use SPDY with this request. This applies only + to SSL requests, and depends on the server supporting SPDY. + + \value SpdyWasUsedAttribute + Replies only, type: QMetaType::Bool + Indicates whether SPDY was used for receiving + this reply. + \value User Special type. Additional information can be passed in QVariants with types ranging from User to UserMax. The default diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 1512c6dadd..27b02a89ef 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -86,6 +86,8 @@ public: DownloadBufferAttribute, // internal SynchronousRequestAttribute, // internal BackgroundRequestAttribute, + SpdyAllowedAttribute, + SpdyWasUsedAttribute, User = 1000, UserMax = 32767 diff --git a/src/network/access/qspdyprotocolhandler.cpp b/src/network/access/qspdyprotocolhandler.cpp new file mode 100644 index 0000000000..f12b9535fe --- /dev/null +++ b/src/network/access/qspdyprotocolhandler.cpp @@ -0,0 +1,1272 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#if !defined(QT_NO_HTTP) && !defined(QT_NO_SSL) + +QT_BEGIN_NAMESPACE + +static const char spdyDictionary[] = { + 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // ....opti + 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // ons....h + 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // ead....p + 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // ost....p + 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // ut....de + 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // lete.... + 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // trace... + 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // .accept. + 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep + 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t-charse + 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t....acc + 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ept-enco + 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // ding.... + 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // accept-l + 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // anguage. + 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep + 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t-ranges + 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // ....age. + 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // ...allow + 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // ....auth + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // orizatio + 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n....cac + 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // he-contr + 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // ol....co + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // nnection + 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // ....cont + 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // ent-base + 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // ....cont + 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ent-enco + 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // ding.... + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // content- + 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // language + 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // ....cont + 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // ent-leng + 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // th....co + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // ntent-lo + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // cation.. + 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten + 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t-md5... + 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // .content + 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // -range.. + 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten + 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t-type.. + 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // ..date.. + 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // ..etag.. + 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // ..expect + 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // ....expi + 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // res....f + 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // rom....h + 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // ost....i + 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f-match. + 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // ...if-mo + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // dified-s + 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // ince.... + 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // if-none- + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // match... + 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // .if-rang + 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e....if- + 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // unmodifi + 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // ed-since + 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // ....last + 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // -modifie + 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d....loc + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // ation... + 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // .max-for + 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // wards... + 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // .pragma. + 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // ...proxy + 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // -authent + 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // icate... + 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // .proxy-a + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // uthoriza + 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // tion.... + 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // range... + 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // .referer + 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // ....retr + 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y-after. + 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // ...serve + 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r....te. + 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // ...trail + 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // er....tr + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // ansfer-e + 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // ncoding. + 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // ...upgra + 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // de....us + 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // er-agent + 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // ....vary + 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // ....via. + 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // ...warni + 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // ng....ww + 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w-authen + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // ticate.. + 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // ..method + 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // ....get. + 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // ...statu + 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s....200 + 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // .OK....v + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // ersion.. + 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // ..HTTP.1 + 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // .1....ur + 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l....pub + 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // lic....s + 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // et-cooki + 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e....kee + 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p-alive. + 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // ...origi + 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n1001012 + 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 01202205 + 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 20630030 + 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 23033043 + 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 05306307 + 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 40240540 + 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 64074084 + 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 09410411 + 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 41241341 + 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 44154164 + 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 17502504 + 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 505203.N + 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // on-Autho + 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // ritative + 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // .Informa + 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // tion204. + 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // No.Conte + 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // nt301.Mo + 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // ved.Perm + 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // anently4 + 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 00.Bad.R + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // equest40 + 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1.Unauth + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // orized40 + 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3.Forbid + 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // den404.N + 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // ot.Found + 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 500.Inte + 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // rnal.Ser + 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // ver.Erro + 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r501.Not + 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // .Impleme + 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // nted503. + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // Service. + 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // Unavaila + 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // bleJan.F + 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // eb.Mar.A + 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // pr.May.J + 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // un.Jul.A + 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // ug.Sept. + 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // Oct.Nov. + 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // Dec.00.0 + 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0.00.Mon + 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // ..Tue..W + 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // ed..Thu. + 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // .Fri..Sa + 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t..Sun.. + 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // GMTchunk + 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // ed.text. + 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // html.ima + 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // ge.png.i + 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // mage.jpg + 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // .image.g + 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // if.appli + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x + 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // ml.appli + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x + 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // html.xml + 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // .text.pl + 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // ain.text + 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // .javascr + 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // ipt.publ + 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // icprivat + 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // emax-age + 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // .gzip.de + 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // flate.sd + 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // chcharse + 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t.utf-8c + 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i + 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859- + 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-.. + 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0. +}; + +// uncomment to debug +//static void printHex(const QByteArray &ba) +//{ +// QByteArray hex; +// QByteArray clearText; +// for (int a = 0; a < ba.count(); ++a) { +// QByteArray currentHexChar = QByteArray(1, ba.at(a)).toHex().rightJustified(2, ' '); +// QByteArray currentChar; +// if (ba.at(a) >= 32 && ba.at(a) < 126) { // if ASCII, print the letter +// currentChar = QByteArray(1, ba.at(a)); +// } else { +// currentChar = " "; +// } +// clearText.append(currentChar.rightJustified(2, ' ')); +// hex.append(currentHexChar); +// hex.append(' '); +// clearText.append(' '); +// } +// int chunkSize = 102; // 12 == 4 bytes per line +// for (int a = 0; a < hex.count(); a += chunkSize) { +// qDebug() << hex.mid(a, chunkSize); +// qDebug() << clearText.mid(a, chunkSize); +// } +//} + +QSpdyProtocolHandler::QSpdyProtocolHandler(QHttpNetworkConnectionChannel *channel) + : QObject(0), QAbstractProtocolHandler(channel), + m_nextStreamID(-1), + m_maxConcurrentStreams(100), // 100 is recommended in the SPDY RFC + m_initialWindowSize(0), + m_waitingForCompleteStream(false) +{ + m_inflateStream.zalloc = Z_NULL; + m_inflateStream.zfree = Z_NULL; + m_inflateStream.opaque = Z_NULL; + int zlibRet = inflateInit(&m_inflateStream); + Q_ASSERT(zlibRet == Z_OK); + + m_deflateStream.zalloc = Z_NULL; + m_deflateStream.zfree = Z_NULL; + m_deflateStream.opaque = Z_NULL; + + // Do actually not compress (i.e. compression level = 0) + // when sending the headers because of the CRIME attack + zlibRet = deflateInit(&m_deflateStream, /* compression level = */ 0); + Q_ASSERT(zlibRet == Z_OK); +} + +QSpdyProtocolHandler::~QSpdyProtocolHandler() +{ + deflateEnd(&m_deflateStream); + deflateEnd(&m_inflateStream); +} + +bool QSpdyProtocolHandler::sendRequest() +{ + Q_ASSERT(!m_reply); + + int maxPossibleRequests = m_maxConcurrentStreams - m_inFlightStreams.count(); + Q_ASSERT(maxPossibleRequests >= 0); + if (maxPossibleRequests == 0) + return true; // return early if max concurrent requests are exceeded + + m_channel->state = QHttpNetworkConnectionChannel::WritingState; + + // requests will be ordered by priority (see QMultiMap doc) + QList requests = m_channel->spdyRequestsToSend.values(); + QList priorities = m_channel->spdyRequestsToSend.keys(); + + int requestsToSend = qMin(requests.count(), maxPossibleRequests); + + for (int a = 0; a < requestsToSend; ++a) { + HttpMessagePair currentPair = requests.at(a); + QHttpNetworkRequest currentRequest = requests.at(a).first; + QHttpNetworkReply *currentReply = requests.at(a).second; + + currentReply->setSpdyWasUsed(true); + qint32 streamID = generateNextStreamID(); + + currentReply->setRequest(currentRequest); + currentReply->d_func()->connection = m_connection; + currentReply->d_func()->connectionChannel = m_channel; + m_inFlightStreams.insert(streamID, currentPair); + + sendSYN_STREAM(currentPair, streamID, /* associatedToStreamID = */ 0); + int requestsRemoved = m_channel->spdyRequestsToSend.remove( + priorities.at(a), currentPair); + Q_ASSERT(requestsRemoved == 1); + Q_UNUSED(requestsRemoved); // silence -Wunused-variable + } + m_channel->state = QHttpNetworkConnectionChannel::IdleState; + return true; +} + +void QSpdyProtocolHandler::_q_receiveReply() +{ + Q_ASSERT(m_socket); + + // only run when the QHttpNetworkConnection is not currently being destructed, e.g. + // this function is called from _q_disconnected which is called because + // of ~QHttpNetworkConnectionPrivate + if (!qobject_cast(m_connection)) { + return; + } + + if (bytesAvailable() < 8) + return; // cannot read frame headers, wait for more data + + char frameHeadersRaw[8]; + if (!readNextChunk(8, frameHeadersRaw)) + return; // this should not happen, we just checked + + const QByteArray frameHeaders(frameHeadersRaw, 8); // ### try without memcpy + if (frameHeadersRaw[0] & 0x80) { + handleControlFrame(frameHeaders); + } else { + handleDataFrame(frameHeaders); + } + + // after handling the current frame, check whether there is more data waiting + if (m_socket->bytesAvailable() > 0) + QMetaObject::invokeMethod(m_channel, "_q_receiveReply", Qt::QueuedConnection); +} + +void QSpdyProtocolHandler::_q_readyRead() +{ + _q_receiveReply(); +} + +static qint16 twoBytesToInt(const char *bytes) +{ + return qFromBigEndian(reinterpret_cast(bytes)); +} + +static qint32 threeBytesToInt(const char *bytes) +{ + return qFromBigEndian(reinterpret_cast(bytes)) >> 8; +} + +static qint32 fourBytesToInt(const char *bytes) +{ + return qFromBigEndian(reinterpret_cast(bytes)); +} + +static void appendIntToThreeBytes(char *output, qint32 number) +{ + qToBigEndian(number, reinterpret_cast(output + 1)); + qToBigEndian(number >> 16, reinterpret_cast(output)); +} + +static void appendIntToFourBytes(char *output, qint32 number) +{ + qToBigEndian(number, reinterpret_cast(output)); +} + +static QByteArray intToFourBytes(qint32 number) // ### try to use appendIntToFourBytes where possible +{ + uchar data[4]; + qToBigEndian(number, data); + QByteArray ret(reinterpret_cast(data), 4); + return ret; +} + +static QByteArray intToThreeBytes(qint32 number) +{ + uchar data[4]; + qToBigEndian(number << 8, data); + QByteArray ret(reinterpret_cast(data), 3); + return ret; +} + +static qint32 getStreamID(const char *bytes) +{ + // eliminate most significant bit; it might be 0 or 1 depending on whether + // we are dealing with a control or data frame + return fourBytesToInt(bytes) & 0x3fffffff; +} + +static QByteArray headerField(const QByteArray &name, const QByteArray &value) +{ + QByteArray ret; + ret.reserve(name.count() + value.count() + 8); // 4 byte for length each + ret.append(intToFourBytes(name.count())); + ret.append(name); + ret.append(intToFourBytes(value.count())); + ret.append(value); + return ret; +} + +bool QSpdyProtocolHandler::uncompressHeader(const QByteArray &input, QByteArray *output) +{ + const size_t chunkSize = 1024; + char outputRaw[chunkSize]; + // input bytes will not be changed by zlib, so it is safe to const_cast here + m_inflateStream.next_in = const_cast(reinterpret_cast(input.constData())); + m_inflateStream.avail_in = input.count(); + m_inflateStream.total_in = input.count(); + int zlibRet; + + do { + m_inflateStream.next_out = reinterpret_cast(outputRaw); + m_inflateStream.avail_out = chunkSize; + zlibRet = inflate(&m_inflateStream, Z_SYNC_FLUSH); + if (zlibRet == Z_NEED_DICT) { + zlibRet = inflateSetDictionary(&m_inflateStream, + reinterpret_cast(spdyDictionary), + /* dictionaryLength = */ 1423); + Q_ASSERT(zlibRet == Z_OK); + continue; + } + switch (zlibRet) { + case Z_BUF_ERROR: { + if (m_inflateStream.avail_in == 0) { + int outputSize = chunkSize - m_inflateStream.avail_out; + output->append(outputRaw, outputSize); + m_inflateStream.avail_out = chunkSize; + } + break; + } + case Z_OK: { + int outputSize = chunkSize - m_inflateStream.avail_out; + output->append(outputRaw, outputSize); + break; + } + default: { + qWarning() << Q_FUNC_INFO << "got unexpected zlib return value:" << zlibRet; + return false; + } + } + } while (m_inflateStream.avail_in > 0 && zlibRet != Z_STREAM_END); + + Q_ASSERT(m_inflateStream.avail_in == 0); + return true; +} + +QByteArray QSpdyProtocolHandler::composeHeader(const QHttpNetworkRequest &request) +{ + QByteArray uncompressedHeader; + uncompressedHeader.reserve(300); // rough estimate + + // calculate additional headers first, because we need to know the size + // ### do not partially copy the list, but restrict the set header fields + // in QHttpNetworkConnection + QList > additionalHeaders; + for (int a = 0; a < request.header().count(); ++a) { + QByteArray key = request.header().at(a).first; + if (key == "Connection" || key == "Host" || key == "Keep-Alive" + || key == "Proxy-Connection" || key == "Transfer-Encoding") + continue; // those headers are not valid (section 3.2.1) + additionalHeaders.append(request.header().at(a)); + } + + qint32 numberOfHeaderPairs = 5 + additionalHeaders.count(); // 5 mandatory below + the additional ones + uncompressedHeader.append(intToFourBytes(numberOfHeaderPairs)); + + // mandatory header fields: + + uncompressedHeader.append(headerField(":method", request.methodName())); +#ifndef QT_NO_NETWORKPROXY + bool useProxy = m_connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy; + uncompressedHeader.append(headerField(":path", request.uri(useProxy))); +#else + uncompressedHeader.append(headerField(":path", request.uri(false))); +#endif + uncompressedHeader.append(headerField(":version", "HTTP/1.1")); + + QHostAddress add; // ### unify with the host parsing from QHttpNetworkConnection + QByteArray host; + QString hostName = m_connection->hostName(); + if (add.setAddress(hostName)) { + if (add.protocol() == QAbstractSocket::IPv6Protocol) + host = "[" + hostName.toLatin1() + "]"; //format the ipv6 in the standard way + else + host = hostName.toLatin1(); + + } else { + host = QUrl::toAce(hostName); + } + + int port = request.url().port(); + if (port != -1) { + host += ':'; + host += QByteArray::number(port); + } + uncompressedHeader.append(headerField(":host", host)); + + uncompressedHeader.append(headerField(":scheme", request.url().scheme().toLatin1())); + + // end of mandatory header fields + + // now add the additional headers + for (int a = 0; a < additionalHeaders.count(); ++a) { + uncompressedHeader.append(headerField(additionalHeaders.at(a).first.toLower(), + additionalHeaders.at(a).second)); + } + + m_deflateStream.total_in = uncompressedHeader.count(); + m_deflateStream.avail_in = uncompressedHeader.count(); + m_deflateStream.next_in = reinterpret_cast(uncompressedHeader.data()); + int outputBytes = uncompressedHeader.count() + 30; // 30 bytes of compression header overhead + m_deflateStream.avail_out = outputBytes; + unsigned char *out = new unsigned char[outputBytes]; + m_deflateStream.next_out = out; + int availOutBefore = m_deflateStream.avail_out; + int zlibRet = deflate(&m_deflateStream, Z_SYNC_FLUSH); // do everything in one go since we use no compression + int compressedHeaderSize = availOutBefore - m_deflateStream.avail_out; + Q_ASSERT(zlibRet == Z_OK); // otherwise, we need to allocate more outputBytes + Q_UNUSED(zlibRet); // silence -Wunused-variable + Q_ASSERT(m_deflateStream.avail_in == 0); + QByteArray compressedHeader(reinterpret_cast(out), compressedHeaderSize); + delete[] out; + + return compressedHeader; +} + +quint64 QSpdyProtocolHandler::bytesAvailable() const +{ + Q_ASSERT(m_socket); + return m_spdyBuffer.byteAmount() + m_socket->bytesAvailable(); +} + +bool QSpdyProtocolHandler::readNextChunk(qint64 length, char *sink) +{ + qint64 expectedReadBytes = length; + qint64 requiredBytesFromBuffer = 0; + + if (m_waitingForCompleteStream) { + requiredBytesFromBuffer = qMin(length, m_spdyBuffer.byteAmount()); + // ### if next chunk from buffer bigger than what we want to read, + // we have to call read() (which memcpy's). Otherwise, we can just + // read the next chunk without memcpy'ing. + qint64 bytesReadFromBuffer = m_spdyBuffer.read(sink, requiredBytesFromBuffer); + Q_ASSERT(bytesReadFromBuffer == requiredBytesFromBuffer); + if (length <= bytesReadFromBuffer) { + return true; // buffer > required size -> no need to read from socket + } + expectedReadBytes -= requiredBytesFromBuffer; + } + qint64 readBytes = m_socket->read(sink + requiredBytesFromBuffer, expectedReadBytes); + + if (readBytes < expectedReadBytes) { + m_waitingForCompleteStream = true; + // ### this is inefficient, we should not put back so much data into the buffer + QByteArray temp(sink, requiredBytesFromBuffer + readBytes); + m_spdyBuffer.append(temp); + return false; + } else { + return true; // buffer must be cleared by calling function + } +} + +void QSpdyProtocolHandler::sendControlFrame(FrameType type, + ControlFrameFlags flags, + const char *data, + quint32 length) +{ + // frame type and stream ID + char header[8]; + header[0] = 0x80; // leftmost bit == 1 -> is a control frame + header[1] = 0x03; // 3 bit == version 3 + header[2] = 0; + switch (type) { + case FrameType_CREDENTIAL: { + qWarning("sending SPDY CREDENTIAL frame is not yet implemented"); // QTBUG-36188 + return; + } + default: + header[3] = type; + } + + // flags + header[4] = 0; + if (flags & ControlFrame_FLAG_FIN || length == 0) { + Q_ASSERT(type == FrameType_SYN_STREAM || type == FrameType_SYN_REPLY + || type == FrameType_HEADERS || length == 0); + header[4] |= ControlFrame_FLAG_FIN; + } + if (flags & ControlFrame_FLAG_UNIDIRECTIONAL) { + Q_ASSERT(type == FrameType_SYN_STREAM); + header[4] |= ControlFrame_FLAG_UNIDIRECTIONAL; + } + + // length + appendIntToThreeBytes(header + 5, length); + + qint64 written = m_socket->write(header, 8); + Q_ASSERT(written == 8); + written = m_socket->write(data, length); + Q_ASSERT(written == length); +} + +void QSpdyProtocolHandler::sendSYN_STREAM(HttpMessagePair messagePair, + qint32 streamID, qint32 associatedToStreamID) +{ + QHttpNetworkRequest request = messagePair.first; + QHttpNetworkReply *reply = messagePair.second; + + ControlFrameFlags flags = 0; + + if (!request.uploadByteDevice()) { + // no upload -> this is the last frame, send the FIN flag + flags |= ControlFrame_FLAG_FIN; + reply->d_func()->state = QHttpNetworkReplyPrivate::SPDYHalfClosed; + } else { + reply->d_func()->state = QHttpNetworkReplyPrivate::SPDYUploading; + + // hack: set the stream ID on the device directly, so when we get + // the signal for uploading we know which stream we are sending on + request.uploadByteDevice()->setProperty("SPDYStreamID", streamID); + + QObject::connect(request.uploadByteDevice(), SIGNAL(readyRead()), this, + SLOT(_q_uploadDataReadyRead()), Qt::QueuedConnection); + } + + QByteArray namesAndValues = composeHeader(request); + quint32 length = namesAndValues.count() + 10; // 10 == 4 for Stream-ID + 4 for Associated-To-Stream-ID + // + 2 for Priority, Unused and Slot + + QByteArray wireData; + wireData.reserve(length); + wireData.append(intToFourBytes(streamID)); + wireData.append(intToFourBytes(associatedToStreamID)); + + // priority (3 bits) / unused (5 bits) / slot (8 bits) + char prioAndSlot[2]; + switch (request.priority()) { + case QHttpNetworkRequest::HighPriority: + prioAndSlot[0] = 0x00; // == prio 0 (highest) + break; + case QHttpNetworkRequest::NormalPriority: + prioAndSlot[0] = 0x80; // == prio 4 + break; + case QHttpNetworkRequest::LowPriority: + prioAndSlot[0] = 0xe0; // == prio 7 (lowest) + break; + } + prioAndSlot[1] = 0x00; // slot in client certificates (not supported currently) + wireData.append(prioAndSlot, 2); + + wireData.append(namesAndValues); + + sendControlFrame(FrameType_SYN_STREAM, flags, wireData.constData(), length); + + if (reply->d_func()->state == QHttpNetworkReplyPrivate::SPDYUploading) + uploadData(streamID); +} + +void QSpdyProtocolHandler::sendRST_STREAM(qint32 streamID, RST_STREAM_STATUS_CODE statusCode) +{ + char wireData[8]; + appendIntToFourBytes(wireData, streamID); + appendIntToFourBytes(wireData + 4, statusCode); + sendControlFrame(FrameType_RST_STREAM, /* flags = */ 0, wireData, /* length = */ 8); +} + +void QSpdyProtocolHandler::sendPING(quint32 pingID) +{ + char rawData[4]; + appendIntToFourBytes(rawData, pingID); + sendControlFrame(FrameType_PING, /* flags = */ 0, rawData, /* length = */ 4); +} + +bool QSpdyProtocolHandler::uploadData(qint32 streamID) +{ + // we only rely on SPDY flow control here and don't care about TCP buffers + + HttpMessagePair messagePair = m_inFlightStreams.value(streamID); + QHttpNetworkRequest request = messagePair.first; + QHttpNetworkReply *reply = messagePair.second; + Q_ASSERT(reply); + QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); + Q_ASSERT(replyPrivate); + + qint32 dataLeftInWindow = replyPrivate->windowSizeUpload + - replyPrivate->currentlyUploadedDataInWindow; + + while (dataLeftInWindow > 0 && !request.uploadByteDevice()->atEnd()) { + + // get pointer to upload data + qint64 currentReadSize = 0; + const char *readPointer = request.uploadByteDevice()->readPointer(dataLeftInWindow, + currentReadSize); + + if (currentReadSize == -1) { + // premature eof happened + m_connection->d_func()->emitReplyError(m_socket, reply, + QNetworkReply::UnknownNetworkError); + return false; + } else if (readPointer == 0 || currentReadSize == 0) { + // nothing to read currently, break the loop + break; + } else { + DataFrameFlags flags = 0; + // we will send the FIN flag later if appropriate + qint64 currentWriteSize = sendDataFrame(streamID, flags, currentReadSize, readPointer); + if (currentWriteSize == -1 || currentWriteSize != currentReadSize) { + // socket broke down + m_connection->d_func()->emitReplyError(m_socket, reply, + QNetworkReply::UnknownNetworkError); + return false; + } else { + replyPrivate->currentlyUploadedDataInWindow += currentWriteSize; + replyPrivate->totallyUploadedData += currentWriteSize; + dataLeftInWindow = replyPrivate->windowSizeUpload + - replyPrivate->currentlyUploadedDataInWindow; + request.uploadByteDevice()->advanceReadPointer(currentWriteSize); + + emit reply->dataSendProgress(replyPrivate->totallyUploadedData, + request.contentLength()); + } + } + } + if (replyPrivate->totallyUploadedData == request.contentLength()) { + DataFrameFlags finFlag = DataFrame_FLAG_FIN; + qint64 writeSize = sendDataFrame(streamID, finFlag, 0, 0); + Q_ASSERT(writeSize == 0); + Q_UNUSED(writeSize); // silence -Wunused-variable + replyPrivate->state = QHttpNetworkReplyPrivate::SPDYHalfClosed; + // ### this will not work if the content length is not known, but + // then again many servers will fail in this case anyhow according + // to the SPDY RFC + } + return true; +} + +void QSpdyProtocolHandler::_q_uploadDataReadyRead() +{ + QNonContiguousByteDevice *device = qobject_cast(sender()); + Q_ASSERT(device); + qint32 streamID = device->property("SPDYStreamID").toInt(); + Q_ASSERT(streamID > 0); + uploadData(streamID); +} + +void QSpdyProtocolHandler::sendWINDOW_UPDATE(qint32 streamID, quint32 deltaWindowSize) +{ + char windowUpdateData[8]; + appendIntToFourBytes(windowUpdateData, streamID); + appendIntToFourBytes(windowUpdateData + 4, deltaWindowSize); + + sendControlFrame(FrameType_WINDOW_UPDATE, /* flags = */ 0, windowUpdateData, /* length = */ 8); +} + +qint64 QSpdyProtocolHandler::sendDataFrame(qint32 streamID, DataFrameFlags flags, + quint32 length, const char *data) +{ + QByteArray wireData; + wireData.reserve(8); + + wireData.append(intToFourBytes(streamID)); + wireData.append(flags); + wireData.append(intToThreeBytes(length)); + + Q_ASSERT(m_socket); + m_socket->write(wireData); + + if (data) { + qint64 ret = m_socket->write(data, length); + return ret; + } else { + return 0; // nothing to write, e.g. FIN flag + } +} + +void QSpdyProtocolHandler::handleControlFrame(const QByteArray &frameHeaders) // ### make it char * +{ + Q_ASSERT(frameHeaders.count() >= 8); + qint16 version = twoBytesToInt(frameHeaders.constData()); + version &= 0x3fff; // eliminate most significant bit to determine version + Q_ASSERT(version == 3); + + qint16 type = twoBytesToInt(frameHeaders.constData() + 2); + + char flags = frameHeaders.at(4); + qint32 length = threeBytesToInt(frameHeaders.constData() + 5); + Q_ASSERT(length > 0); + + QByteArray frameData; + frameData.resize(length); + if (!readNextChunk(length, frameData.data())) { + // put back the frame headers to the buffer + m_spdyBuffer.prepend(frameHeaders); + return; // we couldn't read the whole frame and need to wait + } else { + m_spdyBuffer.clear(); + m_waitingForCompleteStream = false; + } + + switch (type) { + case FrameType_SYN_STREAM: { + handleSYN_STREAM(flags, length, frameData); + break; + } + case FrameType_SYN_REPLY: { + handleSYN_REPLY(flags, length, frameData); + break; + } + case FrameType_RST_STREAM: { + handleRST_STREAM(flags, length, frameData); + break; + } + case FrameType_SETTINGS: { + handleSETTINGS(flags, length, frameData); + break; + } + case FrameType_PING: { + handlePING(flags, length, frameData); + break; + } + case FrameType_GOAWAY: { + handleGOAWAY(flags, length, frameData); + break; + } + case FrameType_HEADERS: { + handleHEADERS(flags, length, frameData); + break; + } + case FrameType_WINDOW_UPDATE: { + handleWINDOW_UPDATE(flags, length, frameData); + break; + } + default: + qWarning() << Q_FUNC_INFO << "cannot handle frame of type" << type; + } +} + +void QSpdyProtocolHandler::handleSYN_STREAM(char /*flags*/, quint32 /*length*/, + const QByteArray &frameData) +{ + // not implemented; will be implemented when servers start using it + // we just tell the server that we do not accept that + + qint32 streamID = getStreamID(frameData.constData()); + + sendRST_STREAM(streamID, RST_STREAM_REFUSED_STREAM); +} + +void QSpdyProtocolHandler::handleSYN_REPLY(char flags, quint32 /*length*/, const QByteArray &frameData) +{ + parseHttpHeaders(flags, frameData); +} + +void QSpdyProtocolHandler::parseHttpHeaders(char flags, const QByteArray &frameData) +{ + qint32 streamID = getStreamID(frameData.constData()); + + flags &= 0x3f; + bool flag_fin = flags & 0x01; + + QByteArray headerValuePairs = frameData.mid(4); + + HttpMessagePair pair = m_inFlightStreams.value(streamID); + QHttpNetworkReply *httpReply = pair.second; + Q_ASSERT(httpReply != 0); + + QByteArray uncompressedHeader; + if (!uncompressHeader(headerValuePairs, &uncompressedHeader)) { + qWarning() << Q_FUNC_INFO << "error reading header from SYN_REPLY message"; + return; + } + + qint32 headerCount = fourBytesToInt(uncompressedHeader.constData()); + qint32 readPointer = 4; + for (qint32 a = 0; a < headerCount; ++a) { + qint32 count = fourBytesToInt(uncompressedHeader.constData() + readPointer); + readPointer += 4; + QByteArray name = uncompressedHeader.mid(readPointer, count); + readPointer += count; + count = fourBytesToInt(uncompressedHeader.constData() + readPointer); + readPointer += 4; + QByteArray value = uncompressedHeader.mid(readPointer, count); + readPointer += count; + if (name == ":status") { + httpReply->setStatusCode(value.left(3).toInt()); + httpReply->d_func()->reasonPhrase = QString::fromLatin1(value.mid(4)); + } else if (name == ":version") { + int majorVersion = value.at(5) - 48; + int minorVersion = value.at(7) - 48; + httpReply->d_func()->majorVersion = majorVersion; + httpReply->d_func()->minorVersion = minorVersion; + } else if (name == "content-length") { + httpReply->setContentLength(value.toLongLong()); + } else { + httpReply->setHeaderField(name, value); + } + } + emit httpReply->headerChanged(); + + if (flag_fin) { + switch (httpReply->d_func()->state) { + case QHttpNetworkReplyPrivate::SPDYSYNSent: + httpReply->d_func()->state = QHttpNetworkReplyPrivate::SPDYHalfClosed; + break; + case QHttpNetworkReplyPrivate::SPDYHalfClosed: + replyFinished(httpReply, streamID); + break; + case QHttpNetworkReplyPrivate::SPDYClosed: { + sendRST_STREAM(streamID, RST_STREAM_PROTOCOL_ERROR); + replyFinishedWithError(httpReply, streamID, QNetworkReply::ProtocolFailure, + "server sent SYN_REPLY on an already closed stream"); + break; + } + default: + qWarning() << Q_FUNC_INFO << "got data frame in unknown state"; + } + } +} + +void QSpdyProtocolHandler::handleRST_STREAM(char /*flags*/, quint32 length, + const QByteArray &frameData) +{ + // flags are ignored + + Q_ASSERT(length == 8); + Q_UNUSED(length); // silence -Wunused-parameter + qint32 streamID = getStreamID(frameData.constData()); + QHttpNetworkReply *httpReply = m_inFlightStreams.value(streamID).second; + Q_ASSERT(httpReply); + + qint32 statusCodeInt = fourBytesToInt(frameData.constData() + 4); + RST_STREAM_STATUS_CODE statusCode = static_cast(statusCodeInt); + QNetworkReply::NetworkError errorCode; + QByteArray errorMessage; + + switch (statusCode) { + case RST_STREAM_PROTOCOL_ERROR: + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "SPDY protocol error"; + break; + case RST_STREAM_INVALID_STREAM: + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "SPDY stream is not active"; + break; + case RST_STREAM_REFUSED_STREAM: + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "SPDY stream was refused"; + break; + case RST_STREAM_UNSUPPORTED_VERSION: + errorCode = QNetworkReply::ProtocolUnknownError; + errorMessage = "SPDY version is unknown to the server"; + break; + case RST_STREAM_CANCEL: + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "SPDY stream is no longer needed"; + break; + case RST_STREAM_INTERNAL_ERROR: + errorCode = QNetworkReply::InternalServerError; + errorMessage = "Internal server error"; + break; + case RST_STREAM_FLOW_CONTROL_ERROR: + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "peer violated the flow control protocol"; + break; + case RST_STREAM_STREAM_IN_USE: + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "server received a SYN_REPLY for an already open stream"; + break; + case RST_STREAM_STREAM_ALREADY_CLOSED: + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "server received data or a SYN_REPLY for an already half-closed stream"; + break; + case RST_STREAM_INVALID_CREDENTIALS: + errorCode = QNetworkReply::ContentAccessDenied; + errorMessage = "server received invalid credentials"; + break; + case RST_STREAM_FRAME_TOO_LARGE: + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "server cannot process the frame because it is too large"; + break; + default: + qWarning() << Q_FUNC_INFO << "could not understand servers RST_STREAM status code"; + errorCode = QNetworkReply::ProtocolFailure; + errorMessage = "got SPDY RST_STREAM message with unknown error code"; + } + replyFinishedWithError(httpReply, streamID, errorCode, errorMessage.constData()); +} + +void QSpdyProtocolHandler::handleSETTINGS(char flags, quint32 /*length*/, const QByteArray &frameData) +{ + Q_ASSERT(frameData.count() > 0); + + SETTINGS_Flags settingsFlags = static_cast(flags); + if (settingsFlags & FLAG_SETTINGS_CLEAR_SETTINGS) { + // ### clear all persistent settings; since we do not persist settings + // as of now, we don't need to clear anything either + } + + qint32 numberOfEntries = fourBytesToInt(frameData.constData()); + Q_ASSERT(numberOfEntries > 0); + for (int a = 0, frameDataIndex = 4; a < numberOfEntries; ++a, frameDataIndex += 8) { + SETTINGS_ID_Flag idFlag = static_cast(frameData[frameDataIndex]); + if (idFlag & FLAG_SETTINGS_PERSIST_VALUE) { + // ### we SHOULD persist the settings here according to the RFC, but we don't have to, + // so implement that later + } // the other value is only sent by us, but not received + + quint32 uniqueID = static_cast( + threeBytesToInt(frameData.constData() + frameDataIndex + 1)); + quint32 value = fourBytesToInt(frameData.constData() + frameDataIndex + 4); + switch (uniqueID) { + case SETTINGS_UPLOAD_BANDWIDTH: { + // ignored for now, just an estimated informative value + break; + } + case SETTINGS_DOWNLOAD_BANDWIDTH: { + // ignored for now, just an estimated informative value + break; + } + case SETTINGS_ROUND_TRIP_TIME: { + // ignored for now, just an estimated informative value + break; + } + case SETTINGS_MAX_CONCURRENT_STREAMS: { + m_maxConcurrentStreams = value; + break; + } + case SETTINGS_CURRENT_CWND: { + // ignored for now, just an informative value + break; + } + case SETTINGS_DOWNLOAD_RETRANS_RATE: { + // ignored for now, just an estimated informative value + break; + } + case SETTINGS_INITIAL_WINDOW_SIZE: { + m_initialWindowSize = value; + break; + } + case SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE: { + // client certificates are not supported + break; + } + default: + qWarning() << Q_FUNC_INFO << "found unknown settings value" << value; + } + } +} + +void QSpdyProtocolHandler::handlePING(char /*flags*/, quint32 length, const QByteArray &frameData) +{ + // flags are ignored + + Q_ASSERT(length == 4); + Q_UNUSED(length); // silence -Wunused-parameter + quint32 pingID = fourBytesToInt(frameData.constData()); + + // odd numbered IDs must be ignored + if ((pingID & 1) == 0) // is even? + sendPING(pingID); +} + +void QSpdyProtocolHandler::handleGOAWAY(char /*flags*/, quint32 /*length*/, + const QByteArray &frameData) +{ + // flags are ignored + + qint32 statusCode = static_cast(fourBytesToInt(frameData.constData() + 4)); + QNetworkReply::NetworkError errorCode; + switch (statusCode) { + case GOAWAY_OK: { + errorCode = QNetworkReply::NoError; + break; + } + case GOAWAY_PROTOCOL_ERROR: { + errorCode = QNetworkReply::ProtocolFailure; + break; + } + case GOAWAY_INTERNAL_ERROR: { + errorCode = QNetworkReply::InternalServerError; + break; + } + default: + qWarning() << Q_FUNC_INFO << "unexpected status code" << statusCode; + errorCode = QNetworkReply::ProtocolUnknownError; + } + + qint32 lastGoodStreamID = getStreamID(frameData.constData()); + + // emit errors for all replies after the last good stream ID + Q_ASSERT(m_connection); + for (qint32 currentStreamID = lastGoodStreamID + 2; currentStreamID <= m_nextStreamID; + ++currentStreamID) { + QHttpNetworkReply *reply = m_inFlightStreams.value(currentStreamID).second; + Q_ASSERT(reply); + m_connection->d_func()->emitReplyError(m_socket, reply, errorCode); + } + // ### we could make sure a new session is initiated anyhow +} + +void QSpdyProtocolHandler::handleHEADERS(char flags, quint32 /*length*/, + const QByteArray &frameData) +{ + parseHttpHeaders(flags, frameData); +} + +void QSpdyProtocolHandler::handleWINDOW_UPDATE(char /*flags*/, quint32 /*length*/, + const QByteArray &frameData) +{ + qint32 streamID = getStreamID(frameData.constData()); + qint32 deltaWindowSize = fourBytesToInt(frameData.constData() + 4); + + QHttpNetworkReply *reply = m_inFlightStreams.value(streamID).second; + Q_ASSERT(reply); + QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); + Q_ASSERT(replyPrivate); + + replyPrivate->currentlyUploadedDataInWindow = replyPrivate->windowSizeUpload - deltaWindowSize; + uploadData(streamID); // we hopefully can continue to upload +} + + +void QSpdyProtocolHandler::handleDataFrame(const QByteArray &frameHeaders) +{ + Q_ASSERT(frameHeaders.count() >= 8); + + qint32 streamID = getStreamID(frameHeaders.constData()); + unsigned char flags = static_cast(frameHeaders.at(4)); + flags &= 0x3f; + bool flag_fin = flags & 0x01; + bool flag_compress = flags & 0x02; + qint32 length = threeBytesToInt(frameHeaders.constData() + 5); + + QByteArray data; + data.resize(length); + if (!readNextChunk(length, data.data())) { + // put back the frame headers to the buffer + m_spdyBuffer.prepend(frameHeaders); + return; // we couldn't read the whole frame and need to wait + } else { + m_spdyBuffer.clear(); + m_waitingForCompleteStream = false; + } + + HttpMessagePair pair = m_inFlightStreams.value(streamID); + QHttpNetworkRequest httpRequest = pair.first; + QHttpNetworkReply *httpReply = pair.second; + Q_ASSERT(httpReply != 0); + + QHttpNetworkReplyPrivate *replyPrivate = httpReply->d_func(); + + // check whether we need to send WINDOW_UPDATE (i.e. tell the sender it can send more) + replyPrivate->currentlyReceivedDataInWindow += length; + qint32 dataLeftInWindow = replyPrivate->windowSizeDownload - replyPrivate->currentlyReceivedDataInWindow; + + if (replyPrivate->currentlyReceivedDataInWindow > 0 + && dataLeftInWindow < replyPrivate->windowSizeDownload / 2) { + + // socket read buffer size is 64K actually, hard coded in the channel + // We can read way more than 64K per socket, because the window size + // here is per stream. + if (replyPrivate->windowSizeDownload >= m_socket->readBufferSize()) { + replyPrivate->windowSizeDownload = m_socket->readBufferSize(); + } else { + replyPrivate->windowSizeDownload *= 1.5; + } + QMetaObject::invokeMethod(this, "sendWINDOW_UPDATE", Qt::QueuedConnection, + Q_ARG(qint32, streamID), + Q_ARG(quint32, replyPrivate->windowSizeDownload)); + // setting the current data count to 0 is a race condition, + // because we call sendWINDOW_UPDATE through the event loop. + // But then again, the whole situation is a race condition because + // we don't know when the packet will arrive at the server; so + // this is most likely good enough here. + replyPrivate->currentlyReceivedDataInWindow = 0; + } + + httpReply->d_func()->compressedData.append(data); + + + replyPrivate->totalProgress += length; + + if (httpRequest.d->autoDecompress && httpReply->d_func()->isCompressed()) { + QByteDataBuffer inDataBuffer; // ### should we introduce one in the http reply? + inDataBuffer.append(data); + qint64 compressedCount = httpReply->d_func()->uncompressBodyData(&inDataBuffer, + &replyPrivate->responseData); + Q_ASSERT(compressedCount >= 0); + Q_UNUSED(compressedCount); // silence -Wunused-variable + } else { + replyPrivate->responseData.append(data); + } + + if (replyPrivate->shouldEmitSignals()) { + emit httpReply->readyRead(); + emit httpReply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); + } + + if (flag_compress) { + qWarning() << Q_FUNC_INFO << "SPDY level compression is not supported"; + } + + if (flag_fin) { + switch (httpReply->d_func()->state) { + case QHttpNetworkReplyPrivate::SPDYSYNSent: + httpReply->d_func()->state = QHttpNetworkReplyPrivate::SPDYHalfClosed; + // ### send FIN ourselves? + break; + case QHttpNetworkReplyPrivate::SPDYHalfClosed: + replyFinished(httpReply, streamID); + break; + case QHttpNetworkReplyPrivate::SPDYClosed: { + sendRST_STREAM(streamID, RST_STREAM_PROTOCOL_ERROR); + replyFinishedWithError(httpReply, streamID, QNetworkReply::ProtocolFailure, + "server sent data on an already closed stream"); + break; + } + default: + qWarning() << Q_FUNC_INFO << "got data frame in unknown state"; + } + } +} + +void QSpdyProtocolHandler::replyFinished(QHttpNetworkReply *httpReply, qint32 streamID) +{ + httpReply->d_func()->state = QHttpNetworkReplyPrivate::SPDYClosed; + int streamsRemoved = m_inFlightStreams.remove(streamID); + Q_ASSERT(streamsRemoved == 1); + Q_UNUSED(streamsRemoved); // silence -Wunused-variable + emit httpReply->finished(); +} + +void QSpdyProtocolHandler::replyFinishedWithError(QHttpNetworkReply *httpReply, qint32 streamID, + QNetworkReply::NetworkError errorCode, const char *errorMessage) +{ + httpReply->d_func()->state = QHttpNetworkReplyPrivate::SPDYClosed; + int streamsRemoved = m_inFlightStreams.remove(streamID); + Q_ASSERT(streamsRemoved == 1); + Q_UNUSED(streamsRemoved); // silence -Wunused-variable + emit httpReply->finishedWithError(errorCode, QSpdyProtocolHandler::tr(errorMessage)); +} + +qint32 QSpdyProtocolHandler::generateNextStreamID() +{ + // stream IDs initiated by the client must be odd + m_nextStreamID += 2; + return m_nextStreamID; +} + +QT_END_NAMESPACE + +#endif // !defined(QT_NO_HTTP) && !defined(QT_NO_SSL) diff --git a/src/network/access/qspdyprotocolhandler_p.h b/src/network/access/qspdyprotocolhandler_p.h new file mode 100644 index 0000000000..8cbfbdda86 --- /dev/null +++ b/src/network/access/qspdyprotocolhandler_p.h @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSPDYPROTOCOLHANDLER_H +#define QSPDYPROTOCOLHANDLER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the Network Access API. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include + +#if !defined(QT_NO_HTTP) && !defined(QT_NO_SSL) + +QT_BEGIN_NAMESPACE + +class QHttpNetworkRequest; + +#ifndef HttpMessagePair +typedef QPair HttpMessagePair; +#endif + +class QSpdyProtocolHandler : public QObject, public QAbstractProtocolHandler { + Q_OBJECT +public: + QSpdyProtocolHandler(QHttpNetworkConnectionChannel *channel); + ~QSpdyProtocolHandler(); + + enum DataFrameFlag { + DataFrame_FLAG_FIN = 0x01, + DataFrame_FLAG_COMPRESS = 0x02 + }; + + Q_DECLARE_FLAGS(DataFrameFlags, DataFrameFlag) + + enum ControlFrameFlag { + ControlFrame_FLAG_FIN = 0x01, + ControlFrame_FLAG_UNIDIRECTIONAL = 0x02 + }; + + Q_DECLARE_FLAGS(ControlFrameFlags, ControlFrameFlag) + + enum SETTINGS_Flag { + FLAG_SETTINGS_CLEAR_SETTINGS = 0x01 + }; + + Q_DECLARE_FLAGS(SETTINGS_Flags, SETTINGS_Flag) + + enum SETTINGS_ID_Flag { + FLAG_SETTINGS_PERSIST_VALUE = 0x01, + FLAG_SETTINGS_PERSISTED = 0x02 + }; + + Q_DECLARE_FLAGS(SETTINGS_ID_Flags, SETTINGS_ID_Flag) + + virtual void _q_receiveReply() Q_DECL_OVERRIDE; + virtual void _q_readyRead() Q_DECL_OVERRIDE; + virtual bool sendRequest() Q_DECL_OVERRIDE; + +private slots: + void _q_uploadDataReadyRead(); + +private: + + enum FrameType { + FrameType_SYN_STREAM = 1, + FrameType_SYN_REPLY = 2, + FrameType_RST_STREAM = 3, + FrameType_SETTINGS = 4, + FrameType_PING = 6, + FrameType_GOAWAY = 7, + FrameType_HEADERS = 8, + FrameType_WINDOW_UPDATE = 9, + FrameType_CREDENTIAL // has a special type + }; + + enum StatusCode { + StatusCode_PROTOCOL_ERROR = 1, + StatusCode_INVALID_STREAM = 2, + StatusCode_REFUSED_STREAM = 3, + StatusCode_UNSUPPORTED_VERSION = 4, + StatusCode_CANCEL = 5, + StatusCode_INTERNAL_ERROR = 6, + StatusCode_FLOW_CONTROL_ERROR = 7, + StatusCode_STREAM_IN_USE = 8, + StatusCode_STREAM_ALREADY_CLOSED = 9, + StatusCode_INVALID_CREDENTIALS = 10, + StatusCode_FRAME_TOO_LARGE = 11 + }; + + enum SETTINGS_ID { + SETTINGS_UPLOAD_BANDWIDTH = 1, + SETTINGS_DOWNLOAD_BANDWIDTH = 2, + SETTINGS_ROUND_TRIP_TIME = 3, + SETTINGS_MAX_CONCURRENT_STREAMS = 4, + SETTINGS_CURRENT_CWND = 5, + SETTINGS_DOWNLOAD_RETRANS_RATE = 6, + SETTINGS_INITIAL_WINDOW_SIZE = 7, + SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8 + }; + + enum GOAWAY_STATUS { + GOAWAY_OK = 0, + GOAWAY_PROTOCOL_ERROR = 1, + GOAWAY_INTERNAL_ERROR = 11 + }; + + enum RST_STREAM_STATUS_CODE { + RST_STREAM_PROTOCOL_ERROR = 1, + RST_STREAM_INVALID_STREAM = 2, + RST_STREAM_REFUSED_STREAM = 3, + RST_STREAM_UNSUPPORTED_VERSION = 4, + RST_STREAM_CANCEL = 5, + RST_STREAM_INTERNAL_ERROR = 6, + RST_STREAM_FLOW_CONTROL_ERROR = 7, + RST_STREAM_STREAM_IN_USE = 8, + RST_STREAM_STREAM_ALREADY_CLOSED = 9, + RST_STREAM_INVALID_CREDENTIALS = 10, + RST_STREAM_FRAME_TOO_LARGE = 11 + }; + + quint64 bytesAvailable() const; + bool readNextChunk(qint64 length, char *sink); + + void sendControlFrame(FrameType type, ControlFrameFlags flags, const char *data, quint32 length); + + void sendSYN_STREAM(HttpMessagePair pair, qint32 streamID, + qint32 associatedToStreamID); + void sendRST_STREAM(qint32 streamID, RST_STREAM_STATUS_CODE statusCode); + void sendPING(quint32 pingID); + + bool uploadData(qint32 streamID); + Q_INVOKABLE void sendWINDOW_UPDATE(qint32 streamID, quint32 deltaWindowSize); + + qint64 sendDataFrame(qint32 streamID, DataFrameFlags flags, quint32 length, + const char *data); + + QByteArray composeHeader(const QHttpNetworkRequest &request); + bool uncompressHeader(const QByteArray &input, QByteArray *output); + + void handleControlFrame(const QByteArray &frameHeaders); + void handleDataFrame(const QByteArray &frameHeaders); + + void handleSYN_STREAM(char, quint32, const QByteArray &frameData); + void handleSYN_REPLY(char flags, quint32, const QByteArray &frameData); + void handleRST_STREAM(char flags, quint32 length, const QByteArray &frameData); + void handleSETTINGS(char flags, quint32 length, const QByteArray &frameData); + void handlePING(char, quint32 length, const QByteArray &frameData); + void handleGOAWAY(char flags, quint32, const QByteArray &frameData); + void handleHEADERS(char flags, quint32, const QByteArray &frameData); + void handleWINDOW_UPDATE(char, quint32, const QByteArray &frameData); + + qint32 generateNextStreamID(); + void parseHttpHeaders(char flags, const QByteArray &frameData); + + void replyFinished(QHttpNetworkReply *httpReply, qint32 streamID); + void replyFinishedWithError(QHttpNetworkReply *httpReply, qint32 streamID, + QNetworkReply::NetworkError errorCode, const char *errorMessage); + + qint32 m_nextStreamID; + QHash m_inFlightStreams; + qint32 m_maxConcurrentStreams; + quint32 m_initialWindowSize; + QByteDataBuffer m_spdyBuffer; + bool m_waitingForCompleteStream; + z_stream m_deflateStream; + z_stream m_inflateStream; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::DataFrameFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::ControlFrameFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::SETTINGS_Flags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QSpdyProtocolHandler::SETTINGS_ID_Flags) + +QT_END_NAMESPACE + +#endif // !defined(QT_NO_HTTP) && !defined(QT_NO_SSL) + +#endif // QSPDYPROTOCOLHANDLER_H diff --git a/tests/auto/network/access/access.pro b/tests/auto/network/access/access.pro index 3139f19f7b..bc76190e30 100644 --- a/tests/auto/network/access/access.pro +++ b/tests/auto/network/access/access.pro @@ -7,6 +7,7 @@ SUBDIRS=\ qnetworkrequest \ qhttpnetworkconnection \ qnetworkreply \ + spdy \ qnetworkcachemetadata \ qftp \ qhttpnetworkreply \ diff --git a/tests/auto/network/access/spdy/spdy.pro b/tests/auto/network/access/spdy/spdy.pro new file mode 100644 index 0000000000..6bfc6d84e0 --- /dev/null +++ b/tests/auto/network/access/spdy/spdy.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +CONFIG += parallel_test +TARGET = tst_spdy +SOURCES += tst_spdy.cpp + +QT = core core-private network network-private testlib +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/spdy/tst_spdy.cpp b/tests/auto/network/access/spdy/tst_spdy.cpp new file mode 100644 index 0000000000..d2a220bad4 --- /dev/null +++ b/tests/auto/network/access/spdy/tst_spdy.cpp @@ -0,0 +1,690 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#ifdef QT_BUILD_INTERNAL +#include +#endif // QT_BUILD_INTERNAL + +#include "../../../network-settings.h" + +Q_DECLARE_METATYPE(QAuthenticator*) + +class tst_Spdy: public QObject +{ + Q_OBJECT + +public: + tst_Spdy(); + ~tst_Spdy(); + +private Q_SLOTS: + void settingsAndNegotiation_data(); + void settingsAndNegotiation(); + void download_data(); + void download(); + void headerFields(); + void upload_data(); + void upload(); + void errors_data(); + void errors(); + void multipleRequests_data(); + void multipleRequests(); + +private: + QNetworkAccessManager m_manager; + int m_multipleRequestsCount; + int m_multipleRepliesFinishedCount; + +protected Q_SLOTS: + void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *authenticator); + void multipleRequestsFinishedSlot(); +}; + +tst_Spdy::tst_Spdy() +{ +#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + qRegisterMetaType(); // for QSignalSpy + qRegisterMetaType(); + + connect(&m_manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), + this, SLOT(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); +#else + QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old"); +#endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ... +} + +tst_Spdy::~tst_Spdy() +{ +} + +void tst_Spdy::settingsAndNegotiation_data() +{ + QTest::addColumn("url"); + QTest::addColumn("setAttribute"); + QTest::addColumn("enabled"); + QTest::addColumn("expectedProtocol"); + QTest::addColumn("expectedContent"); + + QTest::newRow("default-settings") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/cgi-bin/echo.cgi?1") + << false << false << QByteArray() + << QByteArray("1"); + + QTest::newRow("http-url") << QUrl("http://" + QtNetworkSettings::serverName() + + "/qtest/cgi-bin/echo.cgi?1") + << true << true << QByteArray() + << QByteArray("1"); + + QTest::newRow("spdy-disabled") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/cgi-bin/echo.cgi?1") + << true << false << QByteArray() + << QByteArray("1"); + +#ifndef QT_NO_OPENSSL + QTest::newRow("spdy-enabled") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/cgi-bin/echo.cgi?1") + << true << true << QByteArray(QSslConfiguration::NextProtocolSpdy3_0) + << QByteArray("1"); +#endif // QT_NO_OPENSSL +} + +void tst_Spdy::settingsAndNegotiation() +{ + QFETCH(QUrl, url); + QFETCH(bool, setAttribute); + QFETCH(bool, enabled); + + QNetworkRequest request(url); + + if (setAttribute) { + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, QVariant(enabled)); + } + + QNetworkReply *reply = m_manager.get(request); + reply->ignoreSslErrors(); + QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged())); + QSignalSpy readyReadSpy(reply, SIGNAL(readyRead())); + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + + QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*))); + + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QFETCH(QByteArray, expectedProtocol); + +#ifndef QT_NO_OPENSSL + bool expectedSpdyUsed = (expectedProtocol == QSslConfiguration::NextProtocolSpdy3_0) + ? true : false; + QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), expectedSpdyUsed); +#endif // QT_NO_OPENSSL + + QCOMPARE(metaDataChangedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); + + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QCOMPARE(statusCode, 200); + + QByteArray content = reply->readAll(); + + QFETCH(QByteArray, expectedContent); + QCOMPARE(expectedContent, content); + +#ifndef QT_NO_OPENSSL + QSslConfiguration::NextProtocolNegotiationStatus expectedStatus = + (expectedProtocol.isEmpty()) + ? QSslConfiguration::NextProtocolNegotiationNone + : QSslConfiguration::NextProtocolNegotiationNegotiated; + QCOMPARE(reply->sslConfiguration().nextProtocolNegotiationStatus(), + expectedStatus); + + QCOMPARE(reply->sslConfiguration().nextNegotiatedProtocol(), expectedProtocol); +#endif // QT_NO_OPENSSL +} + +void tst_Spdy::proxyAuthenticationRequired(const QNetworkProxy &/*proxy*/, + QAuthenticator *authenticator) +{ + authenticator->setUser("qsockstest"); + authenticator->setPassword("password"); +} + +void tst_Spdy::download_data() +{ + QTest::addColumn("url"); + QTest::addColumn("fileName"); + QTest::addColumn("proxy"); + + QTest::newRow("mediumfile") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/rfc3252.txt") + << QFINDTESTDATA("../qnetworkreply/rfc3252.txt") + << QNetworkProxy(); + + QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName()); + QString proxyserver = hostInfo.addresses().first().toString(); + + QTest::newRow("mediumfile-http-proxy") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/rfc3252.txt") + << QFINDTESTDATA("../qnetworkreply/rfc3252.txt") + << QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3128); + + QTest::newRow("mediumfile-http-proxy-auth") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/rfc3252.txt") + << QFINDTESTDATA("../qnetworkreply/rfc3252.txt") + << QNetworkProxy(QNetworkProxy::HttpProxy, + proxyserver, 3129); + + QTest::newRow("mediumfile-socks-proxy") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/rfc3252.txt") + << QFINDTESTDATA("../qnetworkreply/rfc3252.txt") + << QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1080); + + QTest::newRow("mediumfile-socks-proxy-auth") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/rfc3252.txt") + << QFINDTESTDATA("../qnetworkreply/rfc3252.txt") + << QNetworkProxy(QNetworkProxy::Socks5Proxy, + proxyserver, 1081); + + QTest::newRow("bigfile") << QUrl("https://" + QtNetworkSettings::serverName() + + "/qtest/bigfile") + << QFINDTESTDATA("../qnetworkreply/bigfile") + << QNetworkProxy(); +} + +void tst_Spdy::download() +{ + QFETCH(QUrl, url); + QFETCH(QString, fileName); + QFETCH(QNetworkProxy, proxy); + + QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); + + if (proxy.type() != QNetworkProxy::DefaultProxy) { + m_manager.setProxy(proxy); + } + QNetworkReply *reply = m_manager.get(request); + reply->ignoreSslErrors(); + QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged())); + QSignalSpy downloadProgressSpy(reply, SIGNAL(downloadProgress(qint64, qint64))); + QSignalSpy readyReadSpy(reply, SIGNAL(readyRead())); + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + + QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*))); + QSignalSpy proxyAuthRequiredSpy(&m_manager, SIGNAL( + proxyAuthenticationRequired(const QNetworkProxy &, + QAuthenticator *))); + + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(finishedManagerSpy.count(), 1); + QCOMPARE(metaDataChangedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); + QVERIFY(downloadProgressSpy.count() > 0); + QVERIFY(readyReadSpy.count() > 0); + + QVERIFY(proxyAuthRequiredSpy.count() <= 1); + + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true); + QCOMPARE(reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true); + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + + QFile file(fileName); + QVERIFY(file.open(QIODevice::ReadOnly)); + + qint64 contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(); + qint64 expectedContentLength = file.bytesAvailable(); + QCOMPARE(contentLength, expectedContentLength); + + QByteArray expectedContent = file.readAll(); + QByteArray content = reply->readAll(); + QCOMPARE(content, expectedContent); + + reply->deleteLater(); + m_manager.setProxy(QNetworkProxy()); // reset +} + +void tst_Spdy::headerFields() +{ + QUrl url(QUrl("https://" + QtNetworkSettings::serverName())); + QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); + + QNetworkReply *reply = m_manager.get(request); + reply->ignoreSslErrors(); + + QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->rawHeader("Content-Type"), QByteArray("text/html")); + QVERIFY(reply->rawHeader("Content-Length").toInt() > 0); + QVERIFY(reply->rawHeader("server").contains("Apache")); + + QCOMPARE(reply->header(QNetworkRequest::ContentTypeHeader).toByteArray(), QByteArray("text/html")); + QVERIFY(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong() > 0); + QVERIFY(reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().isValid()); + QVERIFY(reply->header(QNetworkRequest::ServerHeader).toByteArray().contains("Apache")); +} + +static inline QByteArray md5sum(const QByteArray &data) +{ + return QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex().append('\n'); +} + +void tst_Spdy::upload_data() +{ + QTest::addColumn("url"); + QTest::addColumn("data"); + QTest::addColumn("uploadMethod"); + QTest::addColumn("uploadObject"); + QTest::addColumn("md5sum"); + QTest::addColumn("proxy"); + + + // 1. test uploading of byte arrays + + QUrl md5Url("https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); + + QByteArray data; + data = ""; + QObject *dummyObject = 0; + QTest::newRow("empty") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) << QNetworkProxy(); + + data = "This is a normal message."; + QTest::newRow("generic") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) << QNetworkProxy(); + + data = "This is a message to show that Qt rocks!\r\n\n"; + QTest::newRow("small") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) << QNetworkProxy(); + + data = QByteArray("abcd\0\1\2\abcd",12); + QTest::newRow("with-nul") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) << QNetworkProxy(); + + data = QByteArray(4097, '\4'); + QTest::newRow("4k+1") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data)<< QNetworkProxy(); + + QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName()); + QString proxyserver = hostInfo.addresses().first().toString(); + + QTest::newRow("4k+1-with-http-proxy") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) + << QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3128); + + QTest::newRow("4k+1-with-http-proxy-auth") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) + << QNetworkProxy(QNetworkProxy::HttpProxy, + proxyserver, 3129); + + QTest::newRow("4k+1-with-socks-proxy") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) + << QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1080); + + QTest::newRow("4k+1-with-socks-proxy-auth") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) + << QNetworkProxy(QNetworkProxy::Socks5Proxy, + proxyserver, 1081); + + data = QByteArray(128*1024+1, '\177'); + QTest::newRow("128k+1") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) << QNetworkProxy(); + + data = QByteArray(128*1024+1, '\177'); + QTest::newRow("128k+1-put") << md5Url << data << QByteArray("PUT") << dummyObject + << md5sum(data) << QNetworkProxy(); + + data = QByteArray(2*1024*1024+1, '\177'); + QTest::newRow("2MB+1") << md5Url << data << QByteArray("POST") << dummyObject + << md5sum(data) << QNetworkProxy(); + + + // 2. test uploading of files + + QFile *file = new QFile(QFINDTESTDATA("../qnetworkreply/rfc3252.txt")); + file->open(QIODevice::ReadOnly); + QTest::newRow("file-26K") << md5Url << QByteArray() << QByteArray("POST") + << static_cast(file) + << QByteArray("b3e32ac459b99d3f59318f3ac31e4bee\n") << QNetworkProxy(); + + QFile *file2 = new QFile(QFINDTESTDATA("../qnetworkreply/image1.jpg")); + file2->open(QIODevice::ReadOnly); + QTest::newRow("file-1MB") << md5Url << QByteArray() << QByteArray("POST") + << static_cast(file2) + << QByteArray("87ef3bb319b004ba9e5e9c9fa713776e\n") << QNetworkProxy(); + + + // 3. test uploading of multipart + + QUrl multiPartUrl("https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/multipart.cgi"); + + QHttpPart imagePart31; + imagePart31.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart31.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage1\"")); + imagePart31.setRawHeader("Content-Location", "http://my.test.location.tld"); + imagePart31.setRawHeader("Content-ID", "my@id.tld"); + QFile *file31 = new QFile(QFINDTESTDATA("../qnetworkreply/image1.jpg")); + file31->open(QIODevice::ReadOnly); + imagePart31.setBodyDevice(file31); + QHttpMultiPart *imageMultiPart3 = new QHttpMultiPart(QHttpMultiPart::FormDataType); + imageMultiPart3->append(imagePart31); + file31->setParent(imageMultiPart3); + QHttpPart imagePart32; + imagePart32.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart32.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage2\"")); + QFile *file32 = new QFile(QFINDTESTDATA("../qnetworkreply/image2.jpg")); + file32->open(QIODevice::ReadOnly); + imagePart32.setBodyDevice(file31); // check that resetting works + imagePart32.setBodyDevice(file32); + imageMultiPart3->append(imagePart32); + file32->setParent(imageMultiPart3); + QHttpPart imagePart33; + imagePart33.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart33.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage3\"")); + QFile *file33 = new QFile(QFINDTESTDATA("../qnetworkreply/image3.jpg")); + file33->open(QIODevice::ReadOnly); + imagePart33.setBodyDevice(file33); + imageMultiPart3->append(imagePart33); + file33->setParent(imageMultiPart3); + QByteArray expectedData = "content type: multipart/form-data; boundary=\"" + + imageMultiPart3->boundary(); + expectedData.append("\"\nkey: testImage1, value: 87ef3bb319b004ba9e5e9c9fa713776e\n" + "key: testImage2, value: 483761b893f7fb1bd2414344cd1f3dfb\n" + "key: testImage3, value: ab0eb6fd4fcf8b4436254870b4513033\n"); + + QTest::newRow("multipart-3images") << multiPartUrl << QByteArray() << QByteArray("POST") + << static_cast(imageMultiPart3) << expectedData + << QNetworkProxy(); +} + +void tst_Spdy::upload() +{ + QFETCH(QUrl, url); + QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); + + QFETCH(QByteArray, data); + QFETCH(QByteArray, uploadMethod); + QFETCH(QObject *, uploadObject); + QFETCH(QNetworkProxy, proxy); + + if (proxy.type() != QNetworkProxy::DefaultProxy) { + m_manager.setProxy(proxy); + } + + QNetworkReply *reply; + QHttpMultiPart *multiPart = 0; + + if (uploadObject) { + // upload via device + if (QIODevice *device = qobject_cast(uploadObject)) { + reply = m_manager.post(request, device); + } else if ((multiPart = qobject_cast(uploadObject))) { + reply = m_manager.post(request, multiPart); + } else { + QFAIL("got unknown upload device"); + } + } else { + // upload via byte array + if (uploadMethod == "PUT") { + reply = m_manager.put(request, data); + } else { + reply = m_manager.post(request, data); + } + } + + reply->ignoreSslErrors(); + QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged())); + QSignalSpy uploadProgressSpy(reply, SIGNAL(uploadProgress(qint64, qint64))); + QSignalSpy readyReadSpy(reply, SIGNAL(readyRead())); + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + + QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*))); + + QTestEventLoop::instance().enterLoop(20); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(finishedManagerSpy.count(), 1); + QCOMPARE(metaDataChangedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); + QVERIFY(uploadProgressSpy.count() > 0); + QVERIFY(readyReadSpy.count() > 0); + + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true); + QCOMPARE(reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true); + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + + qint64 contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(); + if (!multiPart) // script to test multiparts does not return a content length + QCOMPARE(contentLength, 33); // 33 bytes for md5 sums (including new line) + + QFETCH(QByteArray, md5sum); + QByteArray content = reply->readAll(); + QCOMPARE(content, md5sum); + + reply->deleteLater(); + if (uploadObject) + uploadObject->deleteLater(); + + m_manager.setProxy(QNetworkProxy()); // reset +} + +void tst_Spdy::errors_data() +{ + QTest::addColumn("url"); + QTest::addColumn("proxy"); + QTest::addColumn("ignoreSslErrors"); + QTest::addColumn("expectedReplyError"); + + QTest::newRow("http-404") << QUrl("https://" + QtNetworkSettings::serverName() + "/non-existent-url") + << QNetworkProxy() << true << int(QNetworkReply::ContentNotFoundError); + + QTest::newRow("ssl-errors") << QUrl("https://" + QtNetworkSettings::serverName()) + << QNetworkProxy() << false << int(QNetworkReply::SslHandshakeFailedError); + + QTest::newRow("host-not-found") << QUrl("https://this-host-does-not.exist") + << QNetworkProxy() + << true << int(QNetworkReply::HostNotFoundError); + + QTest::newRow("proxy-not-found") << QUrl("https://" + QtNetworkSettings::serverName()) + << QNetworkProxy(QNetworkProxy::HttpProxy, + "https://this-host-does-not.exist", 3128) + << true << int(QNetworkReply::HostNotFoundError); + + QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName()); + QString proxyserver = hostInfo.addresses().first().toString(); + + QTest::newRow("proxy-unavailable") << QUrl("https://" + QtNetworkSettings::serverName()) + << QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 10) + << true << int(QNetworkReply::UnknownNetworkError); + + QTest::newRow("no-proxy-credentials") << QUrl("https://" + QtNetworkSettings::serverName()) + << QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3129) + << true << int(QNetworkReply::ProxyAuthenticationRequiredError); +} + +void tst_Spdy::errors() +{ + QFETCH(QUrl, url); + QFETCH(QNetworkProxy, proxy); + QFETCH(bool, ignoreSslErrors); + QFETCH(int, expectedReplyError); + + QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); + + disconnect(&m_manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), + 0, 0); + if (proxy.type() != QNetworkProxy::DefaultProxy) { + m_manager.setProxy(proxy); + } + QNetworkReply *reply = m_manager.get(request); + if (ignoreSslErrors) + reply->ignoreSslErrors(); + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + QSignalSpy errorSpy(reply, SIGNAL(error(QNetworkReply::NetworkError))); + + QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(errorSpy.count(), 1); + + QCOMPARE(reply->error(), static_cast(expectedReplyError)); + + m_manager.setProxy(QNetworkProxy()); // reset + m_manager.clearAccessCache(); // e.g. to get an SSL error we need a new connection + connect(&m_manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), + this, SLOT(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), + Qt::UniqueConnection); // reset +} + +void tst_Spdy::multipleRequests_data() +{ + QTest::addColumn >("urls"); + + QString baseUrl = "https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/echo.cgi?"; + QList urls; + for (int a = 1; a <= 50; ++a) + urls.append(QUrl(baseUrl + QLatin1String(QByteArray::number(a)))); + + QTest::newRow("one-request") << urls.mid(0, 1); + QTest::newRow("two-requests") << urls.mid(0, 2); + QTest::newRow("ten-requests") << urls.mid(0, 10); + QTest::newRow("twenty-requests") << urls.mid(0, 20); + QTest::newRow("fifty-requests") << urls; +} + +void tst_Spdy::multipleRequestsFinishedSlot() +{ + m_multipleRepliesFinishedCount++; + if (m_multipleRepliesFinishedCount == m_multipleRequestsCount) + QTestEventLoop::instance().exitLoop(); +} + +void tst_Spdy::multipleRequests() +{ + QFETCH(QList, urls); + m_multipleRequestsCount = urls.count(); + m_multipleRepliesFinishedCount = 0; + + QList replies; + QList metaDataChangedSpies; + QList readyReadSpies; + QList finishedSpies; + + foreach (const QUrl &url, urls) { + QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); + QNetworkReply *reply = m_manager.get(request); + replies.append(reply); + reply->ignoreSslErrors(); + QObject::connect(reply, SIGNAL(finished()), this, SLOT(multipleRequestsFinishedSlot())); + QSignalSpy *metaDataChangedSpy = new QSignalSpy(reply, SIGNAL(metaDataChanged())); + metaDataChangedSpies << metaDataChangedSpy; + QSignalSpy *readyReadSpy = new QSignalSpy(reply, SIGNAL(readyRead())); + readyReadSpies << readyReadSpy; + QSignalSpy *finishedSpy = new QSignalSpy(reply, SIGNAL(finished())); + finishedSpies << finishedSpy; + } + + QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*))); + + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(finishedManagerSpy.count(), m_multipleRequestsCount); + + for (int a = 0; a < replies.count(); ++a) { + +#ifndef QT_NO_OPENSSL + QCOMPARE(replies.at(a)->sslConfiguration().nextProtocolNegotiationStatus(), + QSslConfiguration::NextProtocolNegotiationNegotiated); + QCOMPARE(replies.at(a)->sslConfiguration().nextNegotiatedProtocol(), + QByteArray(QSslConfiguration::NextProtocolSpdy3_0)); +#endif // QT_NO_OPENSSL + + QCOMPARE(replies.at(a)->error(), QNetworkReply::NoError); + QCOMPARE(replies.at(a)->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true); + QCOMPARE(replies.at(a)->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true); + QCOMPARE(replies.at(a)->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + + // using the echo script, a request to "echo.cgi?1" will return a body of "1" + QByteArray expectedContent = replies.at(a)->url().query().toUtf8(); + QByteArray content = replies.at(a)->readAll(); + QCOMPARE(expectedContent, content); + + QCOMPARE(metaDataChangedSpies.at(a)->count(), 1); + metaDataChangedSpies.at(a)->deleteLater(); + + QCOMPARE(finishedSpies.at(a)->count(), 1); + finishedSpies.at(a)->deleteLater(); + + QVERIFY(readyReadSpies.at(a)->count() > 0); + readyReadSpies.at(a)->deleteLater(); + + replies.at(a)->deleteLater(); + } +} + +QTEST_MAIN(tst_Spdy) + +#include "tst_spdy.moc" diff --git a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp index 55376d5a79..3b8565a0ec 100644 --- a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -52,6 +52,7 @@ #ifdef QT_BUILD_INTERNAL #include +#include #endif Q_DECLARE_METATYPE(QSharedPointer) @@ -552,10 +553,16 @@ void tst_qnetworkreply::echoPerformance() void tst_qnetworkreply::preConnectEncrypted() { + QFETCH(int, sleepTime); + QFETCH(QSslConfiguration, sslConfiguration); + bool spdyEnabled = !sslConfiguration.isNull(); + QString hostName = QLatin1String("www.google.com"); QNetworkAccessManager manager; QNetworkRequest request(QUrl("https://" + hostName)); + if (spdyEnabled) + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); // make sure we have a full request including // DNS lookup, TCP and SSL handshakes @@ -581,8 +588,12 @@ void tst_qnetworkreply::preConnectEncrypted() manager.clearAccessCache(); // now try to make the connection beforehand - QFETCH(int, sleepTime); - manager.connectToHostEncrypted(hostName); + if (spdyEnabled) { + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); + manager.connectToHostEncrypted(hostName, 443, sslConfiguration); + } else { + manager.connectToHostEncrypted(hostName); + } QTestEventLoop::instance().enterLoopMSecs(sleepTime); // now make another request and hopefully use the existing connection @@ -590,18 +601,42 @@ void tst_qnetworkreply::preConnectEncrypted() QNetworkReply *preConnectReply = normalResult.first; QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(preConnectReply->error() == QNetworkReply::NoError); + bool spdyWasUsed = preConnectReply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(); + QCOMPARE(spdyEnabled, spdyWasUsed); qint64 preConnectElapsed = preConnectResult.second; qDebug() << request.url().toString() << "full request:" << normalElapsed << "ms, pre-connect request:" << preConnectElapsed << "ms, difference:" << (normalElapsed - preConnectElapsed) << "ms"; } + #endif // !QT_NO_SSL void tst_qnetworkreply::preConnectEncrypted_data() { +#ifndef QT_NO_OPENSSL QTest::addColumn("sleepTime"); - QTest::newRow("2secs") << 2000; // to start a new request after preconnecting is done - QTest::newRow("100ms") << 100; // to start a new request while preconnecting is in-flight + QTest::addColumn("sslConfiguration"); + + // start a new normal request after preconnecting is done + QTest::newRow("HTTPS-2secs") << 2000 << QSslConfiguration(); + + // start a new normal request while preconnecting is in-flight + QTest::newRow("HTTPS-100ms") << 100 << QSslConfiguration(); + + QSslConfiguration spdySslConf = QSslConfiguration::defaultConfiguration(); + QList nextProtocols = QList() + << QSslConfiguration::NextProtocolSpdy3_0 + << QSslConfiguration::NextProtocolHttp1_1; + spdySslConf.setAllowedNextProtocols(nextProtocols); + +#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + // start a new SPDY request while preconnecting is done + QTest::newRow("SPDY-2secs") << 2000 << spdySslConf; + + // start a new SPDY request while preconnecting is in-flight + QTest::newRow("SPDY-100ms") << 100 << spdySslConf; +#endif // defined (QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ... +#endif // QT_NO_OPENSSL } void tst_qnetworkreply::downloadPerformance() diff --git a/tests/manual/qnetworkreply/main.cpp b/tests/manual/qnetworkreply/main.cpp index fe667e92a0..ff96f2598d 100644 --- a/tests/manual/qnetworkreply/main.cpp +++ b/tests/manual/qnetworkreply/main.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -53,6 +54,7 @@ #if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) #include "private/qsslsocket_p.h" +#include #endif #define BANDWIDTH_LIMIT_BYTES (1024*100) @@ -68,8 +70,16 @@ private slots: void setSslConfiguration_data(); void setSslConfiguration(); void uploadToFacebook(); + void spdy_data(); + void spdy(); + void spdyMultipleRequestsPerHost(); + +protected slots: + void spdyReplyFinished(); // only used by spdyMultipleRequestsPerHost test + private: QHttpMultiPart *createFacebookMultiPart(const QByteArray &accessToken); + QNetworkAccessManager m_manager; }; QNetworkReply *reply; @@ -104,6 +114,7 @@ protected: void tst_qnetworkreply::initTestCase() { + qRegisterMetaType(); // for QSignalSpy QVERIFY(QtNetworkSettings::verifyTestNetworkSettings()); } @@ -284,6 +295,215 @@ void tst_qnetworkreply::uploadToFacebook() } } +void tst_qnetworkreply::spdy_data() +{ + QTest::addColumn("host"); + QTest::addColumn("setAttribute"); + QTest::addColumn("enabled"); + QTest::addColumn("expectedProtocol"); + + QList hosts = QList() + << QStringLiteral("www.google.com") // sends SPDY and 30x redirect + << QStringLiteral("www.google.de") // sends SPDY and 200 OK + << QStringLiteral("mail.google.com") // sends SPDY and 200 OK + << QStringLiteral("www.youtube.com") // sends SPDY and 200 OK + << QStringLiteral("www.dropbox.com") // no SPDY, but NPN which selects HTTP + << QStringLiteral("www.facebook.com") // sends SPDY and 200 OK + << QStringLiteral("graph.facebook.com") // sends SPDY and 200 OK + << QStringLiteral("www.twitter.com") // sends SPDY and 30x redirect + << QStringLiteral("twitter.com") // sends SPDY and 200 OK + << QStringLiteral("api.twitter.com"); // sends SPDY and 200 OK + + foreach (const QString &host, hosts) { + QByteArray tag = host.toLocal8Bit(); + tag.append("-not-used"); + QTest::newRow(tag) + << QStringLiteral("https://") + host + << false + << false + << QByteArray(); + + tag = host.toLocal8Bit(); + tag.append("-disabled"); + QTest::newRow(tag) + << QStringLiteral("https://") + host + << true + << false + << QByteArray(); + + if (host != QStringLiteral("api.twitter.com")) { // they don't offer an API over HTTP + tag = host.toLocal8Bit(); + tag.append("-no-https-url"); + QTest::newRow(tag) + << QStringLiteral("http://") + host + << true + << true + << QByteArray(); + } + +#ifndef QT_NO_OPENSSL + tag = host.toLocal8Bit(); + tag.append("-enabled"); + QTest::newRow(tag) + << QStringLiteral("https://") + host + << true + << true + << (host == QStringLiteral("www.dropbox.com") + ? QByteArray(QSslConfiguration::NextProtocolHttp1_1) + : QByteArray(QSslConfiguration::NextProtocolSpdy3_0)); +#endif // QT_NO_OPENSSL + } +} + +void tst_qnetworkreply::spdy() +{ +#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + + m_manager.clearAccessCache(); + + QFETCH(QString, host); + QUrl url(host); + QNetworkRequest request(url); + + QFETCH(bool, setAttribute); + QFETCH(bool, enabled); + if (setAttribute) { + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, QVariant(enabled)); + } + + QNetworkReply *reply = m_manager.get(request); + QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged())); + QSignalSpy readyReadSpy(reply, SIGNAL(readyRead())); + QSignalSpy finishedSpy(reply, SIGNAL(finished())); + QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*))); + + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QFETCH(QByteArray, expectedProtocol); + + bool expectedSpdyUsed = (expectedProtocol == QSslConfiguration::NextProtocolSpdy3_0) + ? true : false; + QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), expectedSpdyUsed); + + QCOMPARE(metaDataChangedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(finishedManagerSpy.count(), 1); + + QUrl redirectUrl = reply->header(QNetworkRequest::LocationHeader).toUrl(); + QByteArray content = reply->readAll(); + + int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QVERIFY(statusCode >= 200 && statusCode < 500); + if (statusCode == 200 || statusCode >= 400) { + QVERIFY(readyReadSpy.count() > 0); + QVERIFY(!content.isEmpty()); + } else if (statusCode >= 300 && statusCode < 400) { + QVERIFY(!redirectUrl.isEmpty()); + } + + QSslConfiguration::NextProtocolNegotiationStatus expectedStatus = + expectedProtocol.isNull() ? QSslConfiguration::NextProtocolNegotiationNone + : QSslConfiguration::NextProtocolNegotiationNegotiated; + QCOMPARE(reply->sslConfiguration().nextProtocolNegotiationStatus(), + expectedStatus); + + QCOMPARE(reply->sslConfiguration().nextNegotiatedProtocol(), expectedProtocol); +#else + QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old"); +#endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ... +} + +void tst_qnetworkreply::spdyReplyFinished() +{ + static int finishedCount = 0; + finishedCount++; + + if (finishedCount == 12) + QTestEventLoop::instance().exitLoop(); +} + +void tst_qnetworkreply::spdyMultipleRequestsPerHost() +{ +#if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + + QList requests; + requests + << QNetworkRequest(QUrl("https://www.facebook.com")) + << QNetworkRequest(QUrl("https://www.facebook.com/images/fb_icon_325x325.png")) + + << QNetworkRequest(QUrl("https://www.google.de")) + << QNetworkRequest(QUrl("https://www.google.de/preferences?hl=de")) + << QNetworkRequest(QUrl("https://www.google.de/intl/de/policies/?fg=1")) + << QNetworkRequest(QUrl("https://www.google.de/intl/de/about.html?fg=1")) + << QNetworkRequest(QUrl("https://www.google.de/services/?fg=1")) + << QNetworkRequest(QUrl("https://www.google.de/intl/de/ads/?fg=1")) + + << QNetworkRequest(QUrl("https://i1.ytimg.com/li/tnHdj3df7iM/default.jpg")) + << QNetworkRequest(QUrl("https://i1.ytimg.com/li/7Dr1BKwqctY/default.jpg")) + << QNetworkRequest(QUrl("https://i1.ytimg.com/li/hfZhJdhTqX8/default.jpg")) + << QNetworkRequest(QUrl("https://i1.ytimg.com/vi/14Nprh8163I/hqdefault.jpg")) + ; + QList replies; + QList metaDataChangedSpies; + QList readyReadSpies; + QList finishedSpies; + + QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*))); + + foreach (QNetworkRequest request, requests) { + request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); + QNetworkReply *reply = m_manager.get(request); + QObject::connect(reply, SIGNAL(finished()), this, SLOT(spdyReplyFinished())); + replies << reply; + QSignalSpy *metaDataChangedSpy = new QSignalSpy(reply, SIGNAL(metaDataChanged())); + metaDataChangedSpies << metaDataChangedSpy; + QSignalSpy *readyReadSpy = new QSignalSpy(reply, SIGNAL(readyRead())); + readyReadSpies << readyReadSpy; + QSignalSpy *finishedSpy = new QSignalSpy(reply, SIGNAL(finished())); + finishedSpies << finishedSpy; + } + + QCOMPARE(requests.count(), replies.count()); + + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(finishedManagerSpy.count(), requests.count()); + + for (int a = 0; a < replies.count(); ++a) { + + QCOMPARE(replies.at(a)->sslConfiguration().nextProtocolNegotiationStatus(), + QSslConfiguration::NextProtocolNegotiationNegotiated); + QCOMPARE(replies.at(a)->sslConfiguration().nextNegotiatedProtocol(), + QByteArray(QSslConfiguration::NextProtocolSpdy3_0)); + + QCOMPARE(replies.at(a)->error(), QNetworkReply::NoError); + QCOMPARE(replies.at(a)->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true); + QCOMPARE(replies.at(a)->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true); + QCOMPARE(replies.at(a)->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + + QByteArray content = replies.at(a)->readAll(); + QVERIFY(content.count() > 0); + + QCOMPARE(metaDataChangedSpies.at(a)->count(), 1); + metaDataChangedSpies.at(a)->deleteLater(); + + QCOMPARE(finishedSpies.at(a)->count(), 1); + finishedSpies.at(a)->deleteLater(); + + QVERIFY(readyReadSpies.at(a)->count() > 0); + readyReadSpies.at(a)->deleteLater(); + + replies.at(a)->deleteLater(); + } +#else + QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old"); +#endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ... +} + QTEST_MAIN(tst_qnetworkreply) #include "main.moc" From 121e71293500e08148d3c2ce31a8e9b618943cba Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sat, 15 Feb 2014 01:17:27 +0100 Subject: [PATCH 011/124] QHash: use prime numbers when rebucketing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QHash uses an array representing the difference between 2^i and the next prime; when growing, it calculates 2^x + array[x] (with `x' representing the "hash table size in bits"). For some reason lost in history the differences are actually wrong and the calculation above leads to using composite numbers. Hence: use the right sequence and always produce primes. The right sequence is actually A092131 from OEIS: http://oeis.org/A092131 Note that the sequence starts at A(1), but we need A(0) too. Also we truncate the sequence to when growing too much, just like the old code did, and use powers of two in that case instead. Task-number: QTBUG-36866 Change-Id: Id2e3fc9cb567c0fdca305dee38f480e17639ca04 Reviewed-by: Morten Johan Sørvig Reviewed-by: JÄ™drzej Nowacki --- src/corelib/tools/qhash.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 5320ea1fbf..a5d14a3535 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -337,20 +337,29 @@ uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW } /* - The prime_deltas array is a table of selected prime values, even - though it doesn't look like one. The primes we are using are 1, - 2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate - surrounding of a power of two. + The prime_deltas array contains the difference between a power + of two and the next prime number: - The primeForNumBits() function returns the prime associated to a - power of two. For example, primeForNumBits(8) returns 257. + prime_deltas[i] = nextprime(2^i) - 2^i + + Basically, it's sequence A092131 from OEIS, assuming: + - nextprime(1) = 1 + - nextprime(2) = 2 + and + - left-extending it for the offset 0 (A092131 starts at i=1) + - stopping the sequence at i = 28 (the table is big enough...) */ static const uchar prime_deltas[] = { - 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, - 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 + 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 17, 27, 3, + 1, 29, 3, 21, 7, 17, 15, 9, 43, 35, 15, 0, 0, 0, 0, 0 }; +/* + The primeForNumBits() function returns the prime associated to a + power of two. For example, primeForNumBits(8) returns 257. +*/ + static inline int primeForNumBits(int numBits) { return (1 << numBits) + prime_deltas[numBits]; From ac127a8c09ab91d15adb1cb9d44123f3e0185e00 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Tue, 18 Feb 2014 12:08:19 +0100 Subject: [PATCH 012/124] Blackberry: Fix QFileSystemEngine::tempPath() Fall back to /var/tmp instead of /tmp if neither TMPDIR nor TEMP are set. /tmp is not a true filesystem on BB10 but rather a symbolic link to /dev/shmem For more info see http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/user_guide/fsystems.html#RAM Change-Id: Ie690ed74ffd81b52ef4623458c3ff88629aee00a Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine_unix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 2327c11c69..ea3a3ca13d 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -720,8 +720,8 @@ QString QFileSystemEngine::tempPath() temp = QFile::decodeName(qgetenv("TMPDIR")); if (temp.isEmpty()) { - qWarning("Neither the TEMP nor the TMPDIR environment variable is set, falling back to /tmp."); - temp = QLatin1String("/tmp"); + qWarning("Neither the TEMP nor the TMPDIR environment variable is set, falling back to /var/tmp."); + temp = QLatin1String("/var/tmp"); } return QDir::cleanPath(temp); #else From a01b7dad50a526189f8f3abe6f48290458225f02 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Tue, 18 Feb 2014 09:33:36 +0100 Subject: [PATCH 013/124] Remove qSort usages from tests QtAlgorithms is getting deprecated, see http://www.mail-archive.com/development@qt-project.org/msg01603.html Change-Id: I4c48db80533802e37771d3967fa10bfb7000cb9a Reviewed-by: Frederik Gladhorn Reviewed-by: Friedemann Kleint --- tests/auto/other/lancelot/tst_lancelot.cpp | 4 +++- tests/auto/other/qaccessibility/tst_qaccessibility.cpp | 6 ++++-- .../printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp | 6 ++++-- tests/auto/tools/rcc/tst_rcc.cpp | 6 ++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/auto/other/lancelot/tst_lancelot.cpp b/tests/auto/other/lancelot/tst_lancelot.cpp index a99b041bfc..237e50ae3d 100644 --- a/tests/auto/other/lancelot/tst_lancelot.cpp +++ b/tests/auto/other/lancelot/tst_lancelot.cpp @@ -50,6 +50,8 @@ #include #endif +#include + class tst_Lancelot : public QObject { Q_OBJECT @@ -114,7 +116,7 @@ void tst_Lancelot::initTestCase() QSKIP("Aborted due to errors."); } - qSort(qpsFiles); + std::sort(qpsFiles.begin(), qpsFiles.end()); foreach (const QString& fileName, qpsFiles) { QFile file(scriptsDir + fileName); file.open(QFile::ReadOnly); diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index dc3f266025..53f74d091b 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -73,6 +73,8 @@ #include "QtTest/qtestaccessible.h" +#include + // Make a widget frameless to prevent size constraints of title bars // from interfering (Windows). static inline void setFrameless(QWidget *w) @@ -2192,7 +2194,7 @@ void tst_QAccessibility::dialogButtonBoxTest() for (int i = 0; i < iface->childCount(); ++i) buttons << iface->child(i); - qSort(buttons.begin(), buttons.end(), accessibleInterfaceLeftOf); + std::sort(buttons.begin(), buttons.end(), accessibleInterfaceLeftOf); for (int i = 0; i < buttons.count(); ++i) actualOrder << buttons.at(i)->text(QAccessible::Name); @@ -2243,7 +2245,7 @@ void tst_QAccessibility::dialogButtonBoxTest() for (int i = 0; i < iface->childCount(); ++i) buttons << iface->child(i); - qSort(buttons.begin(), buttons.end(), accessibleInterfaceAbove); + std::sort(buttons.begin(), buttons.end(), accessibleInterfaceAbove); for (int i = 0; i < buttons.count(); ++i) actualOrder << buttons.at(i)->text(QAccessible::Name); diff --git a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp index 9416224440..fb2609b7ec 100644 --- a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp +++ b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp @@ -44,6 +44,8 @@ #include #include +#include + #ifdef Q_OS_UNIX # include # include @@ -246,8 +248,8 @@ void tst_QPrinterInfo::testForPrinters() for (int i = 0; i < printers.size(); ++i) qtPrinters.append(printers.at(i).printerName()); - qSort(testPrinters); - qSort(qtPrinters); + std::sort(testPrinters.begin(), testPrinters.end()); + std::sort(qtPrinters.begin(), qtPrinters.end()); qDebug() << "Test believes Available Printers = " << testPrinters; qDebug() << "QPrinterInfo::availablePrinters() believes Available Printers = " << qtPrinters; diff --git a/tests/auto/tools/rcc/tst_rcc.cpp b/tests/auto/tools/rcc/tst_rcc.cpp index 4089d53f3d..9a494428e7 100644 --- a/tests/auto/tools/rcc/tst_rcc.cpp +++ b/tests/auto/tools/rcc/tst_rcc.cpp @@ -54,6 +54,8 @@ #include #include +#include + typedef QMap QStringMap; Q_DECLARE_METATYPE(QStringMap) @@ -325,8 +327,8 @@ void tst_rcc::binary() } // check that we have all (and only) the expected files - qSort(filesFound); - qSort(expectedFileNames); + std::sort(filesFound.begin(), filesFound.end()); + std::sort(expectedFileNames.begin(), expectedFileNames.end()); QCOMPARE(filesFound, expectedFileNames); // now actually check the file contents From 170df5addb5334befc8c61130c748fb77de46600 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Mon, 17 Feb 2014 23:37:05 +0100 Subject: [PATCH 014/124] Remove qSort usages from gui tests QtAlgorithms is getting deprecated, see http://www.mail-archive.com/development@qt-project.org/msg01603.html Change-Id: Idf0fc471f8ab7b30a097d8faf93c93d5ebbb03ef Reviewed-by: Friedemann Kleint --- tests/auto/gui/image/qicon/tst_qicon.cpp | 4 +++- tests/auto/gui/image/qimagereader/tst_qimagereader.cpp | 6 ++++-- tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp | 6 ++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp index bfe2fbc9f7..0f642bcc10 100644 --- a/tests/auto/gui/image/qicon/tst_qicon.cpp +++ b/tests/auto/gui/image/qicon/tst_qicon.cpp @@ -45,6 +45,8 @@ #include #include +#include + class tst_QIcon : public QObject { @@ -421,7 +423,7 @@ void tst_QIcon::availableSizes() QList availableSizes = icon.availableSizes(); QCOMPARE(availableSizes.size(), 3); - qSort(availableSizes.begin(), availableSizes.end(), sizeLess); + std::sort(availableSizes.begin(), availableSizes.end(), sizeLess); QCOMPARE(availableSizes.at(0), QSize(32,32)); QCOMPARE(availableSizes.at(1), QSize(64,64)); QCOMPARE(availableSizes.at(2), QSize(128,128)); diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index b684231e10..5decbc86fc 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -55,6 +55,8 @@ #include #include +#include + typedef QMap QStringMap; typedef QList QIntList; Q_DECLARE_METATYPE(QImage::Format) @@ -559,7 +561,7 @@ void tst_QImageReader::supportedFormats() { QList formats = QImageReader::supportedImageFormats(); QList sortedFormats = formats; - qSort(sortedFormats); + std::sort(sortedFormats.begin(), sortedFormats.end()); // check that the list is sorted QCOMPARE(formats, sortedFormats); @@ -576,7 +578,7 @@ void tst_QImageReader::supportedMimeTypes() { QList mimeTypes = QImageReader::supportedMimeTypes(); QList sortedMimeTypes = mimeTypes; - qSort(sortedMimeTypes); + std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end()); // check that the list is sorted QCOMPARE(mimeTypes, sortedMimeTypes); diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp index b10b5704c3..c9f8a1f681 100644 --- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp @@ -57,6 +57,8 @@ # include #endif +#include + typedef QMap QStringMap; typedef QList QIntList; Q_DECLARE_METATYPE(QImageWriter::ImageWriterError) @@ -342,7 +344,7 @@ void tst_QImageWriter::supportedFormats() { QList formats = QImageWriter::supportedImageFormats(); QList sortedFormats = formats; - qSort(sortedFormats); + std::sort(sortedFormats.begin(), sortedFormats.end()); // check that the list is sorted QCOMPARE(formats, sortedFormats); @@ -359,7 +361,7 @@ void tst_QImageWriter::supportedMimeTypes() { QList mimeTypes = QImageWriter::supportedMimeTypes(); QList sortedMimeTypes = mimeTypes; - qSort(sortedMimeTypes); + std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end()); // check that the list is sorted QCOMPARE(mimeTypes, sortedMimeTypes); From 72fbcc8bbf7bfae962ee9c3d3bccfc8253709bd4 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 18 Feb 2014 13:29:32 +0100 Subject: [PATCH 015/124] Ensure we switch back to the real paint engine when not emulating When the emulation paint engine was no longer needed then it would still end up using it because the flags would prevent it from being switched back. This ensures that it has the right engine when something triggers it to be switched. Change-Id: I7571923d16cbebd9fdd34560631b561c07a724f7 Reviewed-by: Laszlo Agocs --- src/gui/painting/qpainter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 1fc044aa44..e35cdd370e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -171,9 +171,6 @@ static bool qt_painter_thread_test(int devType, const char *what) void QPainterPrivate::checkEmulation() { Q_ASSERT(extended); - if (extended->flags() & QPaintEngineEx::DoNotEmulate) - return; - bool doEmulation = false; if (state->bgMode == Qt::OpaqueMode) doEmulation = true; @@ -186,6 +183,9 @@ void QPainterPrivate::checkEmulation() if (pg && pg->coordinateMode() > QGradient::LogicalMode) doEmulation = true; + if (doEmulation && extended->flags() & QPaintEngineEx::DoNotEmulate) + return; + if (doEmulation) { if (extended != emulationEngine) { if (!emulationEngine) From 9babaac16da14657ccf8629419328bf05c866eed Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 19 Feb 2014 10:28:39 +0100 Subject: [PATCH 016/124] Only do a repolish() of the widget if it was already polished By ensuring that the widget is already polished before doing a repolish it means that if you reset the stylesheet then it unsets any changes that the stylesheet had applied to the widget. Task-number: QTBUG-18958 Change-Id: Ie0aeda0dac9f2211b7feca138c115cf2b48aac80 Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qwidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 46aa93fe48..ba8147c4a6 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -2404,7 +2404,8 @@ void QWidget::setStyleSheet(const QString& styleSheet) } if (proxy) { // style sheet update - proxy->repolish(this); + if (d->polished) + proxy->repolish(this); return; } From 37b8bb54733ec61559b74ba0bf8127d9218ae9ca Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Feb 2014 15:42:36 +0100 Subject: [PATCH 017/124] QFileDialog: restore state from QSettings after creating widgets After 37ca2224eca671200a2710f57f970d2993e62aa5 it's necessary to read the saved QSettings again after creating widgets, in order to deal with the settings which only affect widgets (such as saved bookmarks). It's also necessary to read them if widgets are not used though, because some of the settings affect native dialog options. Task-number: QTBUG-36888 Change-Id: I8cf53db864b173c50a876a1d5ce29c1e073fcaa6 Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qfiledialog.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 1c580ce143..3e4490e890 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2739,9 +2739,8 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte q->selectFile(initialSelection(directory)); #ifndef QT_NO_SETTINGS - QSettings settings(QSettings::UserScope, QLatin1String("QtProject")); - settings.beginGroup(QLatin1String("Qt")); - q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray()); + const QSettings settings(QSettings::UserScope, QLatin1String("QtProject")); + q->restoreState(settings.value(QLatin1String("Qt/filedialog")).toByteArray()); #endif #if defined(Q_EMBEDDED_SMALLSCREEN) @@ -2888,6 +2887,11 @@ void QFileDialogPrivate::createWidgets() createToolButtons(); createMenuActions(); +#ifndef QT_NO_SETTINGS + const QSettings settings(QSettings::UserScope, QLatin1String("QtProject")); + q->restoreState(settings.value(QLatin1String("Qt/filedialog")).toByteArray()); +#endif + // Initial widget states from options q->setFileMode(static_cast(options->fileMode())); q->setAcceptMode(static_cast(options->acceptMode())); From e99c37494474fb2c2ddc3c95476f650eb95c3139 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Fri, 14 Feb 2014 12:58:27 +0100 Subject: [PATCH 018/124] Doc: Removed Contents listing for Qt Examples and Tutorials page. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Qt Examples and Tutorials page does not need the table of contents. Task-number: QTBUG-36838 Change-Id: Id51ebc7cba7831a24cd9d8e8e6bde7f96bece326 Reviewed-by: Martin Smith Reviewed-by: Topi Reiniö --- src/tools/qdoc/htmlgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 511dc3240f..1eef42dc2f 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -1465,7 +1465,7 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker) // Replace the marker with a QML code marker. marker = CodeMarker::markerForLanguage(QLatin1String("QML")); } - else if (dn->subType() != Node::Collision && dn->name() != QString("index.html")) + else if (dn->subType() != Node::Collision && dn->name() != QString("index.html") && dn->name() != QString("qtexamplesandtutorials.html")) generateTableOfContents(dn,marker,0); generateTitle(fullTitle, From 93d35c07d06fcc932196aa22586b65411b4e5edd Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Thu, 23 Jan 2014 15:30:27 +0100 Subject: [PATCH 019/124] Doc: Updated CSS used by the offline documentation. -new layout for landing page -updates to title sizes and changes to footer -fixes to general paragraph issues -index.qdoc changed in qtdoc repository Task-number: QTBUG-36411 Change-Id: Icb4fb0374e474137686f4cb67c64dc0249fef2c4 Reviewed-by: Martin Smith --- doc/global/template/style/offline.css | 138 ++++++++++---------------- 1 file changed, 52 insertions(+), 86 deletions(-) diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css index 81e11aac0b..bfa086284f 100644 --- a/doc/global/template/style/offline.css +++ b/doc/global/template/style/offline.css @@ -13,10 +13,6 @@ p { } img { - -moz-box-shadow: 3px 3px 3px #ccc; - -webkit-box-shadow: 3px 3px 3px #ccc; - box-shadow: 3px 3px 3px #ccc; - border: #8E8D8D 2px solid; margin-left: 0px; max-width: 800px; height: auto; @@ -36,7 +32,7 @@ img { .descr { margin-top: 35px; - /*max-width: 75%;*/ + margin-bottom: 45px; margin-left: 5px; text-align: left; vertical-align: top; @@ -51,6 +47,9 @@ tt { text-align: left } +.main { + display: none; +} /* ----------- links @@ -193,17 +192,19 @@ footer and license .footer { text-align: left; - margin-top: 50px; + padding-top: 45px; padding-left: 5px; - margin-bottom: 10px; + margin-top: 45px; + margin-bottom: 45px; font-size: 10px; border-top: 1px solid #999; - padding-top: 11px; } .footer p { line-height: 14px; font-size: 11px; + padding: 0; + margin: 0; } .footer a[href*="http://"], a[href*="ftp://"], a[href*="https://"] { @@ -221,7 +222,7 @@ footer and license display: block; position: relative; top: -20px; - /*border-top: 2px solid #ffffff;*/ + border-top: 1px solid #cecece; border-bottom: 1px solid #cecece; background-color: #F2F2F2; z-index: 1; @@ -288,7 +289,7 @@ headers @media screen { .title { color: #313131; - font-size: 18px; + font-size: 24px; font-weight: normal; left: 0; padding-bottom: 20px; @@ -320,7 +321,6 @@ h2, p.h2 { border-top: #E0E0DE 1px solid; border-bottom: #E0E0DE 1px solid; max-width: 99%; - overflow: hidden; } h3 { @@ -625,73 +625,6 @@ Content table clear: both } -/* start index box */ - -.indexbox { - width: 100%; - display: inline-block; -} - -.indexbox .indexIcon { - width: 11% - } - - .indexbox .indexIcon span { - display: block - } - -.indexboxcont { - display: block -} - -.indexboxcont .sectionlist { - display: inline-block; - vertical-align: top; - width: 32.5%; - padding: 0; - } - - .indexboxcont .sectionlist ul { - margin-bottom: 20px - } - - .indexboxcont .sectionlist ul li { - line-height: 1.5 - } - -.indexboxcont .indexIcon { - width: 11%; - *width: 18%; - _width: 18%; - overflow: hidden; - } - -.indexboxcont .section { - display: inline-block; - width: 49%; - *width: 42%; - _width: 42%; - padding: 0 2% 0 1%; - vertical-align: top; - } - - .indexboxcont .section p { - padding-top: 20px; - padding-bottom: 20px; - } - -.indexboxcont .section { - float: left - } - -.indexboxcont:after { - content: "."; - display: block; - height: 0; - clear: both; - visibility: hidden; -} - /* ----------- Landing page @@ -703,6 +636,19 @@ Landing page vertical-align: top; } + +.landing h2 { + background-color: transparent; + border: none; + margin-bottom: 0px; + font-size: 18px; +} + +.landing a, .landing li { + font-size: 13px; + font-weight: bold !important; +} + .col-1 { display: inline-block; white-space: normal; @@ -711,17 +657,37 @@ Landing page float: left; } -.col-1 h1 { - margin: 20px 0 0 0 - } - .col-2 { display: inline-block; white-space: normal; - width: 25%; - margin: 0 0 0 50px; + width: 20%; + margin-left: 5%; + position: relative; + top: -20px; } -.sectionlist { - width: 100% !important +.col-1 h1 { + margin: 20px 0 0 0; + } + +.col-1 h2 { + font-size: 18px; + font-weight: bold !important; +} + +.landingicons { + display: inline-block; + width: 100%; +} + +.icons1of3 { + display: inline-block; + width: 33.3333%; + float: left; +} + +.icons1of3 h2 { + font-size: 15px; + margin: 0px; + padding: 0px; } From 2d22e737757c959fff103a4a99fbd896ef09597b Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 14 Feb 2014 13:25:42 +0200 Subject: [PATCH 020/124] WinRT package_manifest: Remove comment about manifest overwrite This comment is wrong and should be removed. The manifest is always generated. Change-Id: I281737dd6a358380fb557063eadae88909f5078b Reviewed-by: Oliver Wolff --- mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in | 2 +- .../common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in | 2 +- mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in index 6a0ca444c3..42bac8b8b1 100644 --- a/mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in +++ b/mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in @@ -36,4 +36,4 @@ $${WINRT_MANIFEST.capabilities} $${WINRT_MANIFEST.dependencies} - + diff --git a/mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in index e1d3d071e9..968f42fa06 100644 --- a/mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in +++ b/mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in @@ -36,4 +36,4 @@ - + diff --git a/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in index 8c214871e3..fcc4d75b0f 100644 --- a/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in +++ b/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in @@ -41,4 +41,4 @@ $${WINRT_MANIFEST.capabilities} $${WINRT_MANIFEST.dependencies} - + From d641792ff29cae3ef92bbc76f593e9262b4789ef Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Wed, 19 Feb 2014 18:00:24 +0100 Subject: [PATCH 021/124] Fix QFontMetrics width Commit f4dd534 introduced a regression, so that QFontMetrics reported a wrong size (to be more specific width) for FreeType fonts. The calculation of glyph advances has to to reflect (rounded) integral number of pixels. This was only done when the glyph was cached. So in some cases the first call to QFontMetrics::size gave a different result than the second. This patch reverts f4dd5344fbbce257a40e014acc4e87f4773f40. The tst_QFontMetrics::same auto test only happened to work on some platforms, on BlackBerry for instance it did not. Extended the test case to make sure it works for different font sizes. Change-Id: Ia5bb9abd3ff98193c9bba048b85207672ed8d9c3 Reviewed-by: Konstantin Ritt --- src/gui/text/qfontengine_ft.cpp | 2 +- tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 242c1d8d32..c13f60ff69 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1617,7 +1617,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag face = lockFace(); g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true); glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10) - : QFixed::fromFixed(face->glyph->metrics.horiAdvance); + : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round(); if (!cacheEnabled) delete g; } diff --git a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp index 7adaac9fac..d3f5ce4a7d 100644 --- a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp +++ b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp @@ -100,6 +100,12 @@ void tst_QFontMetrics::same() const QString text = QLatin1String("Some stupid STRING"); QCOMPARE(fm.size(0, text), fm.size(0, text)) ; + for (int i = 10; i <= 32; ++i) { + font.setPixelSize(i); + QFontMetrics fm1(font); + QCOMPARE(fm1.size(0, text), fm1.size(0, text)); + } + { QImage image; QFontMetrics fm2(font, &image); From 22f0dc4f893581f53d1f030587ae535128afccf8 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 10 Jan 2014 13:19:55 +0100 Subject: [PATCH 022/124] Loosen checks for Q_COMPILER_VARIADIC_MACROS So far we did bind the definition of Q_COMPILER_VARIADIC_MACROS to C++11 (so gcc, clang will not define it in default gnu++98 standard). However, variadic macros are a feature of the gcc preprocessor since version 2.97, and are enabled in the default configurations on gcc, clang, icc. This might cause warnings and errors though if one enables additional warnings in gcc, clang (e.g. by -pedantic). Anyhow, as a precedent qglobal.h already relies on 'long long' ... The warning can be disabled by adding '-Wno-variadic-macros'. [ChangeLog][Compiler Specific Changes] Variadic macros are now enabled more liberally for gcc, clang, icc. If you have warnings (because you e.g. compile with -pedantic), disable them by -Wno-variadic-macros. Change-Id: Ie979b85809508ad70cab75e6981f20496429f463 Reviewed-by: Thiago Macieira --- src/corelib/global/qcompilerdetection.h | 19 ++++++++++++++++--- .../kernel/qmetatype/tst_qmetatype.cpp | 5 +++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 70f45345c6..1eb442aa5f 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -489,6 +489,7 @@ #ifdef Q_CC_INTEL # define Q_COMPILER_RESTRICTED_VLA +# define Q_COMPILER_VARIADIC_MACROS // C++11 feature supported as an extension in other modes, too # if __INTEL_COMPILER < 1200 # define Q_NO_TEMPLATE_FRIENDS # endif @@ -498,7 +499,6 @@ # define Q_COMPILER_BINARY_LITERALS # endif # if __cplusplus >= 201103L -# define Q_COMPILER_VARIADIC_MACROS # if __INTEL_COMPILER >= 1200 # define Q_COMPILER_AUTO_TYPE # define Q_COMPILER_CLASS_ENUM @@ -560,6 +560,15 @@ # define Q_COMPILER_BINARY_LITERALS # endif +// Variadic macros are supported for gnu++98, c++11, c99 ... since 2.9 +# if ((__clang_major__ * 100) + __clang_minor__) >= 209 +# if !defined(__STRICT_ANSI__) || defined(__GXX_EXPERIMENTAL_CXX0X__) \ + || (defined(__cplusplus) && (__cplusplus >= 201103L)) \ + || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) +# define Q_COMPILER_VARIADIC_MACROS +# endif +# endif + /* C++11 features, see http://clang.llvm.org/cxx_status.html */ # if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) /* Detect C++ features using __has_feature(), see http://clang.llvm.org/docs/LanguageExtensions.html#cxx11 */ @@ -656,7 +665,6 @@ /* Features that have no __has_feature() check */ # if ((__clang_major__ * 100) + __clang_minor__) >= 209 /* since clang 2.9 */ # define Q_COMPILER_EXTERN_TEMPLATES -# define Q_COMPILER_VARIADIC_MACROS # endif # endif @@ -693,13 +701,18 @@ // GCC supports binary literals in C, C++98 and C++11 modes # define Q_COMPILER_BINARY_LITERALS # endif +# if !defined(__STRICT_ANSI__) || defined(__GXX_EXPERIMENTAL_CXX0X__) \ + || (defined(__cplusplus) && (__cplusplus >= 201103L)) \ + || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) + // Variadic macros are supported for gnu++98, c++11, C99 ... since forever (gcc 2.97) +# define Q_COMPILER_VARIADIC_MACROS +# endif # if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 /* C++11 features supported in GCC 4.3: */ # define Q_COMPILER_DECLTYPE # define Q_COMPILER_RVALUE_REFS # define Q_COMPILER_STATIC_ASSERT -# define Q_COMPILER_VARIADIC_MACROS # endif # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 /* C++11 features supported in GCC 4.4: */ diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 47900204e7..211633f888 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -55,6 +55,11 @@ # define TST_QMETATYPE_BROKEN_COMPILER #endif +// mingw gcc 4.8 also takes way too long, letting the CI system abort the test +#if defined(__MINGW32__) +# define TST_QMETATYPE_BROKEN_COMPILER +#endif + Q_DECLARE_METATYPE(QMetaType::Type) class tst_QMetaType: public QObject From 42afcfd8ce2fec86836d2414ee1e6d88f42613f3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 20 Feb 2014 14:39:28 +0100 Subject: [PATCH 023/124] Windows: Ensure clipboard is flushed out before QGuiApplication is destroyed. Otherwise, OleFlushClipboard() might query the data again which causes problems for QMimeData-derived classes using QPixmap/QImage. Task-number: QTBUG-36958 Change-Id: I89e58eeb64bd3481e89ad789f310f19ddb4604a2 Reviewed-by: Joerg Bornemann --- .../platforms/windows/qwindowsclipboard.cpp | 18 +++++++++++++++++- .../platforms/windows/qwindowsclipboard.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index 5370d556fd..dcfeba12fa 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -132,19 +132,35 @@ extern "C" LRESULT QT_WIN_CALLBACK qClipboardViewerWndProc(HWND hwnd, UINT messa return DefWindowProc(hwnd, message, wParam, lParam); } +// QTBUG-36958, ensure the clipboard is flushed before +// QGuiApplication is destroyed since OleFlushClipboard() +// might query the data again which causes problems +// for QMimeData-derived classes using QPixmap/QImage. +static void cleanClipboardPostRoutine() +{ + if (QWindowsClipboard *cl = QWindowsClipboard::instance()) + cl->cleanup(); +} + QWindowsClipboard *QWindowsClipboard::m_instance = 0; QWindowsClipboard::QWindowsClipboard() : m_data(0), m_clipboardViewer(0), m_nextClipboardViewer(0) { QWindowsClipboard::m_instance = this; + qAddPostRoutine(cleanClipboardPostRoutine); } QWindowsClipboard::~QWindowsClipboard() +{ + cleanup(); + QWindowsClipboard::m_instance = 0; +} + +void QWindowsClipboard::cleanup() { unregisterViewer(); // Should release data if owner. releaseIData(); - QWindowsClipboard::m_instance = 0; } void QWindowsClipboard::releaseIData() diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h index ad7ee6437f..30bc0143f4 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.h +++ b/src/plugins/platforms/windows/qwindowsclipboard.h @@ -64,6 +64,7 @@ public: QWindowsClipboard(); ~QWindowsClipboard(); void registerViewer(); // Call in initialization, when context is up. + void cleanup(); virtual QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard); virtual void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard); From ef2527df6803f43519a84c15f6bf2ff9f69ef25c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 20 Feb 2014 17:16:29 +0100 Subject: [PATCH 024/124] QTextObject: replace a use of an inefficient QList with QVector The QTextLayout::FormatRange is larger than void* and thus should not be held in QList. Use a QVector instead. This is public, but as of yet unreleased API. Change-Id: Ie04a561b43c91c3b2befb3cac2981821f84d5f77 Reviewed-by: Lars Knoll Reviewed-by: Gunnar Sletta Reviewed-by: Konstantin Ritt --- src/gui/text/qtextobject.cpp | 4 ++-- src/gui/text/qtextobject.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index bd1e970583..c0342c0d4e 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1242,9 +1242,9 @@ QString QTextBlock::text() const \sa charFormat(), blockFormat() */ -QList QTextBlock::textFormats() const +QVector QTextBlock::textFormats() const { - QList formats; + QVector formats; if (!p || !n) return formats; diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index 6a127f0315..8138854348 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -223,7 +223,7 @@ public: QString text() const; - QList textFormats() const; + QVector textFormats() const; const QTextDocument *document() const; From 5e05c230af6b53d4323d3d8a445c5af1b1ba546a Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 18 Feb 2014 15:35:13 +0200 Subject: [PATCH 025/124] Fix paint artifacts. Android is using double buffering, so, we need to repaint the bounding rect of the repaint region, otherwise black holes will appear. Change-Id: I21f36a6f5f1a6c64b605c0fef3af10dfdc5ec6e2 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../android/qandroidplatformrasterwindow.cpp | 5 +- .../android/qandroidplatformscreen.cpp | 58 +++++++++---------- .../android/qandroidplatformscreen.h | 2 +- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp b/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp index 68545c6562..334b9cdd23 100644 --- a/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformrasterwindow.cpp @@ -54,6 +54,9 @@ QAndroidPlatformRasterWindow::QAndroidPlatformRasterWindow(QWindow *window) void QAndroidPlatformRasterWindow::repaint(const QRegion ®ion) { + if (QAndroidPlatformWindow::parent()) + return; + QRect currentGeometry = geometry().translated(mapToGlobal(QPoint(0,0))); QRect dirtyClient = region.boundingRect(); @@ -71,7 +74,7 @@ void QAndroidPlatformRasterWindow::repaint(const QRegion ®ion) void QAndroidPlatformRasterWindow::setGeometry(const QRect &rect) { - m_oldGeometry = geometry(); + m_oldGeometry = geometry().translated(mapToGlobal(QPoint(0,0)));; QAndroidPlatformWindow::setGeometry(rect); } diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index dd86a80d23..c6c2c13565 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -197,7 +197,7 @@ void QAndroidPlatformScreen::scheduleUpdate() void QAndroidPlatformScreen::setDirty(const QRect &rect) { QRect intersection = rect.intersected(m_geometry); - m_repaintRegion += intersection; + m_dirtyRect |= intersection; scheduleUpdate(); } @@ -241,11 +241,9 @@ void QAndroidPlatformScreen::doRedraw() { PROFILE_SCOPE; - if (m_repaintRegion.isEmpty()) + if (m_dirtyRect.isEmpty()) return; - QVector rects = m_repaintRegion.rects(); - QMutexLocker lock(&m_surfaceMutex); if (m_id == -1) { m_id = QtAndroid::createSurface(this, m_geometry, true); @@ -257,11 +255,10 @@ void QAndroidPlatformScreen::doRedraw() ANativeWindow_Buffer nativeWindowBuffer; ARect nativeWindowRect; - QRect br = m_repaintRegion.boundingRect(); - nativeWindowRect.top = br.top(); - nativeWindowRect.left = br.left(); - nativeWindowRect.bottom = br.bottom() + 1; // for some reason that I don't understand the QRect bottom needs to +1 to be the same with ARect bottom - nativeWindowRect.right = br.right() + 1; // same for the right + nativeWindowRect.top = m_dirtyRect.top(); + nativeWindowRect.left = m_dirtyRect.left(); + nativeWindowRect.bottom = m_dirtyRect.bottom() + 1; // for some reason that I don't understand the QRect bottom needs to +1 to be the same with ARect bottom + nativeWindowRect.right = m_dirtyRect.right() + 1; // same for the right int ret; if ((ret = ANativeWindow_lock(m_nativeSurface, &nativeWindowBuffer, &nativeWindowRect)) < 0) { @@ -283,36 +280,35 @@ void QAndroidPlatformScreen::doRedraw() QPainter compositePainter(&screenImage); compositePainter.setCompositionMode(QPainter::CompositionMode_Source); - for (int rectIndex = 0; rectIndex < rects.size(); rectIndex++) { - QRegion visibleRegion = rects[rectIndex]; - foreach (QAndroidPlatformWindow *window, m_windowStack) { - if (!window->window()->isVisible() - || !window->isRaster()) + QRegion visibleRegion(m_dirtyRect); + foreach (QAndroidPlatformWindow *window, m_windowStack) { + if (!window->window()->isVisible() + || !window->isRaster()) + continue; + + QVector visibleRects = visibleRegion.rects(); + foreach (const QRect &rect, visibleRects) { + QRect targetRect = window->geometry(); + targetRect &= rect; + + if (targetRect.isNull()) continue; - foreach (const QRect &rect, visibleRegion.rects()) { - QRect targetRect = window->geometry(); - targetRect &= rect; - - if (targetRect.isNull()) - continue; - - visibleRegion -= targetRect; - QRect windowRect = targetRect.translated(-window->geometry().topLeft()); - QAndroidPlatformBackingStore *backingStore = static_cast(window)->backingStore(); - if (backingStore) - compositePainter.drawImage(targetRect.topLeft(), backingStore->image(), windowRect); - } + visibleRegion -= targetRect; + QRect windowRect = targetRect.translated(-window->geometry().topLeft()); + QAndroidPlatformBackingStore *backingStore = static_cast(window)->backingStore(); + if (backingStore) + compositePainter.drawImage(targetRect.topLeft(), backingStore->image(), windowRect); } + } - foreach (const QRect &rect, visibleRegion.rects()) { - compositePainter.fillRect(rect, QColor(Qt::transparent)); - } + foreach (const QRect &rect, visibleRegion.rects()) { + compositePainter.fillRect(rect, QColor(Qt::transparent)); } ret = ANativeWindow_unlockAndPost(m_nativeSurface); if (ret >= 0) - m_repaintRegion = QRegion(); + m_dirtyRect = QRect(); } QDpi QAndroidPlatformScreen::logicalDpi() const diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h index d3de937548..625e77840e 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.h +++ b/src/plugins/platforms/android/qandroidplatformscreen.h @@ -91,7 +91,7 @@ public slots: protected: typedef QList WindowStackType; WindowStackType m_windowStack; - QRegion m_repaintRegion; + QRect m_dirtyRect; QTimer m_redrawTimer; QRect m_geometry; From 4d08d80be60af14c5daed7c6f8d37538aea6c429 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Fri, 21 Feb 2014 16:08:06 +0200 Subject: [PATCH 026/124] Rework the splash screen for Android. Allow the developers to define a splash screen which will be visible until the first window is created. [ChangeLog][Android] Allow the developers to define a splash screen which will be visible until the first window is created. Task-number: QTBUG-30652 Change-Id: I5da80be417ffffb03e66009f45745d4b387d2912 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qt5/android/QtActivityDelegate.java | 19 ++++++++++++++++--- src/android/java/AndroidManifest.xml | 5 ++++- src/android/java/res/layout/splash.xml | 13 ------------- .../qt5/android/bindings/QtActivity.java | 4 ++-- src/android/java/version.xml | 2 +- 5 files changed, 23 insertions(+), 20 deletions(-) delete mode 100644 src/android/java/res/layout/splash.xml diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 4b80d68761..620ea22dad 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -48,6 +48,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; +import android.graphics.drawable.ColorDrawable; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; @@ -56,6 +57,7 @@ import android.os.ResultReceiver; import android.text.method.MetaKeyKeyListener; import android.util.DisplayMetrics; import android.util.Log; +import android.util.TypedValue; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.KeyCharacterMap; @@ -653,9 +655,6 @@ public class QtActivityDelegate m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE); m_surfaces = new HashMap(); m_nativeViews = new HashMap(); - m_activity.setContentView(m_layout, - new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); m_activity.registerForContextMenu(m_layout); int orientation = m_activity.getResources().getConfiguration().orientation; @@ -989,6 +988,20 @@ public class QtActivityDelegate } public void createSurface(int id, boolean onTop, int x, int y, int w, int h) { + if (m_surfaces.size() == 0) { + TypedValue attr = new TypedValue(); + m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true); + if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) { + m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(attr.data)); + } else { + m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId)); + } + + m_activity.setContentView(m_layout, + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + } + if (m_surfaces.containsKey(id)) m_layout.removeView(m_surfaces.remove(id)); diff --git a/src/android/java/AndroidManifest.xml b/src/android/java/AndroidManifest.xml index defbe502ef..3a2a52b874 100644 --- a/src/android/java/AndroidManifest.xml +++ b/src/android/java/AndroidManifest.xml @@ -29,8 +29,11 @@ + - + diff --git a/src/android/java/res/layout/splash.xml b/src/android/java/res/layout/splash.xml deleted file mode 100644 index 6b0d492dd5..0000000000 --- a/src/android/java/res/layout/splash.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index b2f92c04e9..3a0eaa77d6 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -858,8 +858,8 @@ public class QtActivity extends Activity if (null == getLastNonConfigurationInstance()) { // if splash screen is defined, then show it - if (m_activityInfo.metaData.containsKey("android.app.splash_screen") ) - setContentView(m_activityInfo.metaData.getInt("android.app.splash_screen")); + if (m_activityInfo.metaData.containsKey("android.app.splash_screen_drawable")) + getWindow().setBackgroundDrawableResource(m_activityInfo.metaData.getInt("android.app.splash_screen_drawable")); startApp(true); } } diff --git a/src/android/java/version.xml b/src/android/java/version.xml index bdcf915c06..e05bba7588 100644 --- a/src/android/java/version.xml +++ b/src/android/java/version.xml @@ -1,4 +1,4 @@ - + AndroidManifest.xml libs.xml From ba77406c4db35f092591fe09fde9a6574ab3a493 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 19 Feb 2014 16:38:00 +0100 Subject: [PATCH 027/124] Avoid truncation warning in openglwindow example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit msvc shows a warning about double -> float truncation. Avoid this. Change-Id: I1b74cf407c81c881df5e95cc7d64a210888595e3 Reviewed-by: Jørgen Lind Reviewed-by: Gunnar Sletta --- examples/gui/openglwindow/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gui/openglwindow/main.cpp b/examples/gui/openglwindow/main.cpp index 237680a889..aa1c6d7fa1 100644 --- a/examples/gui/openglwindow/main.cpp +++ b/examples/gui/openglwindow/main.cpp @@ -144,7 +144,7 @@ void TriangleWindow::render() m_program->bind(); QMatrix4x4 matrix; - matrix.perspective(60, 4.0/3.0, 0.1, 100.0); + matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f); matrix.translate(0, 0, -2); matrix.rotate(100.0f * m_frame / screen()->refreshRate(), 0, 1, 0); From 727f50d11e33d8ae66a92bdbf932dbac14d4dcf8 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 14 Feb 2014 16:31:49 +0100 Subject: [PATCH 028/124] Remove QT_OPENGLPROXY_DEBUG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iac4c5217eca88ac14acca55d19e421d8e33cdb1d Reviewed-by: Jørgen Lind Reviewed-by: Friedemann Kleint --- src/gui/opengl/qopenglproxy_win.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/gui/opengl/qopenglproxy_win.cpp b/src/gui/opengl/qopenglproxy_win.cpp index 83c3073f63..88f3a1d11d 100644 --- a/src/gui/opengl/qopenglproxy_win.cpp +++ b/src/gui/opengl/qopenglproxy_win.cpp @@ -680,9 +680,6 @@ static HMODULE qgl_loadLib(const char *name, bool warnOnFail = true) QWindowsOpenGL::QWindowsOpenGL() : m_eglLib(0) { - if (qEnvironmentVariableIsSet("QT_OPENGLPROXY_DEBUG")) - QLoggingCategory::setFilterRules(QStringLiteral("qt.gui.openglproxy=true")); - enum RequestedLib { Unknown, Desktop, From 1e413e01e06fcd3ca750dea799cb053801b96c3c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Feb 2014 18:00:11 +0100 Subject: [PATCH 029/124] eglfs: Fix swapped red and blue with QOpenGLWidget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0793d0b53c0e7df65fecfe43ef9daaf07413ea77 Reviewed-by: Jørgen Lind --- src/platformsupport/eglconvenience/qeglcompositor.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/platformsupport/eglconvenience/qeglcompositor.cpp b/src/platformsupport/eglconvenience/qeglcompositor.cpp index a38f00d4f6..0e0a2d9375 100644 --- a/src/platformsupport/eglconvenience/qeglcompositor.cpp +++ b/src/platformsupport/eglconvenience/qeglcompositor.cpp @@ -119,16 +119,21 @@ void QEGLCompositor::render(QEGLPlatformWindow *window) glBindTexture(GL_TEXTURE_2D, textureId); QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect); - m_blitter->setSwizzleRB(window->isRaster()); if (textures->count() > 1 && i == textures->count() - 1) { + // Backingstore for a widget with QOpenGLWidget subwidgets + m_blitter->setSwizzleRB(true); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); glDisable(GL_BLEND); } else if (textures->count() == 1) { + // A regular QWidget window + m_blitter->setSwizzleRB(true); m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); } else { + // Texture from an FBO belonging to a QOpenGLWidget + m_blitter->setSwizzleRB(false); m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft); } } From 3c50119625fec9c0a1e6d056f6f7e9f59e730c36 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 18 Feb 2014 14:11:34 +0100 Subject: [PATCH 030/124] Avoid using GLX Pbuffers on Catalyst Trigger QOffscreenSurface's fallback mode (hidden QWindow and a regular window surface) instead. queryDummyContext() already works like this but the same must be done for any QOffscreenSurface. Task-number: QTBUG-36900 Change-Id: I64176ac6704e9d6ed768fa3d456c40c8818be6dc Reviewed-by: Gunnar Sletta Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbintegration.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 768a591ab5..aaa2e81c40 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -253,7 +253,18 @@ QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *wind QPlatformOffscreenSurface *QXcbIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { #if defined(XCB_USE_GLX) - return new QGLXPbuffer(surface); + static bool vendorChecked = false; + static bool glxPbufferUsable = true; + if (!vendorChecked) { + vendorChecked = true; + const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR); + if (glxvendor && !strcmp(glxvendor, "ATI")) + glxPbufferUsable = false; + } + if (glxPbufferUsable) + return new QGLXPbuffer(surface); + else + return 0; // trigger fallback to hidden QWindow #elif defined(XCB_USE_EGL) QXcbScreen *screen = static_cast(surface->screen()->handle()); return new QEGLPbuffer(screen->connection()->egl_display(), surface->requestedFormat(), surface); From 54d43c6480ff033ad80165a2da02d2e01f708cf4 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Feb 2014 15:33:22 +0100 Subject: [PATCH 031/124] Expose NPOTTextureRepeat in QOpenGLFunctions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Desktop GL 2.0 and higher supports GL_REPEAT on non-power-of-two textures. GL_ARB_texture_non_power_of_two mentions this explicitly in issue #8. Change-Id: Ia7f3b412b39cca4bec8a6caec3b1281b4c29ab75 Reviewed-by: Jørgen Lind Reviewed-by: Friedemann Kleint Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopenglfunctions.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index 150e7dcb32..60743b3a27 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -314,7 +314,8 @@ static int qt_gl_resolve_features() if (extensions.match("GL_ARB_multisample")) features |= QOpenGLFunctions::Multisample; if (extensions.match("GL_ARB_texture_non_power_of_two")) - features |= QOpenGLFunctions::NPOTTextures; + features |= QOpenGLFunctions::NPOTTextures | + QOpenGLFunctions::NPOTTextureRepeat; // assume version 2.0 or higher features |= QOpenGLFunctions::BlendColor | @@ -327,7 +328,8 @@ static int qt_gl_resolve_features() QOpenGLFunctions::Shaders | QOpenGLFunctions::StencilSeparate | QOpenGLFunctions::BlendEquationSeparate | - QOpenGLFunctions::NPOTTextures; + QOpenGLFunctions::NPOTTextures | + QOpenGLFunctions::NPOTTextureRepeat; if (format.majorVersion() >= 3) features |= QOpenGLFunctions::Framebuffers; From ecd3027d385fd0f41cf7d970fc9273965e04ffc3 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 11 Apr 2013 10:23:01 +0200 Subject: [PATCH 032/124] Strip any trailing spaces from the filename before trying to open it On Windows, trailing spaces in a filename are silently ignored, so we need to strip it before trying to open a file with it. Otherwise it ends up being stripped later and in a case like " ." it will end up causing Qt to think that a folder exists when it does not. [ChangeLog][Platform Specific Changes][Windows][QtWidgets][QFileDialog] Handled the case of having trailing spaces in a filename correctly so if the filename ends up being empty that the parent path is used instead. Change-Id: I6500cc3a44746bf4a65e73bcfb63265a0a97c8a3 Reviewed-by: Stephen Kelly Reviewed-by: Marc Mutz --- src/widgets/dialogs/qfilesystemmodel.cpp | 13 +++++++-- .../dialogs/qfiledialog/tst_qfiledialog.cpp | 28 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index bda448bde3..0b0f686564 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -401,9 +401,18 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS for (int i = 0; i < pathElements.count(); ++i) { QString element = pathElements.at(i); #ifdef Q_OS_WIN - // On Windows, "filename......." and "filename" are equivalent Task #133928 - while (element.endsWith(QLatin1Char('.'))) + // On Windows, "filename " and "filename" are equivalent and + // "filename . " and "filename" are equivalent + // "filename......." and "filename" are equivalent Task #133928 + // whereas "filename .txt" is still "filename .txt" + // If after stripping the characters there is nothing left then we + // just return the parent directory as it is assumed that the path + // is referring to the parent + while (element.endsWith(QLatin1Char('.')) || element.endsWith(QLatin1Char(' '))) element.chop(1); + // Only filenames that can't possibly exist will be end up being empty + if (element.isEmpty()) + return parent; #endif bool alreadyExisted = parent->children.contains(element); diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index 8bad4bb176..54a3a85e87 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -148,6 +148,7 @@ private slots: void enableChooseButton(); void hooks(); void widgetlessNativeDialog(); + void trailingDotsAndSpaces(); #ifdef Q_OS_UNIX #ifdef QT_BUILD_INTERNAL void tildeExpansion_data(); @@ -1413,6 +1414,33 @@ void tst_QFiledialog::widgetlessNativeDialog() QVERIFY(!button); } +void tst_QFiledialog::trailingDotsAndSpaces() +{ +#ifndef Q_OS_WIN + QSKIP("This is only tested on Windows"); +#endif + QNonNativeFileDialog fd; + fd.setViewMode(QFileDialog::List); + fd.setFileMode(QFileDialog::ExistingFile); + fd.setOptions(QFileDialog::DontUseNativeDialog); + fd.show(); + QLineEdit *lineEdit = fd.findChild("fileNameEdit"); + QVERIFY(lineEdit); + QListView *list = fd.findChild("listView"); + QVERIFY(list); + QTest::qWait(1000); + int currentChildrenCount = list->model()->rowCount(list->rootIndex()); + QTest::keyClick(lineEdit, Qt::Key_Space); + QTest::keyClick(lineEdit, Qt::Key_Period); + QTest::qWait(1000); + QVERIFY(currentChildrenCount == list->model()->rowCount(list->rootIndex())); + lineEdit->clear(); + QTest::keyClick(lineEdit, Qt::Key_Period); + QTest::keyClick(lineEdit, Qt::Key_Space); + QTest::qWait(1000); + QVERIFY(currentChildrenCount == list->model()->rowCount(list->rootIndex())); +} + #ifdef Q_OS_UNIX #ifdef QT_BUILD_INTERNAL void tst_QFiledialog::tildeExpansion_data() From 388745ecc84ed2723150ea46ce6e5257bb0ea15f Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 18 Feb 2014 15:25:07 +0200 Subject: [PATCH 033/124] Sort include headers Change-Id: I453a40d57a7c3d6062c23f6772de1b8330f61067 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../android/qandroidplatformintegration.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 5848e94aca..2cca974b41 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -50,21 +50,20 @@ #include #include -#warning sort the headers #include "androidjnimain.h" #include "qabstracteventdispatcher.h" -#include "qandroidplatformrasterwindow.h" -#include "qandroidplatformopenglwindow.h" #include "qandroidplatformbackingstore.h" -#include "qandroidplatformservices.h" -#include "qandroidplatformfontdatabase.h" -#include "qandroidplatformclipboard.h" #include "qandroidplatformaccessibility.h" +#include "qandroidplatformclipboard.h" +#include "qandroidplatformforeignwindow.h" +#include "qandroidplatformfontdatabase.h" #include "qandroidplatformopenglcontext.h" +#include "qandroidplatformopenglwindow.h" +#include "qandroidplatformrasterwindow.h" #include "qandroidplatformscreen.h" +#include "qandroidplatformservices.h" #include "qandroidplatformtheme.h" #include "qandroidsystemlocale.h" -#include "qandroidplatformforeignwindow.h" QT_BEGIN_NAMESPACE From b9feb884664aa8869ebfafbd8b3a8c65f668574e Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 18 Feb 2014 15:26:30 +0200 Subject: [PATCH 034/124] Start the chronometer. Change-Id: Ia165ce4a79b108ddb0d74a7d8fccd4f48fe14442 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/android/qandroidplatformscreen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index c6c2c13565..3704097414 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -64,6 +64,7 @@ public: ScopedProfiler(const QString &msg) { m_msg = msg; + m_timer.start(); } ~ScopedProfiler() { From db352e1e97a0eb38cb5756f264b3162efeb86c02 Mon Sep 17 00:00:00 2001 From: John Layt Date: Fri, 14 Feb 2014 01:45:37 +0100 Subject: [PATCH 035/124] QRect - Move QMargins operators Move QMargins operators to QRect file, change include sequence. Change-Id: I0e2ad91859ae65eb67c6ece50f8e4037516b463e Reviewed-by: Lars Knoll Reviewed-by: Friedemann Kleint --- src/corelib/tools/qmargins.cpp | 59 ---------------------------------- src/corelib/tools/qmargins.h | 37 +-------------------- src/corelib/tools/qrect.cpp | 59 ++++++++++++++++++++++++++++++++++ src/corelib/tools/qrect.h | 43 ++++++++++++++++++++++--- 4 files changed, 99 insertions(+), 99 deletions(-) diff --git a/src/corelib/tools/qmargins.cpp b/src/corelib/tools/qmargins.cpp index c5bd8468bc..06f41a6737 100644 --- a/src/corelib/tools/qmargins.cpp +++ b/src/corelib/tools/qmargins.cpp @@ -157,65 +157,6 @@ QT_BEGIN_NAMESPACE Returns \c true if \a m1 and \a m2 are different; otherwise returns \c false. */ -/*! - \fn QRect operator+(const QRect &rectangle, const QMargins &margins) - \relates QRect - - Returns the \a rectangle grown by the \a margins. - - \since 5.1 -*/ - -/*! - \fn QRect operator+(const QMargins &margins, const QRect &rectangle) - \relates QRect - \overload - - Returns the \a rectangle grown by the \a margins. - - \since 5.1 -*/ - -/*! - \fn QRect QRect::marginsAdded(const QMargins &margins) const - - Returns a rectangle grown by the \a margins. - - \sa operator+=(), marginsRemoved(), operator-=() - - \since 5.1 -*/ - -/*! - \fn QRect QRect::operator+=(const QMargins &margins) const - - Adds the \a margins to the rectangle, growing it. - - \sa marginsAdded(), marginsRemoved(), operator-=() - - \since 5.1 -*/ - -/*! - \fn QRect QRect::marginsRemoved(const QMargins &margins) const - - Removes the \a margins from the rectangle, shrinking it. - - \sa marginsAdded(), operator+=(), operator-=() - - \since 5.1 -*/ - -/*! - \fn QRect QRect::operator -=(const QMargins &margins) const - - Returns a rectangle shrunk by the \a margins. - - \sa marginsRemoved(), operator+=(), marginsAdded() - - \since 5.1 -*/ - /*! \fn const QMargins operator+(const QMargins &m1, const QMargins &m2) \relates QMargins diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h index ad5e94cefe..6bffa544c1 100644 --- a/src/corelib/tools/qmargins.h +++ b/src/corelib/tools/qmargins.h @@ -42,7 +42,7 @@ #ifndef QMARGINS_H #define QMARGINS_H -#include +#include QT_BEGIN_NAMESPACE @@ -149,41 +149,6 @@ Q_DECL_CONSTEXPR inline bool operator!=(const QMargins &m1, const QMargins &m2) m1.m_bottom != m2.m_bottom; } -Q_DECL_CONSTEXPR inline QRect operator+(const QRect &rectangle, const QMargins &margins) -{ - return QRect(QPoint(rectangle.left() - margins.left(), rectangle.top() - margins.top()), - QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom())); -} - -Q_DECL_CONSTEXPR inline QRect operator+(const QMargins &margins, const QRect &rectangle) -{ - return QRect(QPoint(rectangle.left() - margins.left(), rectangle.top() - margins.top()), - QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom())); -} - -inline QRect QRect::marginsAdded(const QMargins &margins) const -{ - return *this + margins; -} - -inline QRect QRect::marginsRemoved(const QMargins &margins) const -{ - return QRect(QPoint(x1 + margins.left(), y1 + margins.top()), - QPoint(x2 - margins.right(), y2 - margins.bottom())); -} - -inline QRect &QRect::operator+=(const QMargins &margins) -{ - *this = marginsAdded(margins); - return *this; -} - -inline QRect &QRect::operator-=(const QMargins &margins) -{ - *this = marginsRemoved(margins); - return *this; -} - Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &m1, const QMargins &m2) { return QMargins(m1.left() + m2.left(), m1.top() + m2.top(), diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index fcff8931e8..e67b74ea6c 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -1162,6 +1162,65 @@ bool QRect::intersects(const QRect &r) const returns \c false. */ +/*! + \fn QRect operator+(const QRect &rectangle, const QMargins &margins) + \relates QRect + + Returns the \a rectangle grown by the \a margins. + + \since 5.1 +*/ + +/*! + \fn QRect operator+(const QMargins &margins, const QRect &rectangle) + \relates QRect + \overload + + Returns the \a rectangle grown by the \a margins. + + \since 5.1 +*/ + +/*! + \fn QRect QRect::marginsAdded(const QMargins &margins) const + + Returns a rectangle grown by the \a margins. + + \sa operator+=(), marginsRemoved(), operator-=() + + \since 5.1 +*/ + +/*! + \fn QRect QRect::operator+=(const QMargins &margins) const + + Adds the \a margins to the rectangle, growing it. + + \sa marginsAdded(), marginsRemoved(), operator-=() + + \since 5.1 +*/ + +/*! + \fn QRect QRect::marginsRemoved(const QMargins &margins) const + + Removes the \a margins from the rectangle, shrinking it. + + \sa marginsAdded(), operator+=(), operator-=() + + \since 5.1 +*/ + +/*! + \fn QRect QRect::operator -=(const QMargins &margins) const + + Returns a rectangle shrunk by the \a margins. + + \sa marginsRemoved(), operator+=(), marginsAdded() + + \since 5.1 +*/ + /***************************************************************************** QRect stream functions diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index 22696f9edf..52f1a79362 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -42,6 +42,7 @@ #ifndef QRECT_H #define QRECT_H +#include #include #include @@ -51,8 +52,6 @@ QT_BEGIN_NAMESPACE -class QMargins; - class Q_CORE_EXPORT QRect { public: @@ -138,8 +137,8 @@ public: inline QRect intersected(const QRect &other) const; bool intersects(const QRect &r) const; - inline QRect marginsAdded(const QMargins &margins) const; - inline QRect marginsRemoved(const QMargins &margins) const; + Q_DECL_CONSTEXPR inline QRect marginsAdded(const QMargins &margins) const; + Q_DECL_CONSTEXPR inline QRect marginsRemoved(const QMargins &margins) const; inline QRect &operator+=(const QMargins &margins); inline QRect &operator-=(const QMargins &margins); @@ -452,6 +451,42 @@ Q_DECL_CONSTEXPR inline bool operator!=(const QRect &r1, const QRect &r2) return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2; } +Q_DECL_CONSTEXPR inline QRect operator+(const QRect &rectangle, const QMargins &margins) +{ + return QRect(QPoint(rectangle.left() - margins.left(), rectangle.top() - margins.top()), + QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom())); +} + +Q_DECL_CONSTEXPR inline QRect operator+(const QMargins &margins, const QRect &rectangle) +{ + return QRect(QPoint(rectangle.left() - margins.left(), rectangle.top() - margins.top()), + QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom())); +} + +Q_DECL_CONSTEXPR inline QRect QRect::marginsAdded(const QMargins &margins) const +{ + return QRect(QPoint(x1 - margins.left(), y1 - margins.top()), + QPoint(x2 + margins.right(), y2 + margins.bottom())); +} + +Q_DECL_CONSTEXPR inline QRect QRect::marginsRemoved(const QMargins &margins) const +{ + return QRect(QPoint(x1 + margins.left(), y1 + margins.top()), + QPoint(x2 - margins.right(), y2 - margins.bottom())); +} + +inline QRect &QRect::operator+=(const QMargins &margins) +{ + *this = marginsAdded(margins); + return *this; +} + +inline QRect &QRect::operator-=(const QMargins &margins) +{ + *this = marginsRemoved(margins); + return *this; +} + #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const QRect &); #endif From 9c6447e0815a18102e5ebe236c52ba4343dbb8fa Mon Sep 17 00:00:00 2001 From: John Layt Date: Fri, 14 Feb 2014 15:23:47 +0100 Subject: [PATCH 036/124] QMargins - Add missing operators Add missing standard operators. [ChangeLog][QtCore][QMargins] Added missing addition and subtraction operators. Change-Id: I6aeed39531a736c12d378a817a9431279da79bc4 Reviewed-by: Lars Knoll Reviewed-by: Friedemann Kleint --- src/corelib/tools/qmargins.cpp | 45 +++++++++++++++++++ src/corelib/tools/qmargins.h | 23 ++++++++++ .../corelib/tools/qmargins/tst_qmargins.cpp | 7 +++ 3 files changed, 75 insertions(+) diff --git a/src/corelib/tools/qmargins.cpp b/src/corelib/tools/qmargins.cpp index 06f41a6737..7d8a167a88 100644 --- a/src/corelib/tools/qmargins.cpp +++ b/src/corelib/tools/qmargins.cpp @@ -181,6 +181,42 @@ QT_BEGIN_NAMESPACE \since 5.1 */ +/*! + \fn const QMargins operator+(const QMargins &lhs, int rhs) + \relates QMargins + + Returns a QMargins object that is formed by adding \a rhs to + \a lhs. + + \sa QMargins::operator+=(), QMargins::operator-=() + + \since 5.3 +*/ + +/*! + \fn const QMargins operator+(int lhs, const QMargins &rhs) + \relates QMargins + + Returns a QMargins object that is formed by adding \a lhs to + \a rhs. + + \sa QMargins::operator+=(), QMargins::operator-=() + + \since 5.3 +*/ + +/*! + \fn const QMargins operator-(const QMargins &lhs, int rhs) + \relates QMargins + + Returns a QMargins object that is formed by subtracting \a rhs from + \a lhs. + + \sa QMargins::operator+=(), QMargins::operator-=() + + \since 5.3 +*/ + /*! \fn const QMargins operator*(const QMargins &margins, int factor) \relates QMargins @@ -257,6 +293,15 @@ QT_BEGIN_NAMESPACE \since 5.1 */ +/*! + \fn QMargins operator+(const QMargins &margins) + \relates QMargins + + Returns a QMargin object that is formed from all components of \a margins. + + \since 5.3 +*/ + /*! \fn QMargins operator-(const QMargins &margins) \relates QMargins diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h index 6bffa544c1..55355ac859 100644 --- a/src/corelib/tools/qmargins.h +++ b/src/corelib/tools/qmargins.h @@ -161,6 +161,24 @@ Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &m1, const QMargins &m m1.right() - m2.right(), m1.bottom() - m2.bottom()); } +Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &lhs, int rhs) +{ + return QMargins(lhs.left() + rhs, lhs.top() + rhs, + lhs.right() + rhs, lhs.bottom() + rhs); +} + +Q_DECL_CONSTEXPR inline QMargins operator+(int lhs, const QMargins &rhs) +{ + return QMargins(rhs.left() + lhs, rhs.top() + lhs, + rhs.right() + lhs, rhs.bottom() + lhs); +} + +Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &lhs, int rhs) +{ + return QMargins(lhs.left() - rhs, lhs.top() - rhs, + lhs.right() - rhs, lhs.bottom() - rhs); +} + Q_DECL_CONSTEXPR inline QMargins operator*(const QMargins &margins, int factor) { return QMargins(margins.left() * factor, margins.top() * factor, @@ -245,6 +263,11 @@ inline QMargins &QMargins::operator/=(qreal divisor) return *this = *this / divisor; } +Q_DECL_CONSTEXPR inline QMargins operator+(const QMargins &margins) +{ + return margins; +} + Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &margins) { return QMargins(-margins.left(), -margins.top(), -margins.right(), -margins.bottom()); diff --git a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp index ec83740196..d49e0efe43 100644 --- a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp +++ b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp @@ -123,6 +123,13 @@ void tst_QMargins::operators() QCOMPARE(a, halved); QCOMPARE(m1 + (-m1), QMargins()); + + QMargins m3 = QMargins(10, 11, 12, 13); + QCOMPARE(m3 + 1, QMargins(11, 12, 13, 14)); + QCOMPARE(1 + m3, QMargins(11, 12, 13, 14)); + QCOMPARE(m3 - 1, QMargins(9, 10, 11, 12)); + QCOMPARE(+m3, QMargins(10, 11, 12, 13)); + QCOMPARE(-m3, QMargins(-10, -11, -12, -13)); } // Testing QDataStream operators From c7aa3a69253c82b8ae814c88ebbdfad7e48d0b2d Mon Sep 17 00:00:00 2001 From: John Layt Date: Sat, 15 Feb 2014 16:07:52 +0100 Subject: [PATCH 037/124] QRect - Add missing QMargins subtraction operator [ChangeLog][QtCore][QRect] Added QMargins subtraction operator. Change-Id: I64d449e2bae81a34df2cd019cff3fb186f8aaaae Reviewed-by: Lars Knoll Reviewed-by: Friedemann Kleint --- src/corelib/tools/qrect.cpp | 9 +++++++++ src/corelib/tools/qrect.h | 6 ++++++ tests/auto/corelib/tools/qrect/tst_qrect.cpp | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index e67b74ea6c..e3ecdbb2ca 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -1181,6 +1181,15 @@ bool QRect::intersects(const QRect &r) const \since 5.1 */ +/*! + \fn QRect operator-(const QRect &lhs, const QMargins &rhs) + \relates QRect + + Returns the \a lhs rectangle shrunken by the \a rhs margins. + + \since 5.3 +*/ + /*! \fn QRect QRect::marginsAdded(const QMargins &margins) const diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index 52f1a79362..5f59bde269 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -463,6 +463,12 @@ Q_DECL_CONSTEXPR inline QRect operator+(const QMargins &margins, const QRect &re QPoint(rectangle.right() + margins.right(), rectangle.bottom() + margins.bottom())); } +Q_DECL_CONSTEXPR inline QRect operator-(const QRect &lhs, const QMargins &rhs) +{ + return QRect(QPoint(lhs.left() + rhs.left(), lhs.top() + rhs.top()), + QPoint(lhs.right() - rhs.right(), lhs.bottom() - rhs.bottom())); +} + Q_DECL_CONSTEXPR inline QRect QRect::marginsAdded(const QMargins &margins) const { return QRect(QPoint(x1 - margins.left(), y1 - margins.top()), diff --git a/tests/auto/corelib/tools/qrect/tst_qrect.cpp b/tests/auto/corelib/tools/qrect/tst_qrect.cpp index 1b11673bd1..c5e3aa58e0 100644 --- a/tests/auto/corelib/tools/qrect/tst_qrect.cpp +++ b/tests/auto/corelib/tools/qrect/tst_qrect.cpp @@ -3496,6 +3496,10 @@ void tst_QRect::margins() QCOMPARE(added, margins + rectangle); QCOMPARE(added, rectangle.marginsAdded(margins)); + const QRect subtracted = rectangle - margins; + QCOMPARE(subtracted, QRect(QPoint(12, 13), QSize(44, 42))); + QCOMPARE(subtracted, rectangle.marginsRemoved(margins)); + QRect a = rectangle; a += margins; QCOMPARE(added, a); From 3aae3e81ef55b4131eff0520d67f2594ee9e507c Mon Sep 17 00:00:00 2001 From: John Layt Date: Fri, 7 Feb 2014 11:47:24 +0100 Subject: [PATCH 038/124] QMarginsF - Add new QMarginsF class Add a new QMarginsF class to complement QMargins in the style of QSize/QSizeF and QRect/QRectF. [ChangeLog][QtCore] Added class QMarginsF to support handling margins with floating-point values. Change-Id: Iaaa95ec85f5d126d9d864fc4b607241a8c8a8f3a Reviewed-by: Lars Knoll Reviewed-by: Friedemann Kleint --- src/corelib/tools/qmargins.cpp | 332 ++++++++++++++++++ src/corelib/tools/qmargins.h | 211 +++++++++++ src/corelib/tools/qrect.cpp | 65 ++++ src/corelib/tools/qrect.h | 47 +++ .../corelib/tools/qmargins/tst_qmargins.cpp | 101 ++++++ tests/auto/corelib/tools/qrect/tst_qrect.cpp | 25 ++ 6 files changed, 781 insertions(+) diff --git a/src/corelib/tools/qmargins.cpp b/src/corelib/tools/qmargins.cpp index 7d8a167a88..088f0dc083 100644 --- a/src/corelib/tools/qmargins.cpp +++ b/src/corelib/tools/qmargins.cpp @@ -426,4 +426,336 @@ QDebug operator<<(QDebug dbg, const QMargins &m) { } #endif +/*! + \class QMarginsF + \inmodule QtCore + \ingroup painting + \since 5.3 + + \brief The QMarginsF class defines the four margins of a rectangle. + + QMarginsF defines a set of four margins; left, top, right and bottom, + that describe the size of the borders surrounding a rectangle. + + The isNull() function returns \c true only if all margins are set to zero. + + QMarginsF objects can be streamed as well as compared. +*/ + + +/***************************************************************************** + QMarginsF member functions + *****************************************************************************/ + +/*! + \fn QMarginsF::QMarginsF() + + Constructs a margins object with all margins set to 0. + + \sa isNull() +*/ + +/*! + \fn QMarginsF::QMarginsF(qreal left, qreal top, qreal right, qreal bottom) + + Constructs margins with the given \a left, \a top, \a right, \a bottom + + \sa setLeft(), setRight(), setTop(), setBottom() +*/ + +/*! + \fn QMarginsF::QMarginsF(const QMargins &margins) + + Constructs margins copied from the given \a margins +*/ + +/*! + \fn bool QMarginsF::isNull() const + + Returns \c true if all margins are is 0; otherwise returns + false. +*/ + + +/*! + \fn qreal QMarginsF::left() const + + Returns the left margin. + + \sa setLeft() +*/ + +/*! + \fn qreal QMarginsF::top() const + + Returns the top margin. + + \sa setTop() +*/ + +/*! + \fn qreal QMarginsF::right() const + + Returns the right margin. +*/ + +/*! + \fn qreal QMarginsF::bottom() const + + Returns the bottom margin. +*/ + + +/*! + \fn void QMarginsF::setLeft(qreal left) + + Sets the left margin to \a left. +*/ + +/*! + \fn void QMarginsF::setTop(qreal Top) + + Sets the Top margin to \a Top. +*/ + +/*! + \fn void QMarginsF::setRight(qreal right) + + Sets the right margin to \a right. +*/ + +/*! + \fn void QMarginsF::setBottom(qreal bottom) + + Sets the bottom margin to \a bottom. +*/ + +/*! + \fn bool operator==(const QMarginsF &lhs, const QMarginsF &rhs) + \relates QMarginsF + + Returns \c true if \a lhs and \a rhs are equal; otherwise returns \c false. +*/ + +/*! + \fn bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs) + \relates QMarginsF + + Returns \c true if \a lhs and \a rhs are different; otherwise returns \c false. +*/ + +/*! + \fn const QMarginsF operator+(const QMarginsF &lhs, const QMarginsF &rhs) + \relates QMarginsF + + Returns a QMarginsF object that is the sum of the given margins, \a lhs + and \a rhs; each component is added separately. + + \sa QMarginsF::operator+=(), QMarginsF::operator-=() +*/ + +/*! + \fn const QMarginsF operator-(const QMarginsF &lhs, const QMarginsF &rhs) + \relates QMarginsF + + Returns a QMarginsF object that is formed by subtracting \a rhs from + \a lhs; each component is subtracted separately. + + \sa QMarginsF::operator+=(), QMarginsF::operator-=() +*/ + +/*! + \fn const QMarginsF operator+(const QMarginsF &lhs, qreal rhs) + \relates QMarginsF + + Returns a QMarginsF object that is formed by adding \a rhs to + \a lhs. + + \sa QMarginsF::operator+=(), QMarginsF::operator-=() +*/ + +/*! + \fn const QMarginsF operator+(qreal lhs, const QMarginsF &rhs) + \relates QMarginsF + + Returns a QMarginsF object that is formed by adding \a lhs to + \a rhs. + + \sa QMarginsF::operator+=(), QMarginsF::operator-=() +*/ + +/*! + \fn const QMarginsF operator-(const QMarginsF &lhs, qreal rhs) + \relates QMarginsF + + Returns a QMarginsF object that is formed by subtracting \a rhs from + \a lhs. + + \sa QMarginsF::operator+=(), QMarginsF::operator-=() +*/ + +/*! + \fn const QMarginsF operator*(const QMarginsF &lhs, qreal rhs) + \relates QMarginsF + \overload + + Returns a QMarginsF object that is formed by multiplying each component + of the given \a lhs margins by \a rhs factor. + + \sa QMarginsF::operator*=(), QMarginsF::operator/=() +*/ + +/*! + \fn const QMarginsF operator*(qreal lhs, const QMarginsF &rhs) + \relates QMarginsF + \overload + + Returns a QMarginsF object that is formed by multiplying each component + of the given \a lhs margins by \a rhs factor. + + \sa QMarginsF::operator*=(), QMarginsF::operator/=() +*/ + +/*! + \fn const QMarginsF operator/(const QMarginsF &lhs, qreal rhs) + \relates QMarginsF + \overload + + Returns a QMarginsF object that is formed by dividing the components of + the given \a lhs margins by the given \a rhs divisor. + + \sa QMarginsF::operator*=(), QMarginsF::operator/=() +*/ + +/*! + \fn QMarginsF operator+(const QMarginsF &margins) + \relates QMarginsF + + Returns a QMargin object that is formed from all components of \a margins. +*/ + +/*! + \fn QMarginsF operator-(const QMarginsF &margins) + \relates QMarginsF + + Returns a QMargin object that is formed by negating all components of \a margins. +*/ + +/*! + \fn QMarginsF &QMarginsF::operator+=(const QMarginsF &margins) + + Add each component of \a margins to the respective component of this object + and returns a reference to it. + + \sa operator-=() +*/ + +/*! + \fn QMarginsF &QMarginsF::operator-=(const QMarginsF &margins) + + Subtract each component of \a margins from the respective component of this object + and returns a reference to it. + + \sa operator+=() +*/ + +/*! + \fn QMarginsF &QMarginsF::operator+=(qreal addend) + \overload + + Adds the \a addend to each component of this object + and returns a reference to it. + + \sa operator-=() +*/ + +/*! + \fn QMarginsF &QMarginsF::operator-=(qreal subtrahend) + \overload + + Subtracts the \a subtrahend from each component of this object + and returns a reference to it. + + \sa operator+=() +*/ + +/*! + \fn QMarginsF &QMarginsF::operator*=(qreal factor) + + Multiplies each component of this object by \a factor + and returns a reference to it. + + \sa operator/=() +*/ + +/*! + \fn QMarginsF &QMarginsF::operator/=(qreal divisor) + + Divides each component of this object by \a divisor + and returns a reference to it. + + \sa operator*=() +*/ + +/*! + \fn QMargins QMarginsF::toMargins() const + + Returns an integer based copy of this margins object. + + Note that the components in the returned margins will be rounded to + the nearest integer. + + \sa QMarginsF() +*/ + +/***************************************************************************** + QMarginsF stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QMarginsF &m) + \relates QMarginsF + + Writes margin \a m to the given \a stream and returns a + reference to the stream. + + \sa {Serializing Qt Data Types} +*/ + +QDataStream &operator<<(QDataStream &s, const QMarginsF &m) +{ + s << double(m.left()) << double(m.top()) << double(m.right()) << double(m.bottom()); + return s; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QMarginsF &m) + \relates QMarginsF + + Reads a margin from the given \a stream into margin \a m + and returns a reference to the stream. + + \sa {Serializing Qt Data Types} +*/ + +QDataStream &operator>>(QDataStream &s, QMarginsF &m) +{ + double left, top, right, bottom; + s >> left; + s >> top; + s >> right; + s >> bottom; + m = QMarginsF(qreal(left), qreal(top), qreal(right), qreal(bottom)); + return s; +} +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QMarginsF &m) { + dbg.nospace() << "QMarginsF(" << m.left() << ", " + << m.top() << ", " << m.right() << ", " << m.bottom() << ')'; + return dbg.space(); +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/tools/qmargins.h b/src/corelib/tools/qmargins.h index 55355ac859..d96ccaccae 100644 --- a/src/corelib/tools/qmargins.h +++ b/src/corelib/tools/qmargins.h @@ -46,6 +46,9 @@ QT_BEGIN_NAMESPACE +/***************************************************************************** + QMargins class + *****************************************************************************/ class QMargins { @@ -277,6 +280,214 @@ Q_DECL_CONSTEXPR inline QMargins operator-(const QMargins &margins) Q_CORE_EXPORT QDebug operator<<(QDebug, const QMargins &); #endif +/***************************************************************************** + QMarginsF class + *****************************************************************************/ + +class QMarginsF +{ +public: + Q_DECL_CONSTEXPR QMarginsF(); + Q_DECL_CONSTEXPR QMarginsF(qreal left, qreal top, qreal right, qreal bottom); + Q_DECL_CONSTEXPR QMarginsF(const QMargins &margins); + + Q_DECL_CONSTEXPR bool isNull() const; + + Q_DECL_CONSTEXPR qreal left() const; + Q_DECL_CONSTEXPR qreal top() const; + Q_DECL_CONSTEXPR qreal right() const; + Q_DECL_CONSTEXPR qreal bottom() const; + + void setLeft(qreal left); + void setTop(qreal top); + void setRight(qreal right); + void setBottom(qreal bottom); + + QMarginsF &operator+=(const QMarginsF &margins); + QMarginsF &operator-=(const QMarginsF &margins); + QMarginsF &operator+=(qreal addend); + QMarginsF &operator-=(qreal subtrahend); + QMarginsF &operator*=(qreal factor); + QMarginsF &operator/=(qreal divisor); + + Q_DECL_CONSTEXPR inline QMargins toMargins() const; + +private: + qreal m_left; + qreal m_top; + qreal m_right; + qreal m_bottom; +}; + +Q_DECLARE_TYPEINFO(QMarginsF, Q_MOVABLE_TYPE); + +/***************************************************************************** + QMarginsF stream functions + *****************************************************************************/ + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QMarginsF &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QMarginsF &); +#endif + +/***************************************************************************** + QMarginsF inline functions + *****************************************************************************/ + +Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF() : m_left(0), m_top(0), m_right(0), m_bottom(0) {} + +Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF(qreal aleft, qreal atop, qreal aright, qreal abottom) + : m_left(aleft), m_top(atop), m_right(aright), m_bottom(abottom) {} + +Q_DECL_CONSTEXPR inline QMarginsF::QMarginsF(const QMargins &margins) + : m_left(margins.left()), m_top(margins.top()), m_right(margins.right()), m_bottom(margins.bottom()) {} + +Q_DECL_CONSTEXPR inline bool QMarginsF::isNull() const +{ return qFuzzyIsNull(m_left) && qFuzzyIsNull(m_top) && qFuzzyIsNull(m_right) && qFuzzyIsNull(m_bottom); } + +Q_DECL_CONSTEXPR inline qreal QMarginsF::left() const +{ return m_left; } + +Q_DECL_CONSTEXPR inline qreal QMarginsF::top() const +{ return m_top; } + +Q_DECL_CONSTEXPR inline qreal QMarginsF::right() const +{ return m_right; } + +Q_DECL_CONSTEXPR inline qreal QMarginsF::bottom() const +{ return m_bottom; } + + +inline void QMarginsF::setLeft(qreal aleft) +{ m_left = aleft; } + +inline void QMarginsF::setTop(qreal atop) +{ m_top = atop; } + +inline void QMarginsF::setRight(qreal aright) +{ m_right = aright; } + +inline void QMarginsF::setBottom(qreal abottom) +{ m_bottom = abottom; } + +Q_DECL_CONSTEXPR inline bool operator==(const QMarginsF &lhs, const QMarginsF &rhs) +{ + return qFuzzyCompare(lhs.left(), rhs.left()) + && qFuzzyCompare(lhs.top(), rhs.top()) + && qFuzzyCompare(lhs.right(), rhs.right()) + && qFuzzyCompare(lhs.bottom(), rhs.bottom()); +} + +Q_DECL_CONSTEXPR inline bool operator!=(const QMarginsF &lhs, const QMarginsF &rhs) +{ + return !operator==(lhs, rhs); +} + +Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &lhs, const QMarginsF &rhs) +{ + return QMarginsF(lhs.left() + rhs.left(), lhs.top() + rhs.top(), + lhs.right() + rhs.right(), lhs.bottom() + rhs.bottom()); +} + +Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, const QMarginsF &rhs) +{ + return QMarginsF(lhs.left() - rhs.left(), lhs.top() - rhs.top(), + lhs.right() - rhs.right(), lhs.bottom() - rhs.bottom()); +} + +Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &lhs, qreal rhs) +{ + return QMarginsF(lhs.left() + rhs, lhs.top() + rhs, + lhs.right() + rhs, lhs.bottom() + rhs); +} + +Q_DECL_CONSTEXPR inline QMarginsF operator+(qreal lhs, const QMarginsF &rhs) +{ + return QMarginsF(rhs.left() + lhs, rhs.top() + lhs, + rhs.right() + lhs, rhs.bottom() + lhs); +} + +Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &lhs, qreal rhs) +{ + return QMarginsF(lhs.left() - rhs, lhs.top() - rhs, + lhs.right() - rhs, lhs.bottom() - rhs); +} + +Q_DECL_CONSTEXPR inline QMarginsF operator*(const QMarginsF &lhs, qreal rhs) +{ + return QMarginsF(lhs.left() * rhs, lhs.top() * rhs, + lhs.right() * rhs, lhs.bottom() * rhs); +} + +Q_DECL_CONSTEXPR inline QMarginsF operator*(qreal lhs, const QMarginsF &rhs) +{ + return QMarginsF(rhs.left() * lhs, rhs.top() * lhs, + rhs.right() * lhs, rhs.bottom() * lhs); +} + +Q_DECL_CONSTEXPR inline QMarginsF operator/(const QMarginsF &lhs, qreal divisor) +{ + return QMarginsF(lhs.left() / divisor, lhs.top() / divisor, + lhs.right() / divisor, lhs.bottom() / divisor); +} + +inline QMarginsF &QMarginsF::operator+=(const QMarginsF &margins) +{ + return *this = *this + margins; +} + +inline QMarginsF &QMarginsF::operator-=(const QMarginsF &margins) +{ + return *this = *this - margins; +} + +inline QMarginsF &QMarginsF::operator+=(qreal addend) +{ + m_left += addend; + m_top += addend; + m_right += addend; + m_bottom += addend; + return *this; +} + +inline QMarginsF &QMarginsF::operator-=(qreal subtrahend) +{ + m_left -= subtrahend; + m_top -= subtrahend; + m_right -= subtrahend; + m_bottom -= subtrahend; + return *this; +} + +inline QMarginsF &QMarginsF::operator*=(qreal factor) +{ + return *this = *this * factor; +} + +inline QMarginsF &QMarginsF::operator/=(qreal divisor) +{ + return *this = *this / divisor; +} + +Q_DECL_CONSTEXPR inline QMarginsF operator+(const QMarginsF &margins) +{ + return margins; +} + +Q_DECL_CONSTEXPR inline QMarginsF operator-(const QMarginsF &margins) +{ + return QMarginsF(-margins.left(), -margins.top(), -margins.right(), -margins.bottom()); +} + +Q_DECL_CONSTEXPR inline QMargins QMarginsF::toMargins() const +{ + return QMargins(qRound(m_left), qRound(m_top), qRound(m_right), qRound(m_bottom)); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug, const QMarginsF &); +#endif + QT_END_NAMESPACE #endif // QMARGINS_H diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index e3ecdbb2ca..33e8dd23fc 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -2379,6 +2379,71 @@ QRect QRectF::toAlignedRect() const returns \c false. */ +/*! + \fn QRectF operator+(const QRectF &lhs, const QMarginsF &rhs) + \relates QRectF + \since 5.3 + + Returns the \a lhs rectangle grown by the \a rhs margins. +*/ + +/*! + \fn QRectF operator-(const QRectF &lhs, const QMarginsF &rhs) + \relates QRectF + \since 5.3 + + Returns the \a lhs rectangle grown by the \a rhs margins. +*/ + +/*! + \fn QRectF operator+(const QMarginsF &lhs, const QRectF &rhs) + \relates QRectF + \overload + \since 5.3 + + Returns the \a lhs rectangle grown by the \a rhs margins. +*/ + +/*! + \fn QRectF QRectF::marginsAdded(const QMarginsF &margins) const + \relates QRectF + \since 5.3 + + Returns a rectangle grown by the \a margins. + + \sa operator+=(), marginsRemoved(), operator-=() +*/ + +/*! + \fn QRectF QRectF::marginsRemoved(const QMarginsF &margins) const + \relates QRectF + \since 5.3 + + Removes the \a margins from the rectangle, shrinking it. + + \sa marginsAdded(), operator+=(), operator-=() +*/ + +/*! + \fn QRectF QRectF::operator+=(const QMarginsF &margins) + \relates QRectF + \since 5.3 + + Adds the \a margins to the rectangle, growing it. + + \sa marginsAdded(), marginsRemoved(), operator-=() +*/ + +/*! + \fn QRectF QRectF::operator-=(const QMarginsF &margins) + \relates QRectF + \since 5.3 + + Returns a rectangle shrunk by the \a margins. + + \sa marginsRemoved(), operator+=(), marginsAdded() +*/ + /***************************************************************************** QRectF stream functions *****************************************************************************/ diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index 5f59bde269..2bb74e8221 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -584,6 +584,11 @@ public: inline QRectF intersected(const QRectF &other) const; bool intersects(const QRectF &r) const; + Q_DECL_CONSTEXPR inline QRectF marginsAdded(const QMarginsF &margins) const; + Q_DECL_CONSTEXPR inline QRectF marginsRemoved(const QMarginsF &margins) const; + inline QRectF &operator+=(const QMarginsF &margins); + inline QRectF &operator-=(const QMarginsF &margins); + #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED QRectF unite(const QRectF &r) const { return united(r); } QT_DEPRECATED QRectF intersect(const QRectF &r) const { return intersected(r); } @@ -825,6 +830,48 @@ Q_DECL_CONSTEXPR inline QRect QRectF::toRect() const return QRect(qRound(xp), qRound(yp), qRound(w), qRound(h)); } +Q_DECL_CONSTEXPR inline QRectF operator+(const QRectF &lhs, const QMarginsF &rhs) +{ + return QRectF(QPointF(lhs.left() - rhs.left(), lhs.top() - rhs.top()), + QSizeF(lhs.width() + rhs.left() + rhs.right(), lhs.height() + rhs.top() + rhs.bottom())); +} + +Q_DECL_CONSTEXPR inline QRectF operator+(const QMarginsF &lhs, const QRectF &rhs) +{ + return QRectF(QPointF(rhs.left() - lhs.left(), rhs.top() - lhs.top()), + QSizeF(rhs.width() + lhs.left() + lhs.right(), rhs.height() + lhs.top() + lhs.bottom())); +} + +Q_DECL_CONSTEXPR inline QRectF operator-(const QRectF &lhs, const QMarginsF &rhs) +{ + return QRectF(QPointF(lhs.left() + rhs.left(), lhs.top() + rhs.top()), + QSizeF(lhs.width() - rhs.left() - rhs.right(), lhs.height() - rhs.top() - rhs.bottom())); +} + +Q_DECL_CONSTEXPR inline QRectF QRectF::marginsAdded(const QMarginsF &margins) const +{ + return QRectF(QPointF(xp - margins.left(), yp - margins.top()), + QSizeF(w + margins.left() + margins.right(), h + margins.top() + margins.bottom())); +} + +Q_DECL_CONSTEXPR inline QRectF QRectF::marginsRemoved(const QMarginsF &margins) const +{ + return QRectF(QPointF(xp + margins.left(), yp + margins.top()), + QSizeF(w - margins.left() - margins.right(), h - margins.top() - margins.bottom())); +} + +inline QRectF &QRectF::operator+=(const QMarginsF &margins) +{ + *this = marginsAdded(margins); + return *this; +} + +inline QRectF &QRectF::operator-=(const QMarginsF &margins) +{ + *this = marginsRemoved(margins); + return *this; +} + #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const QRectF &); #endif diff --git a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp index d49e0efe43..409a82aab2 100644 --- a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp +++ b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp @@ -51,6 +51,10 @@ private slots: void getSetCheck(); void dataStreamCheck(); void operators(); + + void getSetCheckF(); + void dataStreamCheckF(); + void operatorsF(); }; // Testing get/set functions @@ -157,5 +161,102 @@ void tst_QMargins::dataStreamCheck() } } +// Testing get/set functions +void tst_QMargins::getSetCheckF() +{ + QMarginsF margins; + // int QMarginsF::width() + // void QMarginsF::setWidth(int) + margins.setLeft(1.1); + QCOMPARE(1.1, margins.left()); + margins.setTop(2.2); + QCOMPARE(2.2, margins.top()); + margins.setBottom(3.3); + QCOMPARE(3.3, margins.bottom()); + margins.setRight(4.4); + QCOMPARE(4.4, margins.right()); + + margins = QMarginsF(); + QVERIFY(margins.isNull()); + margins.setLeft(5.5); + margins.setRight(5.5); + QVERIFY(!margins.isNull()); + QCOMPARE(margins, QMarginsF(5.5, 0.0, 5.5, 0.0)); +} + +void tst_QMargins::operatorsF() +{ + const QMarginsF m1(12.1, 14.1, 16.1, 18.1); + const QMarginsF m2(2.1, 3.1, 4.1, 5.1); + + const QMarginsF added = m1 + m2; + QCOMPARE(added, QMarginsF(14.2, 17.2, 20.2, 23.2)); + QMarginsF a = m1; + a += m2; + QCOMPARE(a, added); + + const QMarginsF subtracted = m1 - m2; + QCOMPARE(subtracted, QMarginsF(10.0, 11.0, 12.0, 13.0)); + a = m1; + a -= m2; + QCOMPARE(a, subtracted); + + QMarginsF h = m1; + h += 2.1; + QCOMPARE(h, QMarginsF(14.2, 16.2, 18.2, 20.2)); + h -= 2.1; + QCOMPARE(h, m1); + + const QMarginsF doubled = m1 * 2.0; + QCOMPARE(doubled, QMarginsF(24.2, 28.2, 32.2, 36.2)); + QCOMPARE(2.0 * m1, doubled); + QCOMPARE(m1 * 2.0, doubled); + + a = m1; + a *= 2.0; + QCOMPARE(a, doubled); + + const QMarginsF halved = m1 / 2.0; + QCOMPARE(halved, QMarginsF(6.05, 7.05, 8.05, 9.05)); + + a = m1; + a /= 2.0; + QCOMPARE(a, halved); + + QCOMPARE(m1 + (-m1), QMarginsF()); + + QMarginsF m3 = QMarginsF(10.3, 11.4, 12.5, 13.6); + QCOMPARE(m3 + 1.1, QMarginsF(11.4, 12.5, 13.6, 14.7)); + QCOMPARE(1.1 + m3, QMarginsF(11.4, 12.5, 13.6, 14.7)); + QCOMPARE(m3 - 1.1, QMarginsF(9.2, 10.3, 11.4, 12.5)); + QCOMPARE(+m3, QMarginsF(10.3, 11.4, 12.5, 13.6)); + QCOMPARE(-m3, QMarginsF(-10.3, -11.4, -12.5, -13.6)); +} + +// Testing QDataStream operators +void tst_QMargins::dataStreamCheckF() +{ + QByteArray buffer; + + // stream out + { + QMarginsF marginsOut(1.1, 2.2, 3.3, 4.4); + QDataStream streamOut(&buffer, QIODevice::WriteOnly); + streamOut << marginsOut; + } + + // stream in & compare + { + QMarginsF marginsIn; + QDataStream streamIn(&buffer, QIODevice::ReadOnly); + streamIn >> marginsIn; + + QCOMPARE(marginsIn.left(), 1.1); + QCOMPARE(marginsIn.top(), 2.2); + QCOMPARE(marginsIn.right(), 3.3); + QCOMPARE(marginsIn.bottom(), 4.4); + } +} + QTEST_APPLESS_MAIN(tst_QMargins) #include "tst_qmargins.moc" diff --git a/tests/auto/corelib/tools/qrect/tst_qrect.cpp b/tests/auto/corelib/tools/qrect/tst_qrect.cpp index c5e3aa58e0..81222552ca 100644 --- a/tests/auto/corelib/tools/qrect/tst_qrect.cpp +++ b/tests/auto/corelib/tools/qrect/tst_qrect.cpp @@ -135,6 +135,7 @@ private slots: void newMoveBottomRight_data(); void newMoveBottomRight(); void margins(); + void marginsf(); void translate_data(); void translate(); @@ -3510,6 +3511,30 @@ void tst_QRect::margins() QCOMPARE(a, rectangle.marginsRemoved(margins)); } +void tst_QRect::marginsf() +{ + const QRectF rectangle = QRectF(QPointF(10.5, 10.5), QSizeF(50.5 ,150.5)); + const QMarginsF margins = QMarginsF(2.5, 3.5, 4.5, 5.5); + + const QRectF added = rectangle + margins; + QCOMPARE(added, QRectF(QPointF(8.0, 7.0), QSizeF(57.5, 159.5))); + QCOMPARE(added, margins + rectangle); + QCOMPARE(added, rectangle.marginsAdded(margins)); + + const QRectF subtracted = rectangle - margins; + QCOMPARE(subtracted, QRectF(QPointF(13.0, 14.0), QSizeF(43.5, 141.5))); + QCOMPARE(subtracted, rectangle.marginsRemoved(margins)); + + QRectF a = rectangle; + a += margins; + QCOMPARE(added, a); + + a = rectangle; + a -= margins; + QCOMPARE(a, QRectF(QPoint(13.0, 14.0), QSizeF(43.5, 141.5))); + QCOMPARE(a, rectangle.marginsRemoved(margins)); +} + void tst_QRect::translate_data() { QTest::addColumn("r"); From ae4e44644adfaf7ddf955c2fefd2fff7470ec0c0 Mon Sep 17 00:00:00 2001 From: Jorgen Lind Date: Thu, 20 Feb 2014 14:21:10 +0100 Subject: [PATCH 039/124] Fix rounding error when creating QT_FT_Vector This fixes a problem that QScanConverter::mergeLine didn't recognize lins as being the same (when they where), causing aliasing effects Task-number: QTBUG-36354 Change-Id: I29d92ddb4e867025541bdc6b294cfaca55c0d3e1 Reviewed-by: Gunnar Sletta --- src/gui/painting/qoutlinemapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index 8b47dae5ff..6a38ed6c70 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE -#define qreal_to_fixed_26_6(f) (int(f * 64)) +#define qreal_to_fixed_26_6(f) (qRound(f * 64)) From f41d5ec626d23423bc7d0cd66ba4566a3d00872d Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 20 Feb 2014 14:26:54 +0100 Subject: [PATCH 040/124] QPainterPathStroker: make QPen constructor explicit A QPainterPathStroker is not an equivalent representation of a QPen, so the constructor that takes a QPen should be explicit. Arguably, the named constructor idiom would be even better here: static QPainterPathStroker QPainterPathStroker::fromPen(const QPen &pen); But QPainterPathStroker is non-copyable. Change-Id: I3148dc0ee336026781d8bc1baf21c113c7b41ce8 Reviewed-by: Gunnar Sletta --- src/gui/painting/qpainterpath.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index c922867eb9..db65e14af9 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -244,7 +244,7 @@ class Q_GUI_EXPORT QPainterPathStroker Q_DECLARE_PRIVATE(QPainterPathStroker) public: QPainterPathStroker(); - QPainterPathStroker(const QPen &pen); + explicit QPainterPathStroker(const QPen &pen); ~QPainterPathStroker(); void setWidth(qreal width); From d9ce5c35df99adefdf18c6e1e50afd7ab50eb441 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 20 Feb 2014 17:36:25 +0100 Subject: [PATCH 041/124] QSslCipher: make QString constructor explicit A QSslCipher is not an equivalent representation of a QString, so the constructor that takes a QString should be explicit. Change-Id: I4c1329d1eebf91b212616eb5200450c0861d900f Reviewed-by: Lars Knoll --- src/network/ssl/qsslcipher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ssl/qsslcipher.h b/src/network/ssl/qsslcipher.h index 4cebffa7ae..f6ca033ede 100644 --- a/src/network/ssl/qsslcipher.h +++ b/src/network/ssl/qsslcipher.h @@ -57,7 +57,7 @@ class Q_NETWORK_EXPORT QSslCipher { public: QSslCipher(); - QSslCipher(const QString &name); + explicit QSslCipher(const QString &name); QSslCipher(const QString &name, QSsl::SslProtocol protocol); QSslCipher(const QSslCipher &other); ~QSslCipher(); From 208acff3fc53a33e1f0a38dfd029dca411537db1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 20 Feb 2014 23:22:43 +0100 Subject: [PATCH 042/124] QLibraryInfo: mark build() function as nothrow Change-Id: Ie95fa52e4e00fd0747d3554c9f2a4d8076faaaf6 Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- src/corelib/global/qlibraryinfo.cpp | 2 +- src/corelib/global/qlibraryinfo.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index ed1715ddb5..93d5407184 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -287,7 +287,7 @@ QLibraryInfo::buildDate() \since 5.3 */ -const char *QLibraryInfo::build() +const char *QLibraryInfo::build() Q_DECL_NOTHROW { static const char data[] = "Qt " QT_VERSION_STR " (" __DATE__ "), " COMPILER_STRING ", " diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 2a8a3b84b9..0b573c2e6a 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -59,7 +59,7 @@ public: static QDate buildDate(); #endif //QT_NO_DATESTRING - static const char * build(); + static const char * build() Q_DECL_NOTHROW; static bool isDebugBuild(); From a03a69efb9ed89cd4a90878eda203df62a1c95d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 10 Feb 2014 01:56:40 +0100 Subject: [PATCH 043/124] Android: Do not enable text selection in QTextEdits by default. Text selection does not work correctly and is currently causing selected text to be randomly copied, pasted or deleted. Task-id: QTBUG-34616 Change-Id: I98678b7575034325dd8a4fa181ee4cb182783a3b Reviewed-by: Paul Olav Tvete --- src/widgets/widgets/qwidgettextcontrol.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 98f85e681b..03a65aa8e5 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -115,7 +115,11 @@ static QTextLine currentTextLine(const QTextCursor &cursor) QWidgetTextControlPrivate::QWidgetTextControlPrivate() : doc(0), cursorOn(false), cursorIsFocusIndicator(false), +#ifndef Q_OS_ANDROID interactionFlags(Qt::TextEditorInteraction), +#else + interactionFlags(Qt::TextEditable), +#endif dragEnabled(true), #ifndef QT_NO_DRAGANDDROP mousePressed(false), mightStartDrag(false), From de5ae6917c819ff23f7d9c5742b50b15e0824877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 17 Feb 2014 15:48:31 +0100 Subject: [PATCH 044/124] Android: Enable text selection only when ImhNoPredictiveText is set. Mouse selection does not work well with Android and text will be randomly copied, pasted or deleted. This behavior is especially bad when predictive text is enabled. Task-number: QTBUG-34616 Change-Id: I732ad7db52169bfb5735c237cf24597a3d6d64ba Reviewed-by: Paul Olav Tvete --- src/widgets/widgets/qlineedit.cpp | 12 ++++++++++-- src/widgets/widgets/qlineedit_p.cpp | 7 ++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 1833dce40b..ba4dbcc878 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1493,6 +1493,9 @@ void QLineEdit::mousePressEvent(QMouseEvent* e) return; } bool mark = e->modifiers() & Qt::ShiftModifier; +#ifdef Q_OS_ANDROID + mark = mark && (d->imHints & Qt::ImhNoPredictiveText); +#endif // Q_OS_ANDROID int cursor = d->xToPos(e->pos().x()); #ifndef QT_NO_DRAGANDDROP if (!mark && d->dragEnabled && d->control->echoMode() == Normal && @@ -1520,14 +1523,19 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) } else #endif { - if (d->control->composeMode()) { +#ifndef Q_OS_ANDROID + const bool select = true; +#else + const bool select = (d->imHints & Qt::ImhNoPredictiveText); +#endif + if (d->control->composeMode() && select) { int startPos = d->xToPos(d->mousePressPos.x()); int currentPos = d->xToPos(e->pos().x()); if (startPos != currentPos) d->control->setSelection(startPos, currentPos - startPos); } else { - d->control->moveCursor(d->xToPos(e->pos().x()), true); + d->control->moveCursor(d->xToPos(e->pos().x()), select); } } } diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 891839ed56..9ff77c87de 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -95,7 +95,12 @@ void QLineEditPrivate::_q_completionHighlighted(QString newText) QString text = control->text(); q->setText(text.left(c) + newText.mid(c)); control->moveCursor(control->end(), false); - control->moveCursor(c, true); +#ifndef Q_OS_ANDROID + const bool mark = true; +#else + const bool mark = (imHints & Qt::ImhNoPredictiveText); +#endif + control->moveCursor(c, mark); } } From 1c63909ad8caee11ba0ec4af998d981bd50d3ee1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 7 Feb 2013 13:56:57 -0800 Subject: [PATCH 045/124] Make sure all containers compile in strict-iterator mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unit-test this by making the QList, QVector, QHash and QMap unit tests be duplicated under strict-iterator mode. There's no test for QLinkedList. The tst_Collections test does not compile under strict-iterator mode. It generated over 15000 errors when I tried. The strict iterators required a small change: the difference_type typedef needs to match the operators that get distances (operator-(iterator)) and move the iterator around (+, -, +=, -=, etc.). Task-number: QTBUG-29608 Change-Id: I834873934c51d0f139a994cd395818da4ec997e2 Reviewed-by: JÄ™drzej Nowacki Reviewed-by: Jason McDonald --- src/corelib/tools/qarraydata.h | 4 ++-- src/corelib/tools/qarraydataops.h | 2 +- tests/auto/corelib/tools/qarraydata/qarraydata.pro | 4 ++-- tests/auto/corelib/tools/qarraydata/simplevector.h | 10 +++++----- tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp | 2 +- .../qarraydata_strictiterators.pro | 3 +++ tests/auto/corelib/tools/qhash/qhash.pro | 2 +- .../qhash_strictiterators/qhash_strictiterators.pro | 3 +++ tests/auto/corelib/tools/qlist/qlist.pro | 2 +- .../qlist_strictiterators/qlist_strictiterators.pro | 3 +++ tests/auto/corelib/tools/qmap/qmap.pro | 2 +- tests/auto/corelib/tools/qmap/tst_qmap.cpp | 2 -- .../qmap_strictiterators/qmap_strictiterators.pro | 3 +++ tests/auto/corelib/tools/qvector/qvector.pro | 2 +- .../qvector_strictiterators.pro | 3 +++ tests/auto/corelib/tools/tools.pro | 7 ++++++- 16 files changed, 36 insertions(+), 18 deletions(-) create mode 100644 tests/auto/corelib/tools/qarraydata_strictiterators/qarraydata_strictiterators.pro create mode 100644 tests/auto/corelib/tools/qhash_strictiterators/qhash_strictiterators.pro create mode 100644 tests/auto/corelib/tools/qlist_strictiterators/qlist_strictiterators.pro create mode 100644 tests/auto/corelib/tools/qmap_strictiterators/qmap_strictiterators.pro create mode 100644 tests/auto/corelib/tools/qvector_strictiterators/qvector_strictiterators.pro diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index 7df4694bcd..ffb2b8765e 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -135,7 +135,7 @@ struct QTypedArrayData public: T *i; typedef std::random_access_iterator_tag iterator_category; - typedef qptrdiff difference_type; + typedef int difference_type; typedef T value_type; typedef T *pointer; typedef T &reference; @@ -169,7 +169,7 @@ struct QTypedArrayData public: const T *i; typedef std::random_access_iterator_tag iterator_category; - typedef qptrdiff difference_type; + typedef int difference_type; typedef T value_type; typedef const T *pointer; typedef const T &reference; diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index c8a0825480..b94c6b50ea 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -122,7 +122,7 @@ struct QPodArrayOps Q_ASSERT(b >= this->begin() && b < this->end()); Q_ASSERT(e > this->begin() && e < this->end()); - ::memmove(b, e, (this->end() - e) * sizeof(T)); + ::memmove(b, e, (static_cast(this->end()) - e) * sizeof(T)); this->size -= (e - b); } }; diff --git a/tests/auto/corelib/tools/qarraydata/qarraydata.pro b/tests/auto/corelib/tools/qarraydata/qarraydata.pro index d13cc86cf5..d5fe08c009 100644 --- a/tests/auto/corelib/tools/qarraydata/qarraydata.pro +++ b/tests/auto/corelib/tools/qarraydata/qarraydata.pro @@ -1,6 +1,6 @@ TARGET = tst_qarraydata -SOURCES += tst_qarraydata.cpp -HEADERS += simplevector.h +SOURCES += $$PWD/tst_qarraydata.cpp +HEADERS += $$PWD/simplevector.h QT = core testlib CONFIG += testcase parallel_test DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h index ea3892ec5c..40917c0172 100644 --- a/tests/auto/corelib/tools/qarraydata/simplevector.h +++ b/tests/auto/corelib/tools/qarraydata/simplevector.h @@ -269,9 +269,9 @@ public: if (first == last) return; - T *const begin = d->begin(); - T *const where = begin + position; - const T *const end = begin + d->size; + const iterator begin = d->begin(); + const iterator where = begin + position; + const iterator end = begin + d->size; if (d.needsDetach() || capacity() - size() < size_t(last - first)) { SimpleVector detached(Data::allocate( @@ -290,8 +290,8 @@ public: if ((first >= where && first < end) || (last > where && last <= end)) { // Copy overlapping data first and only then shuffle it into place - T *start = d->begin() + position; - T *middle = d->end(); + iterator start = d->begin() + position; + iterator middle = d->end(); d->copyAppend(first, last); std::rotate(start, middle, d->end()); diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index f9ce7425f6..60b807a7bc 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -1559,7 +1559,7 @@ void tst_QArrayData::literals() #endif QVERIFY(v.isSharable()); - QCOMPARE((void*)(v.constBegin() + v.size()), (void*)v.constEnd()); + QCOMPARE((void*)(const char*)(v.constBegin() + v.size()), (void*)(const char*)v.constEnd()); for (int i = 0; i < 10; ++i) QCOMPARE(const_(v)[i], char('A' + i)); diff --git a/tests/auto/corelib/tools/qarraydata_strictiterators/qarraydata_strictiterators.pro b/tests/auto/corelib/tools/qarraydata_strictiterators/qarraydata_strictiterators.pro new file mode 100644 index 0000000000..b01fbd84d1 --- /dev/null +++ b/tests/auto/corelib/tools/qarraydata_strictiterators/qarraydata_strictiterators.pro @@ -0,0 +1,3 @@ +include(../qarraydata/qarraydata.pro) +TARGET = tst_qarraydata_strictiterators +DEFINES += QT_STRICT_ITERATORS=1 tst_QArrayData=tst_QArrayData_StrictIterators diff --git a/tests/auto/corelib/tools/qhash/qhash.pro b/tests/auto/corelib/tools/qhash/qhash.pro index 630eabdb7c..1ed062ca91 100644 --- a/tests/auto/corelib/tools/qhash/qhash.pro +++ b/tests/auto/corelib/tools/qhash/qhash.pro @@ -1,5 +1,5 @@ CONFIG += testcase parallel_test TARGET = tst_qhash QT = core testlib -SOURCES = tst_qhash.cpp +SOURCES = $$PWD/tst_qhash.cpp DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qhash_strictiterators/qhash_strictiterators.pro b/tests/auto/corelib/tools/qhash_strictiterators/qhash_strictiterators.pro new file mode 100644 index 0000000000..715e9bf0c9 --- /dev/null +++ b/tests/auto/corelib/tools/qhash_strictiterators/qhash_strictiterators.pro @@ -0,0 +1,3 @@ +include(../qhash/qhash.pro) +TARGET = tst_qhash_strictiterators +DEFINES += QT_STRICT_ITERATORS tst_QHash=tst_QHash_StrictIterators diff --git a/tests/auto/corelib/tools/qlist/qlist.pro b/tests/auto/corelib/tools/qlist/qlist.pro index d3f8d83177..43c06e0ee1 100644 --- a/tests/auto/corelib/tools/qlist/qlist.pro +++ b/tests/auto/corelib/tools/qlist/qlist.pro @@ -2,5 +2,5 @@ CONFIG += testcase CONFIG += parallel_test TARGET = tst_qlist QT = core testlib -SOURCES = tst_qlist.cpp +SOURCES = $$PWD/tst_qlist.cpp DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qlist_strictiterators/qlist_strictiterators.pro b/tests/auto/corelib/tools/qlist_strictiterators/qlist_strictiterators.pro new file mode 100644 index 0000000000..e39ad38919 --- /dev/null +++ b/tests/auto/corelib/tools/qlist_strictiterators/qlist_strictiterators.pro @@ -0,0 +1,3 @@ +include(../qlist/qlist.pro) +TARGET = tst_qlist_strictiterators +DEFINES += QT_STRICT_ITERATORS tst_QList=tst_QList_StrictIterators diff --git a/tests/auto/corelib/tools/qmap/qmap.pro b/tests/auto/corelib/tools/qmap/qmap.pro index 5601bc528c..460b6654fb 100644 --- a/tests/auto/corelib/tools/qmap/qmap.pro +++ b/tests/auto/corelib/tools/qmap/qmap.pro @@ -1,5 +1,5 @@ CONFIG += testcase parallel_test TARGET = tst_qmap QT = core testlib -SOURCES = tst_qmap.cpp +SOURCES = $$PWD/tst_qmap.cpp DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp index dea657f842..e812e5a337 100644 --- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp +++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp @@ -39,8 +39,6 @@ ** ****************************************************************************/ -#define QT_STRICT_ITERATORS - #include #include #include diff --git a/tests/auto/corelib/tools/qmap_strictiterators/qmap_strictiterators.pro b/tests/auto/corelib/tools/qmap_strictiterators/qmap_strictiterators.pro new file mode 100644 index 0000000000..6c1f4727c1 --- /dev/null +++ b/tests/auto/corelib/tools/qmap_strictiterators/qmap_strictiterators.pro @@ -0,0 +1,3 @@ +include(../qmap/qmap.pro) +TARGET = tst_qmap_strictiterators +DEFINES += QT_STRICT_ITERATORS tst_QMap=tst_QMap_StrictIterators diff --git a/tests/auto/corelib/tools/qvector/qvector.pro b/tests/auto/corelib/tools/qvector/qvector.pro index 98fd2f2120..22edde3412 100644 --- a/tests/auto/corelib/tools/qvector/qvector.pro +++ b/tests/auto/corelib/tools/qvector/qvector.pro @@ -1,5 +1,5 @@ CONFIG += testcase parallel_test TARGET = tst_qvector QT = core testlib -SOURCES = tst_qvector.cpp +SOURCES = $$PWD/tst_qvector.cpp DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qvector_strictiterators/qvector_strictiterators.pro b/tests/auto/corelib/tools/qvector_strictiterators/qvector_strictiterators.pro new file mode 100644 index 0000000000..d6cad86aac --- /dev/null +++ b/tests/auto/corelib/tools/qvector_strictiterators/qvector_strictiterators.pro @@ -0,0 +1,3 @@ +include(../qvector/qvector.pro) +TARGET = tst_qvector_strictiterators +DEFINES += QT_STRICT_ITERATORS=1 tst_QVector=tst_QVector_StrictIterators diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index 996879ea69..d5c9e50190 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -2,6 +2,7 @@ TEMPLATE=subdirs SUBDIRS=\ qalgorithms \ qarraydata \ + qarraydata_strictiterators \ qbitarray \ qbytearray \ qbytearraylist \ @@ -20,11 +21,14 @@ SUBDIRS=\ qexplicitlyshareddatapointer \ qfreelist \ qhash \ + qhash_strictiterators \ qline \ qlinkedlist \ qlist \ + qlist_strictiterators \ qlocale \ qmap \ + qmap_strictiterators \ qmargins \ qmessageauthenticationcode \ qpair \ @@ -54,4 +58,5 @@ SUBDIRS=\ qtimezone \ qtimeline \ qvarlengtharray \ - qvector + qvector \ + qvector_strictiterators From 1704cecfac5cf42d98c97e552f04dca8f5dbe287 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 14 Feb 2014 14:51:36 -0800 Subject: [PATCH 046/124] Re-group and re-sort the configure output G does not come after I. That's actually my fault, in the original commit. But some options have been added since then in the wrong place and/or using wrong settings for the report_support function. Change-Id: Ib3f7d58a41059e5e7f97fd0e223b9629664686ad Reviewed-by: Oswald Buddenhagen --- configure | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/configure b/configure index e491836533..7e84123882 100755 --- a/configure +++ b/configure @@ -6786,6 +6786,7 @@ report_support " Qt D-Bus ..............." "$CFG_DBUS" yes "loading dbus-1 at r report_support " Qt Concurrent .........." "$CFG_CONCURRENT" report_support " Qt GUI ................." "$CFG_GUI" report_support " Qt Widgets ............." "$CFG_WIDGETS" +report_support " Large File ............." "$CFG_LARGEFILE" report_support " JavaScriptCore JIT ....." "$CFG_JAVASCRIPTCORE_JIT" auto "To be decided by JavaScriptCore" report_support " QML debugging .........." "$CFG_QML_DEBUG" report_support " Use system proxies ....." "$CFG_SYSTEM_PROXIES" @@ -6801,19 +6802,17 @@ report_support " CUPS ..................." "$CFG_CUPS" [ "$XPLATFORM_MINGW" = "yes" ] && \ report_support " DirectWrite ............" "$CFG_DIRECTWRITE" report_support " FontConfig ............." "$CFG_FONTCONFIG" -report_support " FreeType ..............." "$CFG_FREETYPE" -[ "$CFG_HARFBUZZ" != "no" ] && \ - report_support " HarfBuzz ..............." "$CFG_HARFBUZZ" +report_support " FreeType ..............." "$CFG_FREETYPE" system "system library" yes "bundled copy" +report_support " Glib ..................." "$CFG_GLIB" +report_support " GTK theme .............." "$CFG_QGTKSTYLE" +report_support " HarfBuzz ..............." "$CFG_HARFBUZZ" report_support " Iconv .................." "$CFG_ICONV" report_support " ICU ...................." "$CFG_ICU" report_support " Image formats:" report_support_plugin " GIF .................." "$CFG_GIF" qt QtGui report_support_plugin " JPEG ................." "$CFG_JPEG" "$CFG_LIBJPEG" QtGui report_support_plugin " PNG .................." "$CFG_PNG" "$CFG_LIBPNG" QtGui -report_support " Glib ..................." "$CFG_GLIB" -report_support " GTK theme .............." "$CFG_QGTKSTYLE" report_support " journald ..............." "$CFG_JOURNALD" -report_support " Large File ............." "$CFG_LARGEFILE" report_support " mtdev .................." "$CFG_MTDEV" yes "system library" report_support " Networking:" [ "$XPLATFORM_MAC" = "yes" ] && \ @@ -6823,11 +6822,10 @@ report_support " getifaddrs ..........." "$CFG_GETIFADDRS" report_support " IPv6 ifname .........." "$CFG_IPV6IFNAME" report_support " OpenSSL .............." "$CFG_OPENSSL" yes "loading libraries at run-time" linked "linked to the libraries" report_support " NIS ...................." "$CFG_NIS" -report_support " EGL ...................." "$CFG_EGL" -report_support " EGL on X ..............." "$CFG_EGL_X" -report_support " GLX ...................." "$CFG_XCB_GLX" -report_support " OpenGL ................." "$CFG_OPENGL" yes "Desktop OpenGL" es2 "OpenGL ES 2.x" -report_support " OpenVG ................." "$CFG_OPENVG-$CFG_OPENVG_SHIVA" yes-yes "ShivaVG" yes-no "native" +report_support " OpenGL / OpenVG:" +report_support " EGL .................." "$CFG_EGL" +report_support " OpenGL ..............." "$CFG_OPENGL" yes "Desktop OpenGL" es2 "OpenGL ES 2.x" +report_support " OpenVG ..............." "$CFG_OPENVG-$CFG_OPENVG_SHIVA" yes-yes "ShivaVG" yes-no "native" report_support " PCRE ..................." "$CFG_PCRE" yes "system library" qt "bundled copy" if [ -n "$PKG_CONFIG" ]; then report_support " pkg-config ............. yes" @@ -6842,6 +6840,8 @@ report_support " KMS .................." "$CFG_KMS" report_support " LinuxFB .............." "$CFG_LINUXFB" report_support " XCB .................." "$CFG_XCB" system "system library" qt "bundled copy" if [ "$CFG_XCB" != "no" ]; then + report_support " EGL on X ..........." "$CFG_EGL_X" + report_support " GLX ................" "$CFG_XCB_GLX" report_support " MIT-SHM ............" "$CFG_MITSHM" report_support " Xcb-Xlib ..........." "$CFG_XCB_XLIB" report_support " Xcursor ............" "$CFG_XCURSOR" runtime "loaded at runtime" From d7287f595a5a8fe5d44d0b8c821362a4bb290c96 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 16 Jan 2014 17:59:45 -0800 Subject: [PATCH 047/124] Make QTextDecoder use our qt_from_latin1 code Disassembly shows the Intel compiler does expand to SIMD, but a much worse code than ours. Clang 3.4 does generate a compact SIMD version, probably of the same quality as our hand-written code. And GCC 4.7 through 4.9 don't generate SIMD at all. So let's use the most efficient version. Change-Id: I418e201a774ac0df1fb2b7a7d9589df7c9b655db Reviewed-by: Lars Knoll --- src/corelib/codecs/qtextcodec.cpp | 10 +++++----- src/corelib/tools/qstring.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 2552ddebe9..7e3e629c47 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -993,6 +993,8 @@ QString QTextDecoder::toUnicode(const char *chars, int len) return c->toUnicode(chars, len, &state); } +// in qstring.cpp: +void qt_from_latin1(ushort *dst, const char *str, size_t size); /*! \overload @@ -1005,12 +1007,10 @@ void QTextDecoder::toUnicode(QString *target, const char *chars, int len) case 106: // utf8 static_cast(c)->convertToUnicode(target, chars, len, &state); break; - case 4: { // latin1 + case 4: // latin1 target->resize(len); - ushort *data = (ushort*)target->data(); - for (int i = len; i >=0; --i) - data[i] = (uchar) chars[i]; - } break; + qt_from_latin1((ushort*)target->data(), chars, len); + break; default: *target = c->toUnicode(chars, len, &state); } diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 50f616a010..2b58100baa 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -210,7 +210,7 @@ inline RetType UnrollTailLoop<0>::exec(int, RetType returnIfExited, Functor1, Fu #endif // conversion between Latin 1 and UTF-16 -static void qt_from_latin1(ushort *dst, const char *str, size_t size) +void qt_from_latin1(ushort *dst, const char *str, size_t size) { /* SIMD: * Unpacking with SSE has been shown to improve performance on recent CPUs From 3a3a7f88428a13ddd52d80940fbd086e2355bc23 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 2 Feb 2014 14:03:53 -0800 Subject: [PATCH 048/124] Normalize signal & slot signatures in connection Profiling showed that Qt Creator spent 2% of its load time normalizing signals and slots. By pre-normalizing everything, we ensure that there is no runtime cost. Profiling after this commit and the others in this series shows that the cost dropped down to zero. Change-Id: Ifc5a2c2552e245fb9a5f31514e9dd683c5c55327 Reviewed-by: Lars Knoll Reviewed-by: Oswald Buddenhagen --- src/corelib/doc/snippets/signalmapper/filereader.cpp | 4 ++-- src/gui/doc/snippets/clipboard/clipwindow.cpp | 4 ++-- src/gui/doc/snippets/draganddrop/mainwindow.cpp | 8 ++++---- src/gui/doc/snippets/separations/viewer.cpp | 4 ++-- src/platformsupport/linuxaccessibility/application.cpp | 2 +- src/plugins/bearer/connman/qconnmanengine.cpp | 4 ++-- src/widgets/dialogs/qmessagebox.cpp | 4 ++-- src/widgets/kernel/qwindowcontainer.cpp | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/corelib/doc/snippets/signalmapper/filereader.cpp b/src/corelib/doc/snippets/signalmapper/filereader.cpp index cb83ea9362..6770510f5e 100644 --- a/src/corelib/doc/snippets/signalmapper/filereader.cpp +++ b/src/corelib/doc/snippets/signalmapper/filereader.cpp @@ -74,8 +74,8 @@ FileReader::FileReader(QWidget *parent) //! [2] //slower due to signature normalization at runtime - connect(signalMapper, SIGNAL(mapped(const QString &)), - this, SLOT(readFile(const QString &))); + connect(signalMapper, SIGNAL(mapped(QString)), + this, SLOT(readFile(QString))); //! [2] */ QHBoxLayout *buttonLayout = new QHBoxLayout; diff --git a/src/gui/doc/snippets/clipboard/clipwindow.cpp b/src/gui/doc/snippets/clipboard/clipwindow.cpp index 657ea4e652..19a685b9d4 100644 --- a/src/gui/doc/snippets/clipboard/clipwindow.cpp +++ b/src/gui/doc/snippets/clipboard/clipwindow.cpp @@ -59,8 +59,8 @@ ClipWindow::ClipWindow(QWidget *parent) //! [0] connect(clipboard, SIGNAL(dataChanged()), this, SLOT(updateClipboard())); //! [0] - connect(mimeTypeCombo, SIGNAL(activated(const QString &)), - this, SLOT(updateData(const QString &))); + connect(mimeTypeCombo, SIGNAL(activated(QString)), + this, SLOT(updateData(QString))); QVBoxLayout *currentLayout = new QVBoxLayout(currentItem); currentLayout->addWidget(mimeTypeLabel); diff --git a/src/gui/doc/snippets/draganddrop/mainwindow.cpp b/src/gui/doc/snippets/draganddrop/mainwindow.cpp index dc1b39422d..c8d0bf4e09 100644 --- a/src/gui/doc/snippets/draganddrop/mainwindow.cpp +++ b/src/gui/doc/snippets/draganddrop/mainwindow.cpp @@ -54,10 +54,10 @@ MainWindow::MainWindow(QWidget *parent) QLabel *dataLabel = new QLabel(tr("Amount of data (bytes):"), centralWidget); dragWidget = new DragWidget(centralWidget); - connect(dragWidget, SIGNAL(mimeTypes(const QStringList &)), - this, SLOT(setMimeTypes(const QStringList &))); - connect(dragWidget, SIGNAL(dragResult(const QString &)), - this, SLOT(setDragResult(const QString &))); + connect(dragWidget, SIGNAL(mimeTypes(QStringList)), + this, SLOT(setMimeTypes(QStringList))); + connect(dragWidget, SIGNAL(dragResult(QString)), + this, SLOT(setDragResult(QString))); QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget); mainLayout->addWidget(mimeTypeLabel); diff --git a/src/gui/doc/snippets/separations/viewer.cpp b/src/gui/doc/snippets/separations/viewer.cpp index 84ef7b7567..6a0f49ee2f 100644 --- a/src/gui/doc/snippets/separations/viewer.cpp +++ b/src/gui/doc/snippets/separations/viewer.cpp @@ -119,8 +119,8 @@ void Viewer::createMenus() connect(openAction, SIGNAL(triggered()), this, SLOT(chooseFile())); connect(saveAction, SIGNAL(triggered()), this, SLOT(saveImage())); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); - connect(brightnessMenu, SIGNAL(triggered(QAction *)), this, - SLOT(setBrightness(QAction *))); + connect(brightnessMenu, SIGNAL(triggered(QAction*)), this, + SLOT(setBrightness(QAction*))); } /* diff --git a/src/platformsupport/linuxaccessibility/application.cpp b/src/platformsupport/linuxaccessibility/application.cpp index 5c8f2e5fe2..ae52ab3b57 100644 --- a/src/platformsupport/linuxaccessibility/application.cpp +++ b/src/platformsupport/linuxaccessibility/application.cpp @@ -171,7 +171,7 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event) // FIXME: this is critical, the timeout should probably be pretty low to allow normal processing int timeout = 100; bool sent = dbusConnection.callWithCallback(m, this, SLOT(notifyKeyboardListenerCallback(QDBusMessage)), - SLOT(notifyKeyboardListenerError(QDBusError, QDBusMessage)), timeout); + SLOT(notifyKeyboardListenerError(QDBusError,QDBusMessage)), timeout); if (sent) { //queue the event and send it after callback keyEvents.enqueue(QPair, QKeyEvent*> (QPointer(target), copyKeyEvent(keyEvent))); diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp index aee56eb034..797c30c7c6 100644 --- a/src/plugins/bearer/connman/qconnmanengine.cpp +++ b/src/plugins/bearer/connman/qconnmanengine.cpp @@ -98,8 +98,8 @@ void QConnmanEngine::initialize() ofonoContextManager = new QOfonoDataConnectionManagerInterface(ofonoManager->currentModem(),this); connect(ofonoContextManager,SIGNAL(roamingAllowedChanged(bool)),this,SLOT(reEvaluateCellular())); - connect(connmanManager,SIGNAL(servicesChanged(ConnmanMapList, QList)), - this, SLOT(updateServices(ConnmanMapList, QList))); + connect(connmanManager,SIGNAL(servicesChanged(ConnmanMapList,QList)), + this, SLOT(updateServices(ConnmanMapList,QList))); connect(connmanManager,SIGNAL(servicesReady(QStringList)),this,SLOT(servicesReady(QStringList))); connect(connmanManager,SIGNAL(scanFinished()),this,SLOT(finishedScan())); diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 3080d5f1e8..207fe3d527 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -2697,8 +2697,8 @@ QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb void QMessageBoxPrivate::initHelper(QPlatformDialogHelper *h) { Q_Q(QMessageBox); - QObject::connect(h, SIGNAL(clicked(QPlatformDialogHelper::StandardButton, QPlatformDialogHelper::ButtonRole)), - q, SLOT(_q_clicked(QPlatformDialogHelper::StandardButton, QPlatformDialogHelper::ButtonRole))); + QObject::connect(h, SIGNAL(clicked(QPlatformDialogHelper::StandardButton,QPlatformDialogHelper::ButtonRole)), + q, SLOT(_q_clicked(QPlatformDialogHelper::StandardButton,QPlatformDialogHelper::ButtonRole))); static_cast(h)->setOptions(options); } diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index a4b3caf78d..4618e1c91d 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -197,7 +197,7 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: d->window = embeddedWindow; d->window->setParent(&d->fakeParent); - connect(QGuiApplication::instance(), SIGNAL(focusWindowChanged(QWindow *)), this, SLOT(focusWindowChanged(QWindow *))); + connect(QGuiApplication::instance(), SIGNAL(focusWindowChanged(QWindow*)), this, SLOT(focusWindowChanged(QWindow*))); } QWindow *QWindowContainer::containedWindow() const From c1d4a634cb439a3c1cc3ce762eb5ace6bb6ead95 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 19 Feb 2014 18:59:24 -0800 Subject: [PATCH 049/124] Fix off-by-one error: the next ASCII character is next one The bit scan function returns the index of the last non-ASCII character. The next ASCII is the one after this. This means all the benchmarks were made while reentering the SIMD loop uselessly... Change-Id: If7de485a63428bfa36d413049d9239ddda1986aa Reviewed-by: Lars Knoll --- src/corelib/codecs/qutfcodec.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index a5d16b0b54..54312601e4 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -85,7 +85,7 @@ static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const // we don't want to load 32 bytes again in this loop if we know there are non-ASCII // characters still coming n = _bit_scan_reverse(n); - nextAscii = src + n; + nextAscii = src + n + 1; return false; } @@ -115,7 +115,7 @@ static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const // we don't want to load 16 bytes again in this loop if we know there are non-ASCII // characters still coming n = _bit_scan_reverse(n); - nextAscii = src + n; + nextAscii = src + n + 1; return false; } From 8b54cfff829490cf2e3e34051c3c1ccb02cc093a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 29 Jan 2014 12:37:02 -0800 Subject: [PATCH 050/124] Make D-Bus types without a matching Qt one prettier in qdbus Print "QMap" for "a{ss}" and print a nicer expansion of other types. Change-Id: I0a7a2ecf8f0a62bd97931f3c129cd4cb4f471ef1 Reviewed-by: Lorn Potter --- src/dbus/qdbusmetaobject.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp index 392eac6081..8337a84614 100644 --- a/src/dbus/qdbusmetaobject.cpp +++ b/src/dbus/qdbusmetaobject.cpp @@ -220,8 +220,11 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, } else if (signature == "a{sv}") { result.name = "QVariantMap"; type = QVariant::Map; + } else if (signature == "a{ss}") { + result.name = "QMap"; + type = qMetaTypeId >(); } else { - result.name = "QDBusRawType::" + signature; + result.name = "{D-Bus type \"" + signature + "\"}"; type = registerComplexDBusType(result.name); } } else { From 300be65b16f9dae2ee508858c8758c0110bf0deb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 19 Feb 2014 15:57:42 +0100 Subject: [PATCH 051/124] Windows: Use GetForegroundWindow() to check for active windows. The previously used GetActiveWindow() returns the application's window also if it is minimized. Task-number: QTBUG-36806 Change-Id: I8ede3ea30e7b714aa1af85ed67e510e1692ebb8f Reviewed-by: Joerg Bornemann Reviewed-by: Miikka Heikkinen Reviewed-by: Oliver Wolff Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowswindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index a0a9e75e2d..39b36a29cb 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1065,7 +1065,7 @@ bool QWindowsWindow::isVisible() const bool QWindowsWindow::isActive() const { // Check for native windows or children of the active native window. - if (const HWND activeHwnd = GetActiveWindow()) + if (const HWND activeHwnd = GetForegroundWindow()) if (m_data.hwnd == activeHwnd || IsChild(activeHwnd, m_data.hwnd)) return true; return false; From 3b1e9a7f9bb2825555db48d77b8ebaba810de3b1 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Sat, 22 Feb 2014 17:15:09 +1000 Subject: [PATCH 052/124] Doc: Address some "No documentation for..." warnings in QTest Task-number: QTBUG-36985 Change-Id: I811b4711edc3420911fcd706ecef2d090f41bc89 Reviewed-by: Sergio Ahumada --- .../snippets/code/src_qtestlib_qtestcase.cpp | 11 + src/testlib/qtestcase.cpp | 241 ++++++++++++++++-- 2 files changed, 227 insertions(+), 25 deletions(-) diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp index a17628155a..7bcae3bf74 100644 --- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp @@ -260,5 +260,16 @@ void TestBenchmark::simple() } //! [27] +//! [28] +QTest::keyClick(myWindow, 'a'); +//! [28] + + +//! [29] +QTest::keyClick(myWindow, Qt::Key_Escape); + +QTest::keyClick(myWindow, Qt::Key_Escape, Qt::ShiftModifier, 200); +//! [29] + } diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 6c1df8815c..f0520330af 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -567,23 +567,6 @@ QT_BEGIN_NAMESPACE \value MouseMove The mouse pointer has moved. */ -/*! \fn void QTest::keyClick(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) - - \overload - - Simulates clicking of \a key with an optional \a modifier on a \a widget. - If \a delay is larger than 0, the test will wait for \a delay milliseconds - before clicking the key. - - Example: - \snippet code/src_qtestlib_qtestcase.cpp 13 - - The example above simulates clicking \c a on \c myWidget without - any keyboard modifiers and without delay of the test. - - \sa QTest::keyClicks() -*/ - /*! \fn void QTest::keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) Simulates clicking of \a key with an optional \a modifier on a \a widget. @@ -601,6 +584,58 @@ QT_BEGIN_NAMESPACE \sa QTest::keyClicks() */ +/*! \fn void QTest::keyClick(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + + Simulates clicking of \a key with an optional \a modifier on a \a widget. + If \a delay is larger than 0, the test will wait for \a delay milliseconds + before clicking the key. + + Example: + \snippet code/src_qtestlib_qtestcase.cpp 13 + + The example above simulates clicking \c a on \c myWidget without + any keyboard modifiers and without delay of the test. + + \sa QTest::keyClicks() +*/ + +/*! \fn void QTest::keyClick(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + \since 5.0 + + Simulates clicking of \a key with an optional \a modifier on a \a window. + If \a delay is larger than 0, the test will wait for \a delay milliseconds + before clicking the key. + + Examples: + \snippet code/src_qtestlib_qtestcase.cpp 29 + + The first example above simulates clicking the \c escape key on \c + myWindow without any keyboard modifiers and without delay. The + second example simulates clicking \c shift-escape on \c myWindow + following a 200 ms delay of the test. + + \sa QTest::keyClicks() +*/ + +/*! \fn void QTest::keyClick(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + \since 5.0 + + Simulates clicking of \a key with an optional \a modifier on a \a window. + If \a delay is larger than 0, the test will wait for \a delay milliseconds + before clicking the key. + + Example: + \snippet code/src_qtestlib_qtestcase.cpp 28 + + The example above simulates clicking \c a on \c myWindow without + any keyboard modifiers and without delay of the test. + + \sa QTest::keyClicks() +*/ + /*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) Sends a Qt key event to \a widget with the given \a key and an associated \a action. @@ -609,13 +644,29 @@ QT_BEGIN_NAMESPACE */ /*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, char ascii, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) - \overload Sends a Qt key event to \a widget with the given key \a ascii and an associated \a action. Optionally, a keyboard \a modifier can be specified, as well as a \a delay (in milliseconds) of the test before sending the event. +*/ +/*! \fn void QTest::keyEvent(KeyAction action, QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + \since 5.0 + + Sends a Qt key event to \a window with the given \a key and an associated \a action. + Optionally, a keyboard \a modifier can be specified, as well as a \a delay + (in milliseconds) of the test before sending the event. +*/ + +/*! \fn void QTest::keyEvent(KeyAction action, QWindow *window, char ascii, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + \since 5.0 + + Sends a Qt key event to \a window with the given key \a ascii and an associated \a action. + Optionally, a keyboard \a modifier can be specified, as well as a \a delay + (in milliseconds) of the test before sending the event. */ /*! \fn void QTest::keyPress(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) @@ -629,7 +680,6 @@ QT_BEGIN_NAMESPACE */ /*! \fn void QTest::keyPress(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) - \overload Simulates pressing a \a key with an optional \a modifier on a \a widget. @@ -641,6 +691,31 @@ QT_BEGIN_NAMESPACE \sa QTest::keyRelease(), QTest::keyClick() */ +/*! \fn void QTest::keyPress(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + \since 5.0 + + Simulates pressing a \a key with an optional \a modifier on a \a window. If \a delay + is larger than 0, the test will wait for \a delay milliseconds before pressing the key. + + \b {Note:} At some point you should release the key using \l keyRelease(). + + \sa QTest::keyRelease(), QTest::keyClick() +*/ + +/*! \fn void QTest::keyPress(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + \since 5.0 + + Simulates pressing a \a key with an optional \a modifier on a \a window. + If \a delay is larger than 0, the test will wait for \a delay milliseconds + before pressing the key. + + \b {Note:} At some point you should release the key using \l keyRelease(). + + \sa QTest::keyRelease(), QTest::keyClick() +*/ + /*! \fn void QTest::keyRelease(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) Simulates releasing a \a key with an optional \a modifier on a \a widget. @@ -651,7 +726,6 @@ QT_BEGIN_NAMESPACE */ /*! \fn void QTest::keyRelease(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) - \overload Simulates releasing a \a key with an optional \a modifier on a \a widget. @@ -661,6 +735,27 @@ QT_BEGIN_NAMESPACE \sa QTest::keyClick() */ +/*! \fn void QTest::keyRelease(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + \since 5.0 + + Simulates releasing a \a key with an optional \a modifier on a \a window. + If \a delay is larger than 0, the test will wait for \a delay milliseconds + before releasing the key. + + \sa QTest::keyPress(), QTest::keyClick() +*/ + +/*! \fn void QTest::keyRelease(QWindow *window, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) + \overload + \since 5.0 + + Simulates releasing a \a key with an optional \a modifier on a \a window. + If \a delay is larger than 0, the test will wait for \a delay milliseconds + before releasing the key. + + \sa QTest::keyClick() +*/ /*! \fn void QTest::keyClicks(QWidget *widget, const QString &sequence, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) @@ -679,6 +774,18 @@ QT_BEGIN_NAMESPACE \sa QTest::keyClick() */ +/*! \fn void QTest::waitForEvents() + \internal +*/ + +/*! \fn void QTest::mouseEvent(MouseAction action, QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1) + \internal +*/ + +/*! \fn void QTest::mouseEvent(MouseAction action, QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1) + \internal +*/ + /*! \fn void QTest::mousePress(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1) Simulates pressing a mouse \a button with an optional \a modifier @@ -690,6 +797,19 @@ QT_BEGIN_NAMESPACE \sa QTest::mouseRelease(), QTest::mouseClick() */ +/*! \fn void QTest::mousePress(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, QPoint pos = QPoint(), int delay=-1) + \overload + \since 5.0 + + Simulates pressing a mouse \a button with an optional \a stateKey modifier + on a \a window. The position is defined by \a pos; the default + position is the center of the window. If \a delay is specified, + the test will wait for the specified amount of milliseconds before + the press. + + \sa QTest::mouseRelease(), QTest::mouseClick() +*/ + /*! \fn void QTest::mouseRelease(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1) Simulates releasing a mouse \a button with an optional \a modifier @@ -701,6 +821,19 @@ QT_BEGIN_NAMESPACE \sa QTest::mousePress(), QTest::mouseClick() */ +/*! \fn void QTest::mouseRelease(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, QPoint pos = QPoint(), int delay=-1) + \overload + \since 5.0 + + Simulates releasing a mouse \a button with an optional \a stateKey modifier + on a \a window. The position of the release is defined by \a pos; + the default position is the center of the window. If \a delay is + specified, the test will wait for the specified amount of + milliseconds before releasing the button. + + \sa QTest::mousePress(), QTest::mouseClick() +*/ + /*! \fn void QTest::mouseClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1) Simulates clicking a mouse \a button with an optional \a modifier @@ -712,6 +845,19 @@ QT_BEGIN_NAMESPACE \sa QTest::mousePress(), QTest::mouseRelease() */ +/*! \fn void QTest::mouseClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, QPoint pos = QPoint(), int delay=-1) + \overload + \since 5.0 + + Simulates clicking a mouse \a button with an optional \a stateKey modifier + on a \a window. The position of the click is defined by \a pos; + the default position is the center of the window. If \a delay is + specified, the test will wait for the specified amount of + milliseconds before pressing and before releasing the button. + + \sa QTest::mousePress(), QTest::mouseRelease() +*/ + /*! \fn void QTest::mouseDClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1) Simulates double clicking a mouse \a button with an optional \a @@ -723,6 +869,19 @@ QT_BEGIN_NAMESPACE \sa QTest::mouseClick() */ +/*! \fn void QTest::mouseDClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = 0, QPoint pos = QPoint(), int delay=-1) + \overload + \since 5.0 + + Simulates double clicking a mouse \a button with an optional \a stateKey + modifier on a \a window. The position of the click is defined by + \a pos; the default position is the center of the window. If \a + delay is specified, the test will wait for the specified amount of + milliseconds before each press and release. + + \sa QTest::mouseClick() +*/ + /*! \fn void QTest::mouseMove(QWidget *widget, QPoint pos = QPoint(), int delay=-1) Moves the mouse pointer to a \a widget. If \a pos is not @@ -731,6 +890,16 @@ QT_BEGIN_NAMESPACE moving the mouse pointer. */ +/*! \fn void QTest::mouseMove(QWindow *window, QPoint pos = QPoint(), int delay=-1) + \overload + \since 5.0 + + Moves the mouse pointer to a \a window. If \a pos is not + specified, the mouse pointer moves to the center of the window. If + a \a delay (in milliseconds) is given, the test will wait before + moving the mouse pointer. +*/ + /*! \fn char *QTest::toString(const T &value) @@ -2448,6 +2617,9 @@ static inline bool isWindowsBuildDirectory(const QString &dirName) } #endif +/*! \internal + */ + QString QTest::qFindTestData(const QString& base, const char *file, int line, const char *builddir) { QString found; @@ -2726,7 +2898,7 @@ bool QTest::compare_helper(bool success, const char *failureMsg, } /*! \fn bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line) -\internal + \internal */ bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line) @@ -2736,7 +2908,7 @@ bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const } /*! \fn bool QTest::qCompare(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line) -\internal + \internal */ bool QTest::qCompare(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line) @@ -2745,6 +2917,14 @@ bool QTest::qCompare(double const &t1, double const &t2, const char *actual, con toString(t1), toString(t2), actual, expected, file, line); } +/*! \fn bool QTest::qCompare(double const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line) + \internal + */ + +/*! \fn bool QTest::qCompare(float const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line) + \internal + */ + #define TO_STRING_IMPL(TYPE, FORMAT) \ template <> Q_TESTLIB_EXPORT char *QTest::toString(const TYPE &t) \ { \ @@ -2807,12 +2987,11 @@ bool QTest::compare_string_helper(const char *t1, const char *t2, const char *ac \internal */ - -/*! \fn void QTest::mouseEvent(MouseAction action, QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1) +/*! \fn bool QTest::qCompare(QIcon const &t1, QIcon const &t2, const char *actual, const char *expected, const char *file, int line) \internal */ -/*! \fn bool QTest::qCompare(QIcon const &t1, QIcon const &t2, const char *actual, const char *expected, const char *file, int line) +/*! \fn bool QTest::qCompare(QImage const &t1, QImage const &t2, const char *actual, const char *expected, const char *file, int line) \internal */ @@ -2916,12 +3095,24 @@ bool QTest::compare_string_helper(const char *t1, const char *t2, const char *ac \internal */ +/*! \fn void QTest::sendKeyEvent(KeyAction action, QWindow *window, Qt::Key code, QString text, Qt::KeyboardModifiers modifier, int delay=-1) + \internal +*/ + /*! \fn void QTest::sendKeyEvent(KeyAction action, QWidget *widget, Qt::Key code, char ascii, Qt::KeyboardModifiers modifier, int delay=-1) \internal */ +/*! \fn void QTest::sendKeyEvent(KeyAction action, QWindow *window, Qt::Key code, char ascii, Qt::KeyboardModifiers modifier, int delay=-1) + \internal +*/ + /*! \fn void QTest::simulateEvent(QWidget *widget, bool press, int code, Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1) \internal */ +/*! \fn void QTest::simulateEvent(QWindow *window, bool press, int code, Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1) + \internal +*/ + QT_END_NAMESPACE From acf1cb94587513c29d05b2114d2704f236b7f1b9 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Thu, 20 Feb 2014 15:38:37 +0100 Subject: [PATCH 053/124] Fix typo in QLibraryInfo::build() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit before: Config: Using QtTest library 5.4.0, Qt 5.4.0 (Feb 20 2014), GCC 4.6.3, 32 bit, release build) Qt 5.4.0 (Feb 20 2014), GCC 4.6.3, 32 bit, release build) after: Config: Using QtTest library 5.4.0, Qt 5.4.0 (Feb 20 2014, GCC 4.6.3, 32 bit, release build) Qt 5.4.0 (Feb 20 2014, GCC 4.6.3, 32 bit, release build) Change-Id: Ia4c9f994ef7e834831c78e8dbc00a52e06c0ed9a Reviewed-by: Friedemann Kleint Reviewed-by: JÄ™drzej Nowacki --- src/corelib/global/qlibraryinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 93d5407184..689de48e26 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -289,7 +289,7 @@ QLibraryInfo::buildDate() const char *QLibraryInfo::build() Q_DECL_NOTHROW { - static const char data[] = "Qt " QT_VERSION_STR " (" __DATE__ "), " + static const char data[] = "Qt " QT_VERSION_STR " (" __DATE__ ", " COMPILER_STRING ", " #if QT_POINTER_SIZE == 4 "32" From 70ca6f5bba1116ce63cbdf753d041eecc72d8627 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Mon, 17 Feb 2014 23:52:21 +0100 Subject: [PATCH 054/124] Remove qSort usages from core tests QtAlgorithms is getting deprecated, see http://www.mail-archive.com/development@qt-project.org/msg01603.html Change-Id: I355558fe6a51d00e9aa1f8b1221c6ec0c1e6bb77 Reviewed-by: Friedemann Kleint Reviewed-by: Giuseppe D'Angelo --- .../qitemselectionmodel/tst_qitemselectionmodel.cpp | 6 ++++-- tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp | 4 +++- tests/auto/corelib/tools/qhash/tst_qhash.cpp | 4 +++- .../tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp index 9788b78771..9e3457a25a 100644 --- a/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/corelib/itemmodels/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -43,6 +43,8 @@ #include +#include + class tst_QItemSelectionModel : public QObject { Q_OBJECT @@ -1833,7 +1835,7 @@ void tst_QItemSelectionModel::selectedRows() QModelIndexList selectedRowIndexes = selectionModel.selectedRows(column); QCOMPARE(selectedRowIndexes.count(), expectedRows.count()); - qSort(selectedRowIndexes); + std::sort(selectedRowIndexes.begin(), selectedRowIndexes.end()); for (int l = 0; l < selectedRowIndexes.count(); ++l) { QCOMPARE(selectedRowIndexes.at(l).row(), expectedRows.at(l)); QCOMPARE(selectedRowIndexes.at(l).column(), column); @@ -1893,7 +1895,7 @@ void tst_QItemSelectionModel::selectedColumns() QModelIndexList selectedColumnIndexes = selectionModel.selectedColumns(row); QCOMPARE(selectedColumnIndexes.count(), expectedColumns.count()); - qSort(selectedColumnIndexes); + std::sort(selectedColumnIndexes.begin(), selectedColumnIndexes.end()); for (int l = 0; l < selectedColumnIndexes.count(); ++l) { QCOMPARE(selectedColumnIndexes.at(l).column(), expectedColumns.at(l)); QCOMPARE(selectedColumnIndexes.at(l).row(), row); diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 211633f888..acff6a55ba 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -49,6 +49,8 @@ # include #endif +#include + // At least these specific versions of MSVC2010 has a severe performance problem with this file, // taking about 1 hour to compile if the portion making use of variadic macros is enabled. #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160030319) && (_MSC_FULL_VER <= 160040219) @@ -2153,7 +2155,7 @@ void tst_QMetaType::compareCustomType() { QFETCH(QVariantList, unsorted); QFETCH(QVariantList, sorted); - qSort(unsorted); + std::sort(unsorted.begin(), unsorted.end()); QCOMPARE(unsorted, sorted); } diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp index ddb72a3c32..73f8973245 100644 --- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp +++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp @@ -44,6 +44,8 @@ #include #include +#include + class tst_QHash : public QObject { Q_OBJECT @@ -1167,7 +1169,7 @@ template QList sorted(const QList &list) { QList res = list; - qSort(res); + std::sort(res.begin(), res.end()); return res; } diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp b/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp index 4245fe1418..2c0967da1c 100644 --- a/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp +++ b/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp @@ -47,6 +47,8 @@ #include #include +#include + class tst_QTextBoundaryFinder : public QObject { Q_OBJECT @@ -203,7 +205,7 @@ static void doTestData(const QString &testString, const QList &expectedBrea // test toPreviousBoundary() { QList expectedBreakPositionsRev = expectedBreakPositions; - qSort(expectedBreakPositionsRev.begin(), expectedBreakPositionsRev.end(), qGreater()); + std::sort(expectedBreakPositionsRev.begin(), expectedBreakPositionsRev.end(), qGreater()); QList actualBreakPositions; boundaryFinder.toEnd(); From 0febd75d5242653be3202ea0e46ed6107e4333bd Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Thu, 20 Feb 2014 14:54:35 +0100 Subject: [PATCH 055/124] QWidget: do not allocate a QOpenGLContext unless needed by QQuickWidget Task-number: QTBUG-36871 Change-Id: I739f270e9344f888593e04c6221807dbcf6cb55e Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qwidgetbackingstore.cpp | 16 +++++++--------- src/widgets/kernel/qwidgetbackingstore_p.h | 3 +++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index dc918657b4..6cfe6a6b35 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -73,16 +73,14 @@ extern QRegion qt_dirtyRegion(QWidget *); * \a tlwOffset is the position of the top level widget relative to the window surface. * \a region is the region to be updated in \a widget coordinates. */ -static inline void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore, - QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures = 0, - QOpenGLContext *context = 0) +void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore, + QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures) { #ifdef QT_NO_OPENGL Q_UNUSED(widgetTextures); - Q_UNUSED(context); #endif Q_ASSERT(widget); - Q_ASSERT(!region.isEmpty() || (context && widgetTextures && widgetTextures->count())); + Q_ASSERT(!region.isEmpty() || (widgetTextures && widgetTextures->count())); Q_ASSERT(backingStore); Q_ASSERT(tlw); @@ -117,7 +115,7 @@ static inline void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStor #ifndef QT_NO_OPENGL if (widgetTextures) - backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures, context); + backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures, tlw->d_func()->shareContext()); else #endif backingStore->flush(region, widget->windowHandle(), offset); @@ -936,7 +934,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg // Nothing to repaint. if (!isDirty()) { - qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext()); + qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures); return; } @@ -1190,7 +1188,7 @@ void QWidgetBackingStore::flush(QWidget *widget) { if (!dirtyOnScreen.isEmpty()) { QWidget *target = widget ? widget : tlw; - qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext()); + qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures); dirtyOnScreen = QRegion(); } @@ -1198,7 +1196,7 @@ void QWidgetBackingStore::flush(QWidget *widget) #ifndef QT_NO_OPENGL if (widgetTextures && widgetTextures->count()) { QWidget *target = widget ? widget : tlw; - qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext()); + qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures); } #endif return; diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h index 2fe58fa4a7..9c8ed3d5ca 100644 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ b/src/widgets/kernel/qwidgetbackingstore_p.h @@ -135,6 +135,9 @@ private: static bool flushPaint(QWidget *widget, const QRegion &rgn); static void unflushPaint(QWidget *widget, const QRegion &rgn); + static void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore, + QWidget *tlw, const QPoint &tlwOffset, + QPlatformTextureList *widgetTextures = 0); void doSync(); bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget); From 26a5727f75c7666e257c930af4cc67081ef1f6d6 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 18 Feb 2014 15:31:38 +0200 Subject: [PATCH 056/124] Make full use of QT_ANDROID_RASTER_IMAGE_DEPTH env variable. If raster only apps set QT_ANDROID_RASTER_IMAGE_DEPTH to 16 (RGB16), we should create also RGB16 native surface. Change-Id: I82692ff34b0e604e627d1d86a437272e3700daf8 Reviewed-by: Paul Olav Tvete --- .../src/org/qtproject/qt5/android/QtActivityDelegate.java | 4 ++-- .../jar/src/org/qtproject/qt5/android/QtNative.java | 4 ++-- .../jar/src/org/qtproject/qt5/android/QtSurface.java | 8 ++++++-- src/plugins/platforms/android/androidjnimain.cpp | 7 ++++--- src/plugins/platforms/android/androidjnimain.h | 2 +- .../platforms/android/qandroidplatformopenglwindow.cpp | 2 +- src/plugins/platforms/android/qandroidplatformscreen.cpp | 2 +- 7 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 620ea22dad..aa18dfc2d1 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -987,7 +987,7 @@ public class QtActivityDelegate m_nativeViews.put(id, view); } - public void createSurface(int id, boolean onTop, int x, int y, int w, int h) { + public void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth) { if (m_surfaces.size() == 0) { TypedValue attr = new TypedValue(); m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true); @@ -1005,7 +1005,7 @@ public class QtActivityDelegate if (m_surfaces.containsKey(id)) m_layout.removeView(m_surfaces.remove(id)); - QtSurface surface = new QtSurface(m_activity, id, onTop); + QtSurface surface = new QtSurface(m_activity, id, onTop, imageDepth); if (w < 0 || h < 0) { surface.setLayoutParams( new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 9b716f74e5..02bb1ae485 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -511,12 +511,12 @@ public class QtNative return certificateArray; } - private static void createSurface(final int id, final boolean onTop, final int x, final int y, final int w, final int h) + private static void createSurface(final int id, final boolean onTop, final int x, final int y, final int w, final int h, final int imageDepth) { runAction(new Runnable() { @Override public void run() { - m_activityDelegate.createSurface(id, onTop, x, y, w, h); + m_activityDelegate.createSurface(id, onTop, x, y, w, h, imageDepth); } }); } diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java index 1454c30638..45a80a3dbb 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java @@ -59,14 +59,18 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback private GestureDetector m_gestureDetector; private Object m_accessibilityDelegate = null; - public QtSurface(Context context, int id, boolean onTop) + public QtSurface(Context context, int id, boolean onTop, int imageDepth) { super(context); setFocusable(false); setFocusableInTouchMode(false); setZOrderMediaOverlay(onTop); getHolder().addCallback(this); - getHolder().setFormat(PixelFormat.RGBA_8888); + if (imageDepth == 16) + getHolder().setFormat(PixelFormat.RGB_565); + else + getHolder().setFormat(PixelFormat.RGBA_8888); + if (android.os.Build.VERSION.SDK_INT < 11) getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU); diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 28a5da4b5d..784cc2e38b 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -334,7 +334,7 @@ namespace QtAndroid return manufacturer + QStringLiteral(" ") + model; } - int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop) + int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop, int imageDepth) { QJNIEnvironmentPrivate env; if (!env) @@ -356,7 +356,8 @@ namespace QtAndroid m_createSurfaceMethodID, surfaceId, jboolean(onTop), - x, y, w, h); + x, y, w, h, + imageDepth); return surfaceId; } @@ -689,7 +690,7 @@ static int registerNatives(JNIEnv *env) return JNI_FALSE; } - GET_AND_CHECK_STATIC_METHOD(m_createSurfaceMethodID, m_applicationClass, "createSurface", "(IZIIII)V"); + GET_AND_CHECK_STATIC_METHOD(m_createSurfaceMethodID, m_applicationClass, "createSurface", "(IZIIIII)V"); GET_AND_CHECK_STATIC_METHOD(m_insertNativeViewMethodID, m_applicationClass, "insertNativeView", "(ILandroid/view/View;IIII)V"); GET_AND_CHECK_STATIC_METHOD(m_setSurfaceGeometryMethodID, m_applicationClass, "setSurfaceGeometry", "(IIIII)V"); GET_AND_CHECK_STATIC_METHOD(m_destroySurfaceMethodID, m_applicationClass, "destroySurface", "(I)V"); diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index eb604c8da8..c00b23fff3 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -66,7 +66,7 @@ namespace QtAndroid void setQtThread(QThread *thread); - int createSurface(AndroidSurfaceClient * client, const QRect &geometry, bool onTop); + int createSurface(AndroidSurfaceClient * client, const QRect &geometry, bool onTop, int imageDepth); int insertNativeView(jobject view, const QRect &geometry); void setSurfaceGeometry(int surfaceId, const QRect &geometry); void destroySurface(int surfaceId); diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp index 9df6610a99..34db729289 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp @@ -57,7 +57,7 @@ QAndroidPlatformOpenGLWindow::QAndroidPlatformOpenGLWindow(QWindow *window, EGLD :QAndroidPlatformWindow(window), m_eglDisplay(display) { lockSurface(); - m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), bool(window->flags() & Qt::WindowStaysOnTopHint)); + m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), bool(window->flags() & Qt::WindowStaysOnTopHint), 32); m_surfaceWaitCondition.wait(&m_surfaceMutex); unlockSurface(); } diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 3704097414..dbf317696f 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -247,7 +247,7 @@ void QAndroidPlatformScreen::doRedraw() QMutexLocker lock(&m_surfaceMutex); if (m_id == -1) { - m_id = QtAndroid::createSurface(this, m_geometry, true); + m_id = QtAndroid::createSurface(this, m_geometry, true, m_depth); m_surfaceWaitCondition.wait(&m_surfaceMutex); } From 12a7d23d528262ec1eca3c870fc19ef7d54ca417 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 11 Feb 2014 12:53:36 +0100 Subject: [PATCH 057/124] Introducing QOpenGLShaderProgram::create() Needed for QOpenGLShaderProgram to be usable with GL_OES_get_program_binary and potentially other extensions. [Changelog][QtGui] The function QOpenGLShaderProgram::create() has been added. It is can be used to force immediate allocation of the program's id. Change-Id: I36b3f45b00e7a439df12c54af7dc06c0ba913587 Reviewed-by: Lars Knoll --- src/gui/opengl/qopenglshaderprogram.cpp | 23 ++++++++++++++++++++++- src/gui/opengl/qopenglshaderprogram.h | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index 06f40eafd0..164e5e6925 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -123,7 +123,8 @@ QT_BEGIN_NAMESPACE on the return value from programId(). Then the application should call link(), which will notice that the program has already been specified and linked, allowing other operations to be performed - on the shader program. + on the shader program. The shader program's id can be explicitly + created using the create() function. \sa QOpenGLShader */ @@ -639,6 +640,26 @@ QOpenGLShaderProgram::~QOpenGLShaderProgram() { } +/*! + Requests the shader program's id to be created immediately. Returns \c true + if successful; \c false otherwise. + + This function is primarily useful when combining QOpenGLShaderProgram + with other OpenGL functions that operate directly on the shader + program id, like \c {GL_OES_get_program_binary}. + + When the shader program is used normally, the shader program's id will + be created on demand. + + \sa programId() + + \since 5.3 + */ +bool QOpenGLShaderProgram::create() +{ + return init(); +} + bool QOpenGLShaderProgram::init() { Q_D(QOpenGLShaderProgram); diff --git a/src/gui/opengl/qopenglshaderprogram.h b/src/gui/opengl/qopenglshaderprogram.h index b894ae3af8..91754842e6 100644 --- a/src/gui/opengl/qopenglshaderprogram.h +++ b/src/gui/opengl/qopenglshaderprogram.h @@ -130,6 +130,8 @@ public: bool bind(); void release(); + bool create(); + GLuint programId() const; int maxGeometryOutputVertices() const; From e85b4ed77a6b77e4a5aa9b858e41ff4bbcea04b0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 21 Feb 2014 19:02:45 -0800 Subject: [PATCH 058/124] QtTest: Don't crash when -callgrind is used on QTEST_APPLESS_MAIN If there's no qApp, then QCoreApplication::arguments() returns an empty list (after printing a warning). That means the callgrind runner can't get the arguments it needs in order to rerun the benchmark. The crash happens because it always uses .at(0) to try and get the executable's path. Even if we get the path from somewhere else, we still need the arguments. Change-Id: I5c74af4d96fc5824b2b7fd7a89648d78393016e2 Reviewed-by: Sergio Ahumada --- src/testlib/qtestcase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index f0520330af..10bf200f4f 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2442,6 +2442,9 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) #ifdef QTESTLIB_USE_VALGRIND if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) { + if (!qApp) + qFatal("QtTest: -callgrind option is not available with QTEST_APPLESS_MAIN"); + const QStringList origAppArgs(QCoreApplication::arguments()); if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode)) return -1; From 0c9c43c1483dbe8146f05a8df6ccb15f15a8f403 Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Sat, 22 Feb 2014 00:33:32 +0800 Subject: [PATCH 059/124] Doc: Address some "No documentation for..." QDoc warnings Task-number: QTBUG-36985 Change-Id: I8619fb77e7879399064281f7bbefe5f12d3849a2 Reviewed-by: Frederik Gladhorn --- src/corelib/tools/qbytearray.cpp | 11 +++++------ src/corelib/tools/qstring.cpp | 9 +++++++++ src/gui/opengl/qopenglversionfunctions.cpp | 2 ++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 304ce69449..73fd6369a7 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -3665,12 +3665,6 @@ QByteArray QByteArray::toBase64(Base64Options options) const \sa toUShort() */ -/*! - \overload - - \sa toLongLong() -*/ - static char *qulltoa2(char *p, qulonglong n, int base) { #if defined(QT_CHECK_RANGE) @@ -3689,6 +3683,11 @@ static char *qulltoa2(char *p, qulonglong n, int base) return p; } +/*! + \overload + + \sa toLongLong() +*/ QByteArray &QByteArray::setNum(qlonglong n, int base) { const int buffsize = 66; // big enough for MAX_ULLONG in base 2 diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 2b58100baa..c433120f6f 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1494,6 +1494,10 @@ QString::QString(QChar ch) \internal */ +/*! \fn QString::QString(QStringDataPtr) + \internal +*/ + /*! \fn QString &QString::operator=(const Null &) \internal */ @@ -8464,6 +8468,11 @@ bool operator<(const QStringRef &s1,const QStringRef &s2) this string reference, returning the result. */ +/*! + \typedef QString::Data + \internal +*/ + /*! \typedef QString::DataPtr \internal diff --git a/src/gui/opengl/qopenglversionfunctions.cpp b/src/gui/opengl/qopenglversionfunctions.cpp index 428f6e8a8b..5df7463e8a 100644 --- a/src/gui/opengl/qopenglversionfunctions.cpp +++ b/src/gui/opengl/qopenglversionfunctions.cpp @@ -191,6 +191,8 @@ QAbstractOpenGLFunctions::~QAbstractOpenGLFunctions() delete d_ptr; } +/*! \internal + */ bool QAbstractOpenGLFunctions::initializeOpenGLFunctions() { Q_D(QAbstractOpenGLFunctions); From 74d4fcea4a83933f9f2fcc9ff6a54f1c1e59382e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 18 Feb 2014 15:35:52 +0100 Subject: [PATCH 060/124] Enable QMenu::setNoReplayFor(QWidget *noReplayFor) for all platforms. This prevents a tool button menu from being opened by a replayed click. This partially reverts 8301c0002280c10970cce1e17f634e74c61f2f5d . Task-number: QTBUG-36863 Change-Id: I396e3694de8b3d4ca916457c2b2df39798502530 Reviewed-by: Shawn Rutledge Reviewed-by: Gabriel de Dietrich --- src/widgets/widgets/qmenu.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index edfeb840b1..2820608621 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -3173,11 +3173,7 @@ void QMenu::internalDelayedPopup() */ void QMenu::setNoReplayFor(QWidget *noReplayFor) { -#ifdef Q_OS_WIN d_func()->noReplayFor = noReplayFor; -#else - Q_UNUSED(noReplayFor); -#endif } /*!\internal From aac68a9ef36f75d23877d6ce27b6392612900756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 24 Feb 2014 11:34:20 +0100 Subject: [PATCH 061/124] Fix texture glyph cache setup in old OpenGL paint engine Caused assert-crash reported on Windows. Task-number: QTBUG-37027 Change-Id: If84b970a153570115afb344797728a0b1a04db5b Reviewed-by: Kai Koehne --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index ec4ff5a2b2..b8c039d0e2 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1482,9 +1482,10 @@ void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) // don't try to cache huge fonts or vastly transformed fonts QFontEngine *fontEngine = textItem->fontEngine(); if (shouldDrawCachedGlyphs(fontEngine, s->matrix)) { - QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat >= 0 - ? QFontEngine::GlyphFormat(textItem->fontEngine()->glyphFormat) - : d->glyphCacheFormat; + + QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None + ? fontEngine->glyphFormat : d->glyphCacheFormat; + if (glyphFormat == QFontEngine::Format_A32) { if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || d->device->alphaRequested() || s->matrix.type() > QTransform::TxTranslate @@ -1532,10 +1533,8 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem QTransform::TransformationType txtype = s->matrix.type(); - QFontEngine::GlyphFormat glyphFormat = ti.fontEngine->glyphFormat >= 0 - ? ti.fontEngine->glyphFormat - : d->glyphCacheFormat; - + QFontEngine::GlyphFormat glyphFormat = ti.fontEngine->glyphFormat != QFontEngine::Format_None + ? ti.fontEngine->glyphFormat : d->glyphCacheFormat; if (glyphFormat == QFontEngine::Format_A32) { if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() From c05e5948a0510e00befdb15b12c49b546123ceaf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 24 Feb 2014 11:26:41 +0100 Subject: [PATCH 062/124] Fix division by zero in hellogl_es2 example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-37027 Change-Id: Id18ee9c44650de9c434a82d3d10cf48e6ba9e78c Reviewed-by: Tor Arne Vestbø Reviewed-by: Kai Koehne --- examples/opengl/hellogl_es2/glwidget.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/opengl/hellogl_es2/glwidget.cpp b/examples/opengl/hellogl_es2/glwidget.cpp index a5c22447f0..7267cfd124 100644 --- a/examples/opengl/hellogl_es2/glwidget.cpp +++ b/examples/opengl/hellogl_es2/glwidget.cpp @@ -308,12 +308,12 @@ void GLWidget::paintGL() bubble->drawBubble(&painter); } - QString framesPerSecond; - framesPerSecond.setNum(frames /(time.elapsed() / 1000.0), 'f', 2); - - painter.setPen(Qt::white); - - painter.drawText(20, 40, framesPerSecond + " fps"); + if (const int elapsed = time.elapsed()) { + QString framesPerSecond; + framesPerSecond.setNum(frames /(elapsed / 1000.0), 'f', 2); + painter.setPen(Qt::white); + painter.drawText(20, 40, framesPerSecond + " fps"); + } painter.end(); From 921bfe58c2a41b4605fc6eae342c9a505ad6fb04 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 18 Feb 2014 09:00:24 +0100 Subject: [PATCH 063/124] Fix potential null pointer access in qglx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reportedly does fix crashes when running a Qt Quick 2 application over remote X. Task-number: QTCREATORBUG-11207 Change-Id: I6fa82420f9d12e56e52fa8efd263bf18d868d7d8 Reviewed-by: Ville Nummela Reviewed-by: Jørgen Lind Reviewed-by: Gunnar Sletta --- src/plugins/platforms/xcb/qglxintegration.cpp | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index f7abb4662b..ed2f685770 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -493,19 +493,21 @@ void QGLXContext::queryDummyContext() m_supportsThreading = true; - const char *renderer = (const char *) glGetString(GL_RENDERER); - for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) { - if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) { - m_supportsThreading = false; - break; + if (const char *renderer = (const char *) glGetString(GL_RENDERER)) { + for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) { + if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) { + m_supportsThreading = false; + break; + } } } - const char *vendor = (const char *) glGetString(GL_VENDOR); - for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) { - if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { - m_supportsThreading = false; - break; + if (const char *vendor = (const char *) glGetString(GL_VENDOR)) { + for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) { + if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { + m_supportsThreading = false; + break; + } } } From 328a282ebdbbfe185e87e668285d5152a1133bf9 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Mon, 24 Feb 2014 12:26:59 +0100 Subject: [PATCH 064/124] Compile fix for QT_NO_OPENGL Change-Id: I5ea962b0d77198945a4f87ad821d3c3dcffd260c Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qwidgetbackingstore.cpp | 11 ++++++++--- src/widgets/kernel/qwidgetbackingstore_p.h | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 6cfe6a6b35..43e2ccdf0b 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -78,9 +78,11 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBack { #ifdef QT_NO_OPENGL Q_UNUSED(widgetTextures); + Q_ASSERT(!region.isEmpty()); +#else + Q_ASSERT(!region.isEmpty() || (widgetTextures && widgetTextures->count())); #endif Q_ASSERT(widget); - Q_ASSERT(!region.isEmpty() || (widgetTextures && widgetTextures->count())); Q_ASSERT(backingStore); Q_ASSERT(tlw); @@ -749,8 +751,9 @@ QWidgetBackingStore::~QWidgetBackingStore() for (int c = 0; c < dirtyWidgets.size(); ++c) { resetWidget(dirtyWidgets.at(c)); } - +#ifndef QT_NO_OPENGL delete dirtyOnScreenWidgets; +#endif dirtyOnScreenWidgets = 0; } @@ -959,7 +962,6 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo findTextureWidgetsRecursively(tlw, w, widgetTextures); } } -#endif QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore) : m_locked(false), @@ -979,6 +981,7 @@ void QPlatformTextureListWatcher::onLockStatusChanged(bool locked) if (!locked) m_backingStore->sync(); } +#endif // QT_NO_OPENGL /*! Synchronizes the backing store, i.e. dirty areas are repainted and flushed. @@ -1003,6 +1006,7 @@ void QWidgetBackingStore::sync() return; } +#ifndef QT_NO_OPENGL if (textureListWatcher && !textureListWatcher->isLocked()) { textureListWatcher->deleteLater(); textureListWatcher = 0; @@ -1013,6 +1017,7 @@ void QWidgetBackingStore::sync() textureListWatcher->watch(widgetTextures); return; } +#endif doSync(); } diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h index 9c8ed3d5ca..e362ee4ac1 100644 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ b/src/widgets/kernel/qwidgetbackingstore_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QPlatformTextureList; +class QPlatformTextureListWatcher; class QWidgetBackingStore; struct BeginPaintInfo { @@ -70,6 +71,7 @@ struct BeginPaintInfo { uint backingStoreRecreated : 1; }; +#ifndef QT_NO_OPENGL class QPlatformTextureListWatcher : public QObject { Q_OBJECT @@ -86,6 +88,7 @@ private: bool m_locked; QWidgetBackingStore *m_backingStore; }; +#endif class Q_AUTOTEST_EXPORT QWidgetBackingStore { From f12b0f9a38c792abb13f3e6ecff4542986a6f96b Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 20 Feb 2014 22:55:22 +0100 Subject: [PATCH 065/124] QByteArrayList: optimize op+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old code creates a default-constructed QByteArrayList, then performed two list-appends, the first one of which just performs assignment. Optimize by replacing the default construction and assignment with a copy constructor call. Change-Id: I6d5bd14172798c925b05bd3602e6d1d037d90796 Reviewed-by: Lars Knoll Reviewed-by: JÄ™drzej Nowacki --- src/corelib/tools/qbytearraylist.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h index 5ce6509c28..882bc68f09 100644 --- a/src/corelib/tools/qbytearraylist.h +++ b/src/corelib/tools/qbytearraylist.h @@ -97,9 +97,8 @@ inline QByteArray QByteArrayList::join(char sep) const inline QByteArrayList operator+(const QByteArrayList &lhs, const QByteArrayList &rhs) { - QByteArrayList res; - res.append( lhs ); - res.append( rhs ); + QByteArrayList res = lhs; + res += rhs; return res; } From 6813a21c522631e5388b2cbf3f8e4e273b0d27ce Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 24 Feb 2014 14:05:58 +0100 Subject: [PATCH 066/124] Fix compilation on armv5 Two changes broke compilation on armv5, where we're currently not CI-testing: 634f82f1f1fda7983abf70b58e43c580b1f01df0 changed the signature in a function definition without changing its declaration, while it was actually intending to add this as a new overload. bfe0db6fbea6376dbe395af6d76995a54bbc3b49 added an #error condition without fixing compilation on armv5. I don't know if the fix is correct, but at least it compiles. Task-number: QTBUG-37034 Change-Id: If99142fafb9bd55afc20b17f8b3cce5ee0ffec13 Reviewed-by: Thiago Macieira --- src/corelib/arch/qatomic_armv5.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/corelib/arch/qatomic_armv5.h b/src/corelib/arch/qatomic_armv5.h index 6939650c54..253b9263de 100644 --- a/src/corelib/arch/qatomic_armv5.h +++ b/src/corelib/arch/qatomic_armv5.h @@ -54,6 +54,7 @@ QT_END_NAMESPACE #pragma qt_sync_stop_processing #endif +#define Q_ATOMIC_INT32_IS_SUPPORTED #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE #define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE @@ -98,6 +99,7 @@ template struct QBasicAtomicOps: QGenericAtomicOps static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; + template static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW; template static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW; template static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW; @@ -132,6 +134,18 @@ bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW return newValue != 0; } +template<> template inline +bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW +{ + T originalValue; + do { + originalValue = _q_value; + if (originalValue != expectedValue) + return false; + } while (_q_cmpxchg(expectedValue, newValue, &_q_value) != 0); + return true; +} + template<> template inline bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW { From 9f983eac9f926b4ea3ee4ec860f58dc33a5b7fe7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 22 Feb 2014 23:30:22 +0100 Subject: [PATCH 067/124] QJNI: optimize QSharedPointer creation Instead of QSharedPointer(new T), use QSharedPointer::create(), since the latter co-locates the refcount and the T instance in a single memory allocation, unlike the first form, which uses separate memory allocations. Change-Id: I5095ac43448aad9a7e3ec07ed4dcdca869bcd9e8 Reviewed-by: Lars Knoll Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/kernel/qjni_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h index b1f0011b94..83dd3a00af 100644 --- a/src/corelib/kernel/qjni_p.h +++ b/src/corelib/kernel/qjni_p.h @@ -177,7 +177,7 @@ public: { jobject jobj = static_cast(o); if (!isSameObject(jobj)) { - d = QSharedPointer(new QJNIObjectData()); + d = QSharedPointer::create(); if (jobj) { QJNIEnvironmentPrivate env; d->m_jobject = env->NewGlobalRef(jobj); From 989d439d93341fc8f046a5a6cefe6ed39625b908 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 20 Feb 2014 16:59:54 +0100 Subject: [PATCH 068/124] Windows: Clear transient relationship before destroying windows. Windows differs from the other platforms in that transient parent relationship is not just a window property but also implies ownership; windows will destroy their transient children in DestroyWindow(), which interferes with Qt. Explicitly clear the relationship in QWindowsWindow::destroy() to prevent this. Task-number: QTBUG-36666 Task-number: QTBUG-35499 Change-Id: I5e72524ef57422831f60484993f6c8d7c80c8601 Reviewed-by: J-P Nurmi Reviewed-by: Joerg Bornemann Reviewed-by: Oliver Wolff Reviewed-by: Shawn Rutledge --- .../platforms/windows/qwindowswindow.cpp | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 39b36a29cb..d77f587b92 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -924,11 +924,23 @@ void QWindowsWindow::fireExpose(const QRegion ®ion, bool force) QWindowSystemInterface::handleExposeEvent(window(), region); } +static inline QWindow *findTransientChild(const QWindow *parent) +{ + foreach (QWindow *w, QGuiApplication::topLevelWindows()) + if (w->transientParent() == parent) + return w; + return 0; +} + void QWindowsWindow::destroyWindow() { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << m_data.hwnd; if (m_data.hwnd) { // Stop event dispatching before Window is destroyed. setFlag(WithinDestroy); + // Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666) + if (QWindow *transientChild = findTransientChild(window())) + if (QWindowsWindow *tw = QWindowsWindow::baseWindowOf(transientChild)) + tw->updateTransientParent(); QWindowsContext *context = QWindowsContext::instance(); if (context->windowUnderMouse() == window()) context->clearWindowUnderMouse(); @@ -1102,6 +1114,18 @@ QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const return pos; } +#ifndef Q_OS_WINCE +static inline HWND transientParentHwnd(HWND hwnd) +{ + if (GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow()) { + const HWND rootOwnerHwnd = GetAncestor(hwnd, GA_ROOTOWNER); + if (rootOwnerHwnd != hwnd) // May return itself for toplevels. + return rootOwnerHwnd; + } + return 0; +} +#endif // !Q_OS_WINCE + // Update the transient parent for a toplevel window. The concept does not // really exist on Windows, the relationship is set by passing a parent along with !WS_CHILD // to window creation or by setting the parent using GWL_HWNDPARENT (as opposed to @@ -1112,12 +1136,13 @@ void QWindowsWindow::updateTransientParent() const if (window()->type() == Qt::Popup) return; // QTBUG-34503, // a popup stays on top, no parent, see also WindowCreationData::fromWindow(). // Update transient parent. - const HWND oldTransientParent = - GetAncestor(m_data.hwnd, GA_PARENT) == GetDesktopWindow() ? GetAncestor(m_data.hwnd, GA_ROOTOWNER) : HWND(0); + const HWND oldTransientParent = transientParentHwnd(m_data.hwnd); HWND newTransientParent = 0; if (const QWindow *tp = window()->transientParent()) - newTransientParent = QWindowsWindow::handleOf(tp); - if (newTransientParent && newTransientParent != oldTransientParent) + if (const QWindowsWindow *tw = QWindowsWindow::baseWindowOf(tp)) + if (!tw->testFlag(WithinDestroy)) // Prevent destruction by parent window (QTBUG-35499, QTBUG-36666) + newTransientParent = tw->handle(); + if (newTransientParent != oldTransientParent) SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, (LONG_PTR)newTransientParent); #endif // !Q_OS_WINCE } From 05ee0fcdc7c2d5902beb62d6e1de36ac5b706b24 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 25 Feb 2014 11:49:43 +0100 Subject: [PATCH 069/124] Properly migrate vao helper to dynamic GL Remove the forced bail out when isES() returns true. This is not necessary. Change-Id: I5ee21fe1e66163e2391bd11b647827b3c0a020c1 Reviewed-by: Friedemann Kleint Reviewed-by: Gunnar Sletta Reviewed-by: Sean Harmer --- src/gui/opengl/qopenglvertexarrayobject.cpp | 149 +++++++++----------- 1 file changed, 67 insertions(+), 82 deletions(-) diff --git a/src/gui/opengl/qopenglvertexarrayobject.cpp b/src/gui/opengl/qopenglvertexarrayobject.cpp index e26c6ec25a..52fd482b53 100644 --- a/src/gui/opengl/qopenglvertexarrayobject.cpp +++ b/src/gui/opengl/qopenglvertexarrayobject.cpp @@ -45,34 +45,35 @@ #include #include -#if !defined(QT_OPENGL_ES_2) #include #include -#endif QT_BEGIN_NAMESPACE +class QOpenGLFunctions_3_0; +class QOpenGLFunctions_3_2_Core; + class QVertexArrayObjectHelper { public: QVertexArrayObjectHelper(QOpenGLContext *context) { Q_ASSERT(context); -#if !defined(QT_OPENGL_ES_2) - if (context->hasExtension(QByteArrayLiteral("GL_APPLE_vertex_array_object"))) { - GenVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysAPPLE"))); - DeleteVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysAPPLE"))); - BindVertexArray = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayAPPLE"))); + if (QOpenGLFunctions::isES()) { + GenVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysOES"))); + DeleteVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysOES"))); + BindVertexArray = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayOES"))); } else { - GenVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glGenVertexArrays"))); - DeleteVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArrays"))); - BindVertexArray = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glBindVertexArray"))); + if (context->hasExtension(QByteArrayLiteral("GL_APPLE_vertex_array_object"))) { + GenVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysAPPLE"))); + DeleteVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysAPPLE"))); + BindVertexArray = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayAPPLE"))); + } else { + GenVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glGenVertexArrays"))); + DeleteVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArrays"))); + BindVertexArray = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glBindVertexArray"))); + } } -#else - GenVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glGenVertexArraysOES"))); - DeleteVertexArrays = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glDeleteVertexArraysOES"))); - BindVertexArray = reinterpret_cast(context->getProcAddress(QByteArrayLiteral("glBindVertexArrayOES"))); -#endif } inline void glGenVertexArrays(GLsizei n, GLuint *arrays) @@ -102,23 +103,15 @@ class QOpenGLVertexArrayObjectPrivate : public QObjectPrivate public: QOpenGLVertexArrayObjectPrivate() : vao(0) -#if defined(QT_OPENGL_ES_2) - , vaoFuncs(0) -#else , vaoFuncsType(NotSupported) -#endif , context(0) { } ~QOpenGLVertexArrayObjectPrivate() { -#if defined(QT_OPENGL_ES_2) - delete vaoFuncs; -#else - if ((vaoFuncsType == ARB) || (vaoFuncsType == APPLE)) + if (vaoFuncsType == ARB || vaoFuncsType == APPLE || vaoFuncsType == OES) delete vaoFuncs.helper; -#endif } bool create(); @@ -131,9 +124,6 @@ public: GLuint vao; -#if defined(QT_OPENGL_ES_2) - QVertexArrayObjectHelper *vaoFuncs; -#else union { QOpenGLFunctions_3_0 *core_3_0; QOpenGLFunctions_3_2_Core *core_3_2; @@ -144,9 +134,10 @@ public: Core_3_0, Core_3_2, ARB, - APPLE + APPLE, + OES } vaoFuncsType; -#endif + QOpenGLContext *context; }; @@ -157,13 +148,6 @@ bool QOpenGLVertexArrayObjectPrivate::create() return false; } -#if !defined(QT_OPENGL_ES_2) - if (QOpenGLFunctions::isES()) { - qWarning("QOpenGLVertexArrayObject: Not supported on dynamic GL ES"); - return false; - } -#endif - Q_Q(QOpenGLVertexArrayObject); if (context) QObject::disconnect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed())); @@ -176,35 +160,40 @@ bool QOpenGLVertexArrayObjectPrivate::create() context = ctx; QObject::connect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed())); -#if defined(QT_OPENGL_ES_2) - if (ctx->hasExtension(QByteArrayLiteral("GL_OES_vertex_array_object"))) { - vaoFuncs = new QVertexArrayObjectHelper(ctx); - vaoFuncs->glGenVertexArrays(1, &vao); - } -#else - vaoFuncs.core_3_0 = 0; - vaoFuncsType = NotSupported; - QSurfaceFormat format = ctx->format(); - if (format.version() >= qMakePair(3,2)) { - vaoFuncs.core_3_2 = ctx->versionFunctions(); - vaoFuncsType = Core_3_2; - vaoFuncs.core_3_2->initializeOpenGLFunctions(); - vaoFuncs.core_3_2->glGenVertexArrays(1, &vao); - } else if (format.majorVersion() >= 3) { - vaoFuncs.core_3_0 = ctx->versionFunctions(); - vaoFuncsType = Core_3_0; - vaoFuncs.core_3_0->initializeOpenGLFunctions(); - vaoFuncs.core_3_0->glGenVertexArrays(1, &vao); - } else if (ctx->hasExtension(QByteArrayLiteral("GL_ARB_vertex_array_object"))) { - vaoFuncs.helper = new QVertexArrayObjectHelper(ctx); - vaoFuncsType = ARB; - vaoFuncs.helper->glGenVertexArrays(1, &vao); - } else if (ctx->hasExtension(QByteArrayLiteral("GL_APPLE_vertex_array_object"))) { - vaoFuncs.helper = new QVertexArrayObjectHelper(ctx); - vaoFuncsType = APPLE; - vaoFuncs.helper->glGenVertexArrays(1, &vao); - } + if (QOpenGLFunctions::isES()) { + if (ctx->hasExtension(QByteArrayLiteral("GL_OES_vertex_array_object"))) { + vaoFuncs.helper = new QVertexArrayObjectHelper(ctx); + vaoFuncsType = OES; + vaoFuncs.helper->glGenVertexArrays(1, &vao); + } + } else { + vaoFuncs.core_3_0 = 0; + vaoFuncsType = NotSupported; + QSurfaceFormat format = ctx->format(); +#ifndef QT_OPENGL_ES_2 + if (format.version() >= qMakePair(3,2)) { + vaoFuncs.core_3_2 = ctx->versionFunctions(); + vaoFuncsType = Core_3_2; + vaoFuncs.core_3_2->initializeOpenGLFunctions(); + vaoFuncs.core_3_2->glGenVertexArrays(1, &vao); + } else if (format.majorVersion() >= 3) { + vaoFuncs.core_3_0 = ctx->versionFunctions(); + vaoFuncsType = Core_3_0; + vaoFuncs.core_3_0->initializeOpenGLFunctions(); + vaoFuncs.core_3_0->glGenVertexArrays(1, &vao); + } else #endif + if (ctx->hasExtension(QByteArrayLiteral("GL_ARB_vertex_array_object"))) { + vaoFuncs.helper = new QVertexArrayObjectHelper(ctx); + vaoFuncsType = ARB; + vaoFuncs.helper->glGenVertexArrays(1, &vao); + } else if (ctx->hasExtension(QByteArrayLiteral("GL_APPLE_vertex_array_object"))) { + vaoFuncs.helper = new QVertexArrayObjectHelper(ctx); + vaoFuncsType = APPLE; + vaoFuncs.helper->glGenVertexArrays(1, &vao); + } + } + return (vao != 0); } @@ -212,25 +201,25 @@ void QOpenGLVertexArrayObjectPrivate::destroy() { if (!vao) return; -#if defined(QT_OPENGL_ES_2) - if (vaoFuncs) - vaoFuncs->glDeleteVertexArrays(1, &vao); -#else + switch (vaoFuncsType) { +#ifndef QT_OPENGL_ES_2 case Core_3_2: vaoFuncs.core_3_2->glDeleteVertexArrays(1, &vao); break; case Core_3_0: vaoFuncs.core_3_0->glDeleteVertexArrays(1, &vao); break; +#endif case ARB: case APPLE: + case OES: vaoFuncs.helper->glDeleteVertexArrays(1, &vao); break; - case NotSupported: + default: break; } -#endif + vao = 0; } @@ -244,48 +233,44 @@ void QOpenGLVertexArrayObjectPrivate::_q_contextAboutToBeDestroyed() void QOpenGLVertexArrayObjectPrivate::bind() { -#if defined(QT_OPENGL_ES_2) - if (vaoFuncs) - vaoFuncs->glBindVertexArray(vao); -#else switch (vaoFuncsType) { +#ifndef QT_OPENGL_ES_2 case Core_3_2: vaoFuncs.core_3_2->glBindVertexArray(vao); break; case Core_3_0: vaoFuncs.core_3_0->glBindVertexArray(vao); break; +#endif case ARB: case APPLE: + case OES: vaoFuncs.helper->glBindVertexArray(vao); break; - case NotSupported: + default: break; } -#endif } void QOpenGLVertexArrayObjectPrivate::release() { -#if defined(QT_OPENGL_ES_2) - if (vaoFuncs) - vaoFuncs->glBindVertexArray(0); -#else switch (vaoFuncsType) { +#ifndef QT_OPENGL_ES_2 case Core_3_2: vaoFuncs.core_3_2->glBindVertexArray(0); break; case Core_3_0: vaoFuncs.core_3_0->glBindVertexArray(0); break; +#endif case ARB: case APPLE: + case OES: vaoFuncs.helper->glBindVertexArray(0); break; - case NotSupported: + default: break; } -#endif } From 51572d3d8f85f8836c25d1f793e69b170672cc3c Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 24 Feb 2014 16:09:23 +0100 Subject: [PATCH 070/124] QAssociative/SequentialIterable: add missing \since 5.2 Change-Id: Ia78fa0d70c85f06f48c3bbab47370e15008abe03 Reviewed-by: Jerome Pasion Reviewed-by: Stephen Kelly --- src/corelib/kernel/qvariant.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index dd9a7693ca..f7540dc20f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -3488,7 +3488,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) /*! \class QSequentialIterable - + \since 5.2 \inmodule QtCore \brief The QSequentialIterable class is an iterable interface for a container in a QVariant. @@ -3591,7 +3591,7 @@ bool QSequentialIterable::canReverseIterate() const /*! \class QSequentialIterable::const_iterator - + \since 5.2 \inmodule QtCore \brief The QSequentialIterable::const_iterator allows iteration over a container in a QVariant. @@ -3794,7 +3794,7 @@ QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operato /*! \class QAssociativeIterable - + \since 5.2 \inmodule QtCore \brief The QAssociativeIterable class is an iterable interface for an associative container in a QVariant. @@ -3899,7 +3899,7 @@ int QAssociativeIterable::size() const /*! \class QAssociativeIterable::const_iterator - + \since 5.2 \inmodule QtCore \brief The QAssociativeIterable::const_iterator allows iteration over a container in a QVariant. From f2ade01f4c0c33e070d89b473b4c0037aed9e7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 10 Dec 2013 10:02:51 +0100 Subject: [PATCH 071/124] Cocoa: QImage -> CGImage conversion cleanup Move to one qt_mac_toCGImage function that has simple semantics and properly retains a copy of the QImage for the lifetime of the CGImage. Remove the old qt_mac_toCGImage function which had two problems: 1) It would not retain the QImage data (this was probably ok for its original use case: creating short-lived CGImages for the paint engine) 2) It had acquired a somewhat odd **datacopy out parameter for the cases where you _do_ want to retain the image data. This makes the exported image conversion function from QtMacExtras work: The CGImages it creates will no longer reference free'd memory once the QImage is deleted. Change-Id: I583040d16aefb17fc3d801d6b047a0b2a76c7f74 Reviewed-by: Gabriel de Dietrich --- .../platforms/cocoa/qcocoabackingstore.mm | 2 +- src/plugins/platforms/cocoa/qcocoahelpers.h | 6 +- src/plugins/platforms/cocoa/qcocoahelpers.mm | 131 +++++------------- .../platforms/cocoa/qcocoanativeinterface.mm | 2 +- src/plugins/platforms/cocoa/qmacmime.mm | 2 +- src/plugins/platforms/cocoa/qnsview.mm | 6 +- .../platforms/cocoa/qpaintengine_mac.mm | 6 +- 7 files changed, 42 insertions(+), 113 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 30c15d823a..3ca611b537 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -122,7 +122,7 @@ bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy) CGImageRef QCocoaBackingStore::getBackingStoreCGImage() { if (!m_cgImage) - m_cgImage = qt_mac_toCGImage(m_qImage, false, 0); + m_cgImage = qt_mac_toCGImage(m_qImage); // Warning: do not retain/release/cache the returned image from // outside the backingstore since it shares data with a QImage and diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 419bf631aa..893aa4408a 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -68,10 +68,12 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list); inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist) { return reinterpret_cast(qt_mac_QStringListToNSMutableArrayVoid(qstrlist)); } -CGImageRef qt_mac_image_to_cgimage(const QImage &image); NSImage *qt_mac_cgimage_to_nsimage(CGImageRef iamge); NSImage *qt_mac_create_nsimage(const QPixmap &pm); NSImage *qt_mac_create_nsimage(const QIcon &icon); +CGImageRef qt_mac_toCGImage(const QImage &qImage); +CGImageRef qt_mac_toCGImageMask(const QImage &qImage); +QImage qt_mac_toQImage(CGImageRef image); NSSize qt_mac_toNSSize(const QSize &qtSize); NSRect qt_mac_toNSRect(const QRect &rect); @@ -159,8 +161,6 @@ public: }; CGContextRef qt_mac_cg_context(QPaintDevice *pdev); -CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy); -QImage qt_mac_toQImage(CGImageRef image); template T qt_mac_resolveOption(const T &fallback, const QByteArray &environment) diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index d27c134fa3..9b3198224e 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -79,24 +79,28 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list) return result; } -static void drawImageReleaseData (void *info, const void *, size_t) +static void qt_mac_deleteImage(void *image, const void *, size_t) { - delete static_cast(info); + delete static_cast(image); } -CGImageRef qt_mac_image_to_cgimage(const QImage &img) +// Creates a CGDataProvider with the data from the given image. +// The data provider retains a copy of the image. +CGDataProviderRef qt_mac_CGDataProvider(const QImage &image) { - if (img.isNull()) + return CGDataProviderCreateWithData(new QImage(image), image.bits(), + image.byteCount(), qt_mac_deleteImage); +} + +CGImageRef qt_mac_toCGImage(const QImage &inImage) +{ + if (inImage.isNull()) return 0; - QImage *image; - if (img.depth() != 32) - image = new QImage(img.convertToFormat(QImage::Format_ARGB32_Premultiplied)); - else - image = new QImage(img); + QImage image = (inImage.depth() == 32) ? inImage : inImage.convertToFormat(QImage::Format_ARGB32_Premultiplied); uint cgflags = kCGImageAlphaNone; - switch (image->format()) { + switch (image.format()) { case QImage::Format_ARGB32_Premultiplied: cgflags = kCGImageAlphaPremultipliedFirst; break; @@ -105,20 +109,26 @@ CGImageRef qt_mac_image_to_cgimage(const QImage &img) break; case QImage::Format_RGB32: cgflags = kCGImageAlphaNoneSkipFirst; + break; + case QImage::Format_RGB888: + cgflags |= kCGImageAlphaNone; + break; default: break; } cgflags |= kCGBitmapByteOrder32Host; - QCFType dataProvider = CGDataProviderCreateWithData(image, - static_cast(image)->bits(), - image->byteCount(), - drawImageReleaseData); - - return CGImageCreate(image->width(), image->height(), 8, 32, - image->bytesPerLine(), - qt_mac_genericColorSpace(), - cgflags, dataProvider, 0, false, kCGRenderingIntentDefault); + QCFType dataProvider = qt_mac_CGDataProvider(image); + return CGImageCreate(image.width(), image.height(), 8, 32, + image.bytesPerLine(), + qt_mac_genericColorSpace(), + cgflags, dataProvider, 0, false, kCGRenderingIntentDefault); +} +CGImageRef qt_mac_toCGImageMask(const QImage &image) +{ + QCFType dataProvider = qt_mac_CGDataProvider(image); + return CGImageMaskCreate(image.width(), image.height(), 8, image.depth(), + image.bytesPerLine(), dataProvider, NULL, false); } NSImage *qt_mac_cgimage_to_nsimage(CGImageRef image) @@ -132,7 +142,7 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm) if (pm.isNull()) return 0; QImage image = pm.toImage(); - CGImageRef cgImage = qt_mac_image_to_cgimage(image); + CGImageRef cgImage = qt_mac_toCGImage(image); NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage); CGImageRelease(cgImage); return nsImage; @@ -147,7 +157,7 @@ NSImage *qt_mac_create_nsimage(const QIcon &icon) foreach (QSize size, icon.availableSizes()) { QPixmap pm = icon.pixmap(size); QImage image = pm.toImage(); - CGImageRef cgImage = qt_mac_image_to_cgimage(image); + CGImageRef cgImage = qt_mac_toCGImage(image); NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; [nsImage addRepresentation:imageRep]; [imageRep release]; @@ -780,85 +790,6 @@ CGContextRef qt_mac_cg_context(QPaintDevice *pdev) return ret; } -// qpaintengine_mac.mm -extern void qt_mac_cgimage_data_free(void *, const void *memoryToFree, size_t); - -CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy) -{ - int width = qImage.width(); - int height = qImage.height(); - - if (width <= 0 || height <= 0) { - qWarning() << Q_FUNC_INFO << - "setting invalid size" << width << "x" << height << "for qnsview image"; - return 0; - } - - const uchar *imageData = qImage.bits(); - if (dataCopy) { - *dataCopy = static_cast(malloc(qImage.byteCount())); - memcpy(*dataCopy, imageData, qImage.byteCount()); - } - int bitDepth = qImage.depth(); - int colorBufferSize = 8; - int bytesPrLine = qImage.bytesPerLine(); - - CGDataProviderRef cgDataProviderRef = CGDataProviderCreateWithData( - NULL, - dataCopy ? *dataCopy : imageData, - qImage.byteCount(), - dataCopy ? qt_mac_cgimage_data_free : NULL); - - CGImageRef cgImage = 0; - if (isMask) { - cgImage = CGImageMaskCreate(width, - height, - colorBufferSize, - bitDepth, - bytesPrLine, - cgDataProviderRef, - NULL, - false); - } else { - CGColorSpaceRef cgColourSpaceRef = qt_mac_displayColorSpace(0); - - // Create a CGBitmapInfo contiaining the image format. - // Support the 8-bit per component (A)RGB formats. - CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little; - switch (qImage.format()) { - case QImage::Format_ARGB32_Premultiplied : - bitmapInfo |= kCGImageAlphaPremultipliedFirst; - break; - case QImage::Format_ARGB32 : - bitmapInfo |= kCGImageAlphaFirst; - break; - case QImage::Format_RGB32 : - bitmapInfo |= kCGImageAlphaNoneSkipFirst; - break; - case QImage::Format_RGB888 : - bitmapInfo |= kCGImageAlphaNone; - break; - default: - qWarning() << "qt_mac_toCGImage: Unsupported image format" << qImage.format(); - break; - } - - cgImage = CGImageCreate(width, - height, - colorBufferSize, - bitDepth, - bytesPrLine, - cgColourSpaceRef, - bitmapInfo, - cgDataProviderRef, - NULL, - false, - kCGRenderingIntentDefault); - } - CGDataProviderRelease(cgDataProviderRef); - return cgImage; -} - QImage qt_mac_toQImage(CGImageRef image) { const size_t w = CGImageGetWidth(image), diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 85ce96a8b6..f4776342de 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -248,7 +248,7 @@ void *QCocoaNativeInterface::qMenuBarToNSMenu(QPlatformMenuBar *platformMenuBar) CGImageRef QCocoaNativeInterface::qImageToCGImage(const QImage &image) { - return qt_mac_toCGImage(image, false, 0); + return qt_mac_toCGImage(image); } QImage QCocoaNativeInterface::cgImageToQImage(CGImageRef image) diff --git a/src/plugins/platforms/cocoa/qmacmime.mm b/src/plugins/platforms/cocoa/qmacmime.mm index 89d1b5f681..4274e178f7 100644 --- a/src/plugins/platforms/cocoa/qmacmime.mm +++ b/src/plugins/platforms/cocoa/qmacmime.mm @@ -565,7 +565,7 @@ QList QMacPasteboardMimeTiff::convertFromMime(const QString &mime, Q return ret; QImage img = qvariant_cast(variant); - QCFType cgimage = qt_mac_image_to_cgimage(img); + QCFType cgimage = qt_mac_toCGImage(img); QCFType data = CFDataCreateMutable(0, 0); QCFType imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0); diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 58c732de98..e246775406 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -80,7 +80,6 @@ static QTouchDevice *touchDevice = 0; if (self) { m_backingStore = 0; m_maskImage = 0; - m_maskData = 0; m_shouldInvalidateWindowShadow = false; m_window = 0; m_buttons = Qt::NoButton; @@ -106,7 +105,6 @@ static QTouchDevice *touchDevice = 0; { CGImageRelease(m_maskImage); m_maskImage = 0; - m_maskData = 0; m_window = 0; m_subscribesForGlobalFrameNotifications = false; [m_inputSource release]; @@ -372,7 +370,7 @@ static QTouchDevice *touchDevice = 0; - (BOOL) hasMask { - return m_maskData != 0; + return m_maskImage != 0; } - (BOOL) isOpaque @@ -405,7 +403,7 @@ static QTouchDevice *touchDevice = 0; dst[x] = src[x] & 0xff; } } - m_maskImage = qt_mac_toCGImage(maskImage, true, &m_maskData); + m_maskImage = qt_mac_toCGImageMask(maskImage); } - (void)invalidateWindowShadowIfNeeded diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 40d60a6a0a..61fbe3a61f 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -488,7 +488,7 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c) if (isBitmap) pat->image = qt_mac_create_imagemask(pat->data.pixmap, pat->data.pixmap.rect()); else - pat->image = qt_mac_image_to_cgimage(pat->data.pixmap.toImage()); + pat->image = qt_mac_toCGImage(pat->data.pixmap.toImage()); } } else { w = CGImageGetWidth(pat->image); @@ -963,11 +963,11 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev)); image = qt_mac_create_imagemask(pm, sr); } else if (differentSize) { - QCFType img = qt_mac_image_to_cgimage(pm.toImage()); + QCFType img = qt_mac_toCGImage(pm.toImage()); if (img) image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); } else { - image = qt_mac_image_to_cgimage(pm.toImage()); + image = qt_mac_toCGImage(pm.toImage()); } qt_mac_drawCGImage(d->hd, &rect, image); if (doRestore) From 72ba4cd3858773757d3cc5a66f7859a483b6475b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 17 Feb 2014 11:39:25 +0100 Subject: [PATCH 072/124] Cocoa: Clear GL context pointer on deletion. The QGLWidget destructor sequence is such that the GL context will be deleted before the window is hidden. This would leave QCocoaWindow with a stale m_glContext pointer. Clear QCocoaWindow's context pointer on context deletion. Task-number: QTBUG-36820 Change-Id: I710e3813f9ce90ddd37ad7b406693f0c58a1436d Reviewed-by: Gabriel de Dietrich Reviewed-by: Gunnar Sletta --- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 6f76892d93..9b4d8fd96f 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -162,6 +162,9 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo QCocoaGLContext::~QCocoaGLContext() { + if (m_currentWindow && m_currentWindow.data()->handle()) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(0); + [m_context release]; } From 2f76a30ee18b5a7938e0c7a7be0a816f139fbc7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 18 Feb 2014 07:52:32 +0100 Subject: [PATCH 073/124] Cocoa: Prevent "Invalid Drawable" GL warnings. Worst case this can cause the various OpenGL initialization functions to fail due to the lack of a valid GL context. Task-number: QTBUG-35342 Task-number: QTBUG-31451 Change-Id: I08256ad51acb5370c8c6d44b556572eadd6a9c1d Reviewed-by: Sean Harmer --- src/plugins/platforms/cocoa/qcocoawindow.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index d972782f31..07b4100d4a 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1153,6 +1153,10 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) // Child windows have no NSWindow, link the NSViews instead. [m_parentCocoaWindow->m_contentView addSubview : m_contentView]; QRect rect = window()->geometry(); + // Prevent setting a (0,0) window size; causes opengl context + // "Invalid Drawable" warnings. + if (rect.isNull()) + rect.setSize(QSize(1, 1)); NSRect frame = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); [m_contentView setFrame:frame]; [m_contentView setHidden: YES]; From 7129ec0f476f33f32760e4b7801adaae14164444 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 24 Feb 2014 09:29:41 +0100 Subject: [PATCH 074/124] Document qPrintable encoding issues Change-Id: I8936203afaa100ac4665ed668f7729fc8da1d445 Reviewed-by: Oswald Buddenhagen Reviewed-by: Jerome Pasion --- src/corelib/global/qglobal.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index fe10c493a7..0f1968d151 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2810,12 +2810,17 @@ int qrand() The char pointer will be invalid after the statement in which qPrintable() is used. This is because the array returned by - toLocal8Bit() will fall out of scope. + QString::toLocal8Bit() will fall out of scope. Example: \snippet code/src_corelib_global_qglobal.cpp 37 + \note qDebug(), qWarning(), qCritical(), qFatal() expect %s + arguments to be UTF-8 encoded, while qPrintable() converts to + local 8-bit encoding. Therefore using qPrintable for logging + strings is only safe if the argument contains only ASCII + characters. \sa qDebug(), qWarning(), qCritical(), qFatal() */ From ee55244df4747712f953c448244c68ba3e95e31c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 24 Feb 2014 11:43:13 +0100 Subject: [PATCH 075/124] Fix link to argument formats in QString::setNum documentation Also drop mentioning of 'F', which is (though supported) not mentioned in the linked section. Change-Id: I9bf763f25b8b0309c338adbf3d63d94678ecee5e Reviewed-by: Jerome Pasion --- src/corelib/tools/qstring.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index c433120f6f..116da9e383 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -6428,8 +6428,8 @@ QString &QString::setNum(qulonglong n, int base) to the given \a format and \a precision, and returns a reference to the string. - The \a format can be 'f', 'F', 'e', 'E', 'g' or 'G' (see the - arg() function documentation for an explanation of the formats). + The \a format can be 'e', 'E', 'f', 'g' or 'G' (see + \l{Argument Formats} for an explanation of the formats). The formatting always uses QLocale::C, i.e., English/UnitedStates. To get a localized string representation of a number, use From bb7bf6ca17061d835cf7980179ae0a607830048d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 28 Jan 2014 14:53:49 +0100 Subject: [PATCH 076/124] Make closeAllWindows() close real windows only. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QApplication::closeAllWindows() is documented to close all top-level windows. If the widget has WA_DontShowOnScreen set then that is a strong indication that this widget is, in fact, not a top-level window. [ChangeLog][QtWidgets][Mac] QWidgets embedded in QGraphicsProxyWidget are no longer sent close events when the app is closed. Task-number: QTBUG-33716 Change-Id: I0925ed67a2d2088ca9f950a4a43bc2729b88a86c Reviewed-by: Friedemann Kleint Reviewed-by: Morten Johan Sørvig --- src/widgets/kernel/qapplication.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 9bc1576dc6..c01b535067 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1749,7 +1749,8 @@ bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows QWidgetList list = QApplication::topLevelWidgets(); for (int i = 0; i < list.size(); ++i) { QWidget *w = list.at(i); - if (w->isVisible() && w->windowType() != Qt::Desktop && !w->data->is_closing) { + if (w->isVisible() && w->windowType() != Qt::Desktop && + !w->testAttribute(Qt::WA_DontShowOnScreen) && !w->data->is_closing) { QWindow *window = w->windowHandle(); if (!w->close()) // Qt::WA_DeleteOnClose may cause deletion. return false; From 6a7747f30cc853f07501770a8704fee215eea322 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sun, 23 Feb 2014 03:28:56 +0200 Subject: [PATCH 077/124] HarfBuzz-NG: Hide characters that should normally be invisible These are non-ambigue NLF characters that should only imply the sctructure of the document. For details, see http://www.unicode.org/reports/tr13/ . The issue could be reproduced with use of multi-line QML Text element. Change-Id: Ibb4d5cd26bc0ac6b79a4cb549e6a3cd7633bd071 Reviewed-by: Lars Knoll --- src/gui/text/qtextengine.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index eb31c520ed..63e2af8d15 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1133,6 +1133,21 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st uint cluster = infos[i].cluster; if (last_cluster != cluster) { + if (Q_UNLIKELY(g.glyphs[i] == 0)) { + // hide characters that should normally be invisible + switch (string[item_pos + str_pos]) { + case QChar::LineFeed: + case 0x000c: // FormFeed + case QChar::CarriageReturn: + case QChar::LineSeparator: + case QChar::ParagraphSeparator: + g.attributes[i].dontPrint = true; + break; + default: + break; + } + } + // fix up clusters so that the cluster indices will be monotonic // and thus we never return out-of-order indices while (last_cluster++ < cluster && str_pos < item_length) From b648195c314ab0b342e5883ba13efbdc7104fd9e Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Sat, 15 Feb 2014 11:54:53 +0800 Subject: [PATCH 078/124] Doc: Replace obsolete types with their newer counterparts This patch ignores: - Docs for obsolete types themselves - Comparisons between new and obsolete types Change-Id: Id9b1e628255113e7c44520abe0f8a4e0db4a283d Reviewed-by: Jerome Pasion --- .../widgets/doc/src/treemodelcompleter.qdoc | 2 +- src/corelib/global/qglobal.cpp | 2 +- .../itemmodels/qsortfilterproxymodel.cpp | 20 +++++++------- src/corelib/json/qjsondocument.cpp | 4 +-- src/corelib/json/qjsonvalue.cpp | 26 +++++++++---------- src/corelib/kernel/qvariant.cpp | 8 +++--- src/widgets/dialogs/qfilesystemmodel.cpp | 2 +- src/widgets/doc/src/modelview.qdoc | 2 +- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/examples/widgets/doc/src/treemodelcompleter.qdoc b/examples/widgets/doc/src/treemodelcompleter.qdoc index 9411371d12..82ed9a3e79 100644 --- a/examples/widgets/doc/src/treemodelcompleter.qdoc +++ b/examples/widgets/doc/src/treemodelcompleter.qdoc @@ -83,7 +83,7 @@ \snippet tools/treemodelcompleter/treemodelcompleter.cpp 2 As mentioned earlier, the \c splitPath() function is reimplemented because - the default implementation is more suited to QDirModel or list models. In + the default implementation is more suited to QFileSystemModel or list models. In order for QCompleter to split the path into a list of strings that are matched at each level, we split it using QString::split() with \c sep as its separator. diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 0f1968d151..710f7e8ba1 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -743,7 +743,7 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); \relates This enum describes the messages that can be sent to a message - handler (QtMsgHandler). You can use the enum to identify and + handler (QtMessageHandler). You can use the enum to identify and associate the various message types with the appropriate actions. diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index ebc97ca2d9..1e377abf3e 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -2606,16 +2606,16 @@ void QSortFilterProxyModel::invalidateFilter() the following QVariant types: \list - \li QVariant::Int - \li QVariant::UInt - \li QVariant::LongLong - \li QVariant::ULongLong - \li QVariant::Double - \li QVariant::Char - \li QVariant::Date - \li QVariant::Time - \li QVariant::DateTime - \li QVariant::String + \li QMetaType::Int + \li QMetaType::UInt + \li QMetaType::LongLong + \li QMetaType::ULongLong + \li QMetaType::Double + \li QMetaType::QChar + \li QMetaType::QDate + \li QMetaType::QTime + \li QMetaType::QDateTime + \li QMetaType::QString \endlist Any other type will be converted to a QString using diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp index 6e257df39d..90ce8c63a5 100644 --- a/src/corelib/json/qjsondocument.cpp +++ b/src/corelib/json/qjsondocument.cpp @@ -260,8 +260,8 @@ QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidati /*! Creates a QJsonDocument from the QVariant \a variant. - If the \a variant contains any other type than a QVariant::Map, - QVariant::List or QVariant::StringList, the returned document + If the \a variant contains any other type than a QVariantMap, + QVariantList or QStringList, the returned document document is invalid. \sa toVariant() diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp index c16824ebd2..487a431b8f 100644 --- a/src/corelib/json/qjsonvalue.cpp +++ b/src/corelib/json/qjsonvalue.cpp @@ -344,16 +344,16 @@ QJsonValue &QJsonValue::operator =(const QJsonValue &other) The conversion will convert QVariant types as follows: \list - \li QVariant::Bool to Bool - \li QVariant::Int - \li QVariant::Double - \li QVariant::LongLong - \li QVariant::ULongLong - \li QVariant::UInt to Double - \li QVariant::String to String - \li QVariant::StringList - \li QVariant::VariantList to Array - \li QVariant::VariantMap to Object + \li QMetaType::Bool to Bool + \li QMetaType::Int + \li QMetaType::Double + \li QMetaType::LongLong + \li QMetaType::ULongLong + \li QMetaType::UInt to Double + \li QMetaType::QString to String + \li QMetaType::QStringList + \li QMetaType::QVariantList to Array + \li QMetaType::QVariantMap to Object \endlist For all other QVariant types a conversion to a QString will be attempted. If the returned string @@ -395,9 +395,9 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant) The QJsonValue types will be converted as follows: \value Null QVariant() - \value Bool QVariant::Bool - \value Double QVariant::Double - \value String QVariant::String + \value Bool QMetaType::Bool + \value Double QMetaType::Double + \value String QString \value Array QVariantList \value Object QVariantMap \value Undefined QVariant() diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f7540dc20f..5e8f330a92 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1165,7 +1165,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names instead to construct variants from the pointer types represented by \c QMetaType::VoidStar, and \c QMetaType::QObjectStar. - \sa QVariant::fromValue(), Type + \sa QVariant::fromValue(), QMetaType::Type */ /*! @@ -1765,7 +1765,7 @@ const char *QVariant::typeName() const } /*! - Convert this variant to type Invalid and free up any resources + Convert this variant to type QMetaType::UnknownType and free up any resources used. */ void QVariant::clear() @@ -1781,7 +1781,7 @@ void QVariant::clear() Converts the int representation of the storage type, \a typeId, to its string representation. - Returns a null pointer if the type is QVariant::Invalid or doesn't exist. + Returns a null pointer if the type is QMetaType::UnknownType or doesn't exist. */ const char *QVariant::typeToName(int typeId) { @@ -2019,7 +2019,7 @@ QDataStream& operator<<(QDataStream &s, const QVariant::Type p) \fn bool QVariant::isValid() const Returns \c true if the storage type of this variant is not - QVariant::Invalid; otherwise returns \c false. + QMetaType::UnknownType; otherwise returns \c false. */ template diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 0b0f686564..c31a674cc7 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -107,7 +107,7 @@ QT_BEGIN_NAMESPACE \snippet shareddirmodel/main.cpp 7 The view's root index can be used to control how much of a - hierarchical model is displayed. QDirModel provides a convenience + hierarchical model is displayed. QFileSystemModel provides a convenience function that returns a suitable model index for a path to a directory within the model. diff --git a/src/widgets/doc/src/modelview.qdoc b/src/widgets/doc/src/modelview.qdoc index f094a58a91..3b33e21ec2 100644 --- a/src/widgets/doc/src/modelview.qdoc +++ b/src/widgets/doc/src/modelview.qdoc @@ -816,7 +816,7 @@ \row \li Dir View \li QTreeView - \li QDirModel + \li QFileSystemModel \li Very small example to demonstrate how to assign a model to a view \row \li Editable Tree Model From 71e9d8bd4b0c5d241fcc3de5e9272a35e7874be0 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 13 Feb 2014 13:43:54 +0100 Subject: [PATCH 079/124] fix Windows RT build in amd64 host shell When running a amd64 VS shell we must not call the x86_amd64 cross-compiler, because it won't be able to start. Instead we're calling the native amd64 compiler now. Change-Id: I6968cde3b24c1938b6e0d82f513e49724455f3cc Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- qmake/generators/win32/msvc_nmake.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 24465ad152..b588e68e83 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -121,7 +121,11 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) compiler = QStringLiteral("x86_arm"); compilerArch = QStringLiteral("arm"); } else if (arch == QStringLiteral("x64")) { - compiler = QStringLiteral("x86_amd64"); + const ProStringList hostArch = project->values("QMAKE_TARGET.arch"); + if (hostArch.contains("x86_64")) + compiler = QStringLiteral("amd64"); + else + compiler = QStringLiteral("x86_amd64"); compilerArch = QStringLiteral("amd64"); } else { arch = QStringLiteral("x86"); From 699ba50744395f9eb9f241aa1a96c91c3ea0bc54 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Mon, 17 Feb 2014 17:17:10 +0100 Subject: [PATCH 080/124] QtNetwork tests: Remove DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 Change-Id: If1cc5fafddc41ed19dd818caf294c69cd4969216 Reviewed-by: Richard J. Moore --- .../access/qabstractnetworkcache/qabstractnetworkcache.pro | 1 - tests/auto/network/access/qftp/qftp.pro | 1 - .../access/qhttpnetworkconnection/qhttpnetworkconnection.pro | 1 - .../auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro | 1 - .../access/qnetworkaccessmanager/qnetworkaccessmanager.pro | 1 - .../access/qnetworkcachemetadata/qnetworkcachemetadata.pro | 1 - tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro | 1 - .../auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro | 1 - .../auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro | 1 - tests/auto/network/access/qnetworkreply/echo/echo.pro | 1 - tests/auto/network/access/qnetworkreply/test/test.pro | 1 - tests/auto/network/access/qnetworkrequest/qnetworkrequest.pro | 1 - .../bearer/qnetworkconfiguration/qnetworkconfiguration.pro | 1 - .../qnetworkconfigurationmanager.pro | 1 - tests/auto/network/bearer/qnetworksession/lackey/lackey.pro | 1 - tests/auto/network/bearer/qnetworksession/test/test.pro | 1 - tests/auto/network/kernel/qauthenticator/qauthenticator.pro | 1 - tests/auto/network/kernel/qdnslookup/qdnslookup.pro | 1 - .../network/kernel/qdnslookup_appless/qdnslookup_appless.pro | 1 - tests/auto/network/kernel/qhostaddress/qhostaddress.pro | 1 - tests/auto/network/kernel/qhostinfo/qhostinfo.pro | 1 - .../network/kernel/qnetworkaddressentry/qnetworkaddressentry.pro | 1 - .../auto/network/kernel/qnetworkinterface/qnetworkinterface.pro | 1 - tests/auto/network/kernel/qnetworkproxy/qnetworkproxy.pro | 1 - .../network/kernel/qnetworkproxyfactory/qnetworkproxyfactory.pro | 1 - .../network/socket/platformsocketengine/platformsocketengine.pro | 1 - tests/auto/network/socket/qabstractsocket/qabstractsocket.pro | 1 - .../auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro | 1 - tests/auto/network/socket/qlocalsocket/test/test.pro | 1 - .../network/socket/qsocks5socketengine/qsocks5socketengine.pro | 1 - .../network/socket/qtcpserver/crashingServer/crashingServer.pro | 1 - tests/auto/network/socket/qtcpserver/test/test.pro | 1 - tests/auto/network/socket/qtcpsocket/stressTest/stressTest.pro | 1 - tests/auto/network/socket/qtcpsocket/test/test.pro | 1 - .../auto/network/socket/qudpsocket/clientserver/clientserver.pro | 1 - tests/auto/network/socket/qudpsocket/test/test.pro | 1 - tests/auto/network/socket/qudpsocket/udpServer/udpServer.pro | 1 - tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro | 1 - tests/auto/network/ssl/qsslcipher/qsslcipher.pro | 1 - tests/auto/network/ssl/qsslerror/qsslerror.pro | 1 - tests/auto/network/ssl/qsslkey/qsslkey.pro | 1 - tests/auto/network/ssl/qsslsocket/qsslsocket.pro | 1 - .../qsslsocket_onDemandCertificates_member.pro | 1 - .../qsslsocket_onDemandCertificates_static.pro | 1 - 44 files changed, 44 deletions(-) diff --git a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro index 2b5ffab088..4772af9af9 100644 --- a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro +++ b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro @@ -6,4 +6,3 @@ SOURCES += tst_qabstractnetworkcache.cpp TESTDATA += tests/* -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qftp/qftp.pro b/tests/auto/network/access/qftp/qftp.pro index 917cd10837..c56dfa2b6e 100644 --- a/tests/auto/network/access/qftp/qftp.pro +++ b/tests/auto/network/access/qftp/qftp.pro @@ -15,4 +15,3 @@ wince*: { } CONFIG+=insignificant_test # QTBUG-15111: uses live qt-test-server, inherently unstable -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro index 5f5966e90d..fa19fa7ac9 100644 --- a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro +++ b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro @@ -5,4 +5,3 @@ SOURCES += tst_qhttpnetworkconnection.cpp requires(contains(QT_CONFIG,private_tests)) QT = core-private network-private testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro b/tests/auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro index 2eb0944e44..f5dbc7f010 100644 --- a/tests/auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro +++ b/tests/auto/network/access/qhttpnetworkreply/qhttpnetworkreply.pro @@ -5,4 +5,3 @@ SOURCES += tst_qhttpnetworkreply.cpp requires(contains(QT_CONFIG,private_tests)) QT = core-private network-private testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qnetworkaccessmanager/qnetworkaccessmanager.pro b/tests/auto/network/access/qnetworkaccessmanager/qnetworkaccessmanager.pro index e6354d0479..8b3de90f54 100644 --- a/tests/auto/network/access/qnetworkaccessmanager/qnetworkaccessmanager.pro +++ b/tests/auto/network/access/qnetworkaccessmanager/qnetworkaccessmanager.pro @@ -3,4 +3,3 @@ CONFIG += parallel_test TARGET = tst_qnetworkaccessmanager SOURCES += tst_qnetworkaccessmanager.cpp QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qnetworkcachemetadata/qnetworkcachemetadata.pro b/tests/auto/network/access/qnetworkcachemetadata/qnetworkcachemetadata.pro index 7342252963..d308c286fb 100644 --- a/tests/auto/network/access/qnetworkcachemetadata/qnetworkcachemetadata.pro +++ b/tests/auto/network/access/qnetworkcachemetadata/qnetworkcachemetadata.pro @@ -3,4 +3,3 @@ CONFIG += parallel_test TARGET = tst_qnetworkcachemetadata QT = core network testlib SOURCES += tst_qnetworkcachemetadata.cpp -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro b/tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro index edbc972011..ba3ece8576 100644 --- a/tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro +++ b/tests/auto/network/access/qnetworkcookie/qnetworkcookie.pro @@ -4,4 +4,3 @@ TARGET = tst_qnetworkcookie SOURCES += tst_qnetworkcookie.cpp QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro b/tests/auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro index 2fc1485a50..bb39f83af6 100644 --- a/tests/auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro +++ b/tests/auto/network/access/qnetworkcookiejar/qnetworkcookiejar.pro @@ -4,4 +4,3 @@ TARGET = tst_qnetworkcookiejar SOURCES += tst_qnetworkcookiejar.cpp QT = core core-private network network-private testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro b/tests/auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro index 57f9c0534a..7e26abbe08 100644 --- a/tests/auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro +++ b/tests/auto/network/access/qnetworkdiskcache/qnetworkdiskcache.pro @@ -3,4 +3,3 @@ CONFIG += parallel_test TARGET = tst_qnetworkdiskcache QT = core network testlib SOURCES += tst_qnetworkdiskcache.cpp -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qnetworkreply/echo/echo.pro b/tests/auto/network/access/qnetworkreply/echo/echo.pro index d634c677c6..1f05fd9a54 100644 --- a/tests/auto/network/access/qnetworkreply/echo/echo.pro +++ b/tests/auto/network/access/qnetworkreply/echo/echo.pro @@ -2,4 +2,3 @@ SOURCES += main.cpp QT = core CONFIG -= app_bundle debug_and_release_target CONFIG += console -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qnetworkreply/test/test.pro b/tests/auto/network/access/qnetworkreply/test/test.pro index cc58843eef..b683f620df 100644 --- a/tests/auto/network/access/qnetworkreply/test/test.pro +++ b/tests/auto/network/access/qnetworkreply/test/test.pro @@ -14,4 +14,3 @@ contains(QT_CONFIG,xcb): CONFIG+=insignificant_test # unstable, QTBUG-21102 win32:CONFIG += insignificant_test # QTBUG-24226 TEST_HELPER_INSTALLS = ../echo/echo -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/access/qnetworkrequest/qnetworkrequest.pro b/tests/auto/network/access/qnetworkrequest/qnetworkrequest.pro index bbcb9226aa..0470d96b8c 100644 --- a/tests/auto/network/access/qnetworkrequest/qnetworkrequest.pro +++ b/tests/auto/network/access/qnetworkrequest/qnetworkrequest.pro @@ -4,4 +4,3 @@ TARGET = tst_qnetworkrequest SOURCES += tst_qnetworkrequest.cpp QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/bearer/qnetworkconfiguration/qnetworkconfiguration.pro b/tests/auto/network/bearer/qnetworkconfiguration/qnetworkconfiguration.pro index 8c1e111873..cde82a4fb2 100644 --- a/tests/auto/network/bearer/qnetworkconfiguration/qnetworkconfiguration.pro +++ b/tests/auto/network/bearer/qnetworkconfiguration/qnetworkconfiguration.pro @@ -4,4 +4,3 @@ SOURCES += tst_qnetworkconfiguration.cpp HEADERS += ../qbearertestcommon.h QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/bearer/qnetworkconfigurationmanager/qnetworkconfigurationmanager.pro b/tests/auto/network/bearer/qnetworkconfigurationmanager/qnetworkconfigurationmanager.pro index 1a1220763c..52cee1f64d 100644 --- a/tests/auto/network/bearer/qnetworkconfigurationmanager/qnetworkconfigurationmanager.pro +++ b/tests/auto/network/bearer/qnetworkconfigurationmanager/qnetworkconfigurationmanager.pro @@ -4,4 +4,3 @@ SOURCES += tst_qnetworkconfigurationmanager.cpp HEADERS += ../qbearertestcommon.h QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/bearer/qnetworksession/lackey/lackey.pro b/tests/auto/network/bearer/qnetworksession/lackey/lackey.pro index 9f2e82d4cc..1605b31d94 100644 --- a/tests/auto/network/bearer/qnetworksession/lackey/lackey.pro +++ b/tests/auto/network/bearer/qnetworksession/lackey/lackey.pro @@ -7,4 +7,3 @@ DESTDIR = ./ win32:CONFIG += console mac:CONFIG -= app_bundle -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/bearer/qnetworksession/test/test.pro b/tests/auto/network/bearer/qnetworksession/test/test.pro index 574d0672b6..dd7618b4ad 100644 --- a/tests/auto/network/bearer/qnetworksession/test/test.pro +++ b/tests/auto/network/bearer/qnetworksession/test/test.pro @@ -16,4 +16,3 @@ CONFIG(debug_and_release) { } TEST_HELPER_INSTALLS = ../lackey/lackey -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qauthenticator/qauthenticator.pro b/tests/auto/network/kernel/qauthenticator/qauthenticator.pro index 54ec0e4cff..5e4759b690 100644 --- a/tests/auto/network/kernel/qauthenticator/qauthenticator.pro +++ b/tests/auto/network/kernel/qauthenticator/qauthenticator.pro @@ -4,4 +4,3 @@ requires(contains(QT_CONFIG,private_tests)) QT = core network-private testlib SOURCES += tst_qauthenticator.cpp DEFINES += SRCDIR=\\\"$$PWD/\\\" -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qdnslookup/qdnslookup.pro b/tests/auto/network/kernel/qdnslookup/qdnslookup.pro index 36727a3bf6..3727736fad 100644 --- a/tests/auto/network/kernel/qdnslookup/qdnslookup.pro +++ b/tests/auto/network/kernel/qdnslookup/qdnslookup.pro @@ -6,4 +6,3 @@ TARGET = tst_qdnslookup SOURCES += tst_qdnslookup.cpp QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qdnslookup_appless/qdnslookup_appless.pro b/tests/auto/network/kernel/qdnslookup_appless/qdnslookup_appless.pro index 4a97b89d9a..0515bbad3b 100644 --- a/tests/auto/network/kernel/qdnslookup_appless/qdnslookup_appless.pro +++ b/tests/auto/network/kernel/qdnslookup_appless/qdnslookup_appless.pro @@ -6,4 +6,3 @@ TARGET = tst_qdnslookup_appless SOURCES += tst_qdnslookup_appless.cpp QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro index 318c78531b..421685d855 100644 --- a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro +++ b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro @@ -13,4 +13,3 @@ wince*: { LIBS += -lws2_32 } } -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro index 3b217f6e7b..a95a6bc2d6 100644 --- a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro +++ b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro @@ -16,4 +16,3 @@ wince*: { mingw:DEFINES += _WIN32_WINNT=0x0501 linux-*:CONFIG+=insignificant_test # QTBUG-23837 - test is unstable -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qnetworkaddressentry/qnetworkaddressentry.pro b/tests/auto/network/kernel/qnetworkaddressentry/qnetworkaddressentry.pro index 864d945064..ae207e9c79 100644 --- a/tests/auto/network/kernel/qnetworkaddressentry/qnetworkaddressentry.pro +++ b/tests/auto/network/kernel/qnetworkaddressentry/qnetworkaddressentry.pro @@ -4,4 +4,3 @@ TARGET = tst_qnetworkaddressentry SOURCES += tst_qnetworkaddressentry.cpp QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qnetworkinterface/qnetworkinterface.pro b/tests/auto/network/kernel/qnetworkinterface/qnetworkinterface.pro index 3b59690580..79279514d1 100644 --- a/tests/auto/network/kernel/qnetworkinterface/qnetworkinterface.pro +++ b/tests/auto/network/kernel/qnetworkinterface/qnetworkinterface.pro @@ -4,4 +4,3 @@ TARGET = tst_qnetworkinterface SOURCES += tst_qnetworkinterface.cpp QT = core network testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qnetworkproxy/qnetworkproxy.pro b/tests/auto/network/kernel/qnetworkproxy/qnetworkproxy.pro index daf3e5dead..996f9e3691 100644 --- a/tests/auto/network/kernel/qnetworkproxy/qnetworkproxy.pro +++ b/tests/auto/network/kernel/qnetworkproxy/qnetworkproxy.pro @@ -7,4 +7,3 @@ TARGET = tst_qnetworkproxy QT = core network testlib SOURCES += tst_qnetworkproxy.cpp -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/kernel/qnetworkproxyfactory/qnetworkproxyfactory.pro b/tests/auto/network/kernel/qnetworkproxyfactory/qnetworkproxyfactory.pro index 1afb5de603..c63c7742a1 100644 --- a/tests/auto/network/kernel/qnetworkproxyfactory/qnetworkproxyfactory.pro +++ b/tests/auto/network/kernel/qnetworkproxyfactory/qnetworkproxyfactory.pro @@ -8,4 +8,3 @@ TARGET = tst_qnetworkproxyfactory QT = core network testlib SOURCES += tst_qnetworkproxyfactory.cpp -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pro b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pro index 8da6ad9a67..eee762037d 100644 --- a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pro +++ b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pro @@ -9,4 +9,3 @@ requires(contains(QT_CONFIG,private_tests)) MOC_DIR=tmp QT = core-private network-private testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qabstractsocket/qabstractsocket.pro b/tests/auto/network/socket/qabstractsocket/qabstractsocket.pro index 970a3ffe60..00e604972f 100644 --- a/tests/auto/network/socket/qabstractsocket/qabstractsocket.pro +++ b/tests/auto/network/socket/qabstractsocket/qabstractsocket.pro @@ -8,4 +8,3 @@ QT = core network testlib SOURCES += tst_qabstractsocket.cpp -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro index 009d151e29..12ce576e23 100644 --- a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro +++ b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro @@ -10,4 +10,3 @@ MOC_DIR=tmp requires(contains(QT_CONFIG,private_tests)) QT = core-private network-private testlib -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qlocalsocket/test/test.pro b/tests/auto/network/socket/qlocalsocket/test/test.pro index c870304549..6a5df7f9b6 100644 --- a/tests/auto/network/socket/qlocalsocket/test/test.pro +++ b/tests/auto/network/socket/qlocalsocket/test/test.pro @@ -25,4 +25,3 @@ CONFIG(debug_and_release) { DESTDIR = .. } -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro b/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro index c741c78980..c9793952ce 100644 --- a/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro +++ b/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro @@ -13,4 +13,3 @@ QT = core-private network-private testlib linux-*:system(". /etc/lsb-release && [ $DISTRIB_CODENAME = oneiric ]"):DEFINES+=UBUNTU_ONEIRIC # QTBUG-23380 requires(contains(QT_CONFIG,private_tests)) -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qtcpserver/crashingServer/crashingServer.pro b/tests/auto/network/socket/qtcpserver/crashingServer/crashingServer.pro index 23b36ddade..487b9014d0 100644 --- a/tests/auto/network/socket/qtcpserver/crashingServer/crashingServer.pro +++ b/tests/auto/network/socket/qtcpserver/crashingServer/crashingServer.pro @@ -6,4 +6,3 @@ DESTDIR = ./ # This means the auto test works on some machines for MinGW. No dialog stalls # the application. mingw:CONFIG += console -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qtcpserver/test/test.pro b/tests/auto/network/socket/qtcpserver/test/test.pro index 1cc9f66de4..4daa9963ce 100644 --- a/tests/auto/network/socket/qtcpserver/test/test.pro +++ b/tests/auto/network/socket/qtcpserver/test/test.pro @@ -25,4 +25,3 @@ win32 { QT = core network testlib MOC_DIR=tmp -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qtcpsocket/stressTest/stressTest.pro b/tests/auto/network/socket/qtcpsocket/stressTest/stressTest.pro index c290fb8aa3..2eb00593e0 100644 --- a/tests/auto/network/socket/qtcpsocket/stressTest/stressTest.pro +++ b/tests/auto/network/socket/qtcpsocket/stressTest/stressTest.pro @@ -7,4 +7,3 @@ CONFIG += console DESTDIR = ./ MOC_DIR = .moc/ TMP_DIR = .tmp/ -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qtcpsocket/test/test.pro b/tests/auto/network/socket/qtcpsocket/test/test.pro index bc34adf349..6c6697bfdc 100644 --- a/tests/auto/network/socket/qtcpsocket/test/test.pro +++ b/tests/auto/network/socket/qtcpsocket/test/test.pro @@ -21,4 +21,3 @@ win32 { } else { DESTDIR = ../ } -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qudpsocket/clientserver/clientserver.pro b/tests/auto/network/socket/qudpsocket/clientserver/clientserver.pro index b8522f970e..a1b0021232 100644 --- a/tests/auto/network/socket/qudpsocket/clientserver/clientserver.pro +++ b/tests/auto/network/socket/qudpsocket/clientserver/clientserver.pro @@ -4,4 +4,3 @@ CONFIG += console CONFIG -= app_bundle TARGET = clientserver DESTDIR = ./ -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qudpsocket/test/test.pro b/tests/auto/network/socket/qudpsocket/test/test.pro index ec249b4840..8ad16c652d 100644 --- a/tests/auto/network/socket/qudpsocket/test/test.pro +++ b/tests/auto/network/socket/qudpsocket/test/test.pro @@ -24,4 +24,3 @@ wince* { TARGET = tst_qudpsocket CONFIG+=insignificant_test # QTBUG-25367, QTBUG-25368 -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/socket/qudpsocket/udpServer/udpServer.pro b/tests/auto/network/socket/qudpsocket/udpServer/udpServer.pro index 9532401e0b..cf707aa14a 100644 --- a/tests/auto/network/socket/qudpsocket/udpServer/udpServer.pro +++ b/tests/auto/network/socket/qudpsocket/udpServer/udpServer.pro @@ -3,4 +3,3 @@ QT = core network CONFIG -= app_bundle CONFIG += console -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro index 2a1f6ef299..09cb22defe 100644 --- a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro +++ b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro @@ -8,4 +8,3 @@ QT = core network testlib TARGET = tst_qsslcertificate TESTDATA += certificates/* more-certificates/* verify-certs/* -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/ssl/qsslcipher/qsslcipher.pro b/tests/auto/network/ssl/qsslcipher/qsslcipher.pro index 07907d3b76..a091bd0184 100644 --- a/tests/auto/network/ssl/qsslcipher/qsslcipher.pro +++ b/tests/auto/network/ssl/qsslcipher/qsslcipher.pro @@ -14,4 +14,3 @@ win32 { DESTDIR = release } } -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/ssl/qsslerror/qsslerror.pro b/tests/auto/network/ssl/qsslerror/qsslerror.pro index 9708ed0703..85a5046923 100644 --- a/tests/auto/network/ssl/qsslerror/qsslerror.pro +++ b/tests/auto/network/ssl/qsslerror/qsslerror.pro @@ -14,4 +14,3 @@ win32 { DESTDIR = release } } -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/ssl/qsslkey/qsslkey.pro b/tests/auto/network/ssl/qsslkey/qsslkey.pro index 37796bf5b7..78cfb9ce92 100644 --- a/tests/auto/network/ssl/qsslkey/qsslkey.pro +++ b/tests/auto/network/ssl/qsslkey/qsslkey.pro @@ -8,4 +8,3 @@ QT = core network testlib TARGET = tst_qsslkey TESTDATA += keys/* rsa-without-passphrase.pem rsa-with-passphrase.pem -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro index d8a6b2cdcb..6e34b23f6c 100644 --- a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro +++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro @@ -33,4 +33,3 @@ wince* { linux-*:system(". /etc/lsb-release && [ $DISTRIB_CODENAME = oneiric ]"):DEFINES+=UBUNTU_ONEIRIC # QTBUG-24234 requires(contains(QT_CONFIG,private_tests)) -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro index e8247d7b16..9b12785081 100644 --- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro +++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro @@ -23,4 +23,3 @@ wince* { } requires(contains(QT_CONFIG,private_tests)) -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro index 8a95e11780..c4d56436d0 100644 --- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro +++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro @@ -22,4 +22,3 @@ wince* { } requires(contains(QT_CONFIG,private_tests)) -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 From 5e39b7ad1ef76ab04d6997017b07efb4169cf018 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Fri, 21 Feb 2014 14:12:45 +0100 Subject: [PATCH 081/124] tst_spdy: Check network test server There is no need to even try to run the tests if the network test server is not present. Add a validation in initTestCase() since all test functions depend on the network test server. Change-Id: I8eca376a718ab5b6e1cc2c57f2e045dd0b58f52b Reviewed-by: Richard J. Moore --- tests/auto/network/access/spdy/tst_spdy.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/auto/network/access/spdy/tst_spdy.cpp b/tests/auto/network/access/spdy/tst_spdy.cpp index d2a220bad4..15c0831590 100644 --- a/tests/auto/network/access/spdy/tst_spdy.cpp +++ b/tests/auto/network/access/spdy/tst_spdy.cpp @@ -64,6 +64,7 @@ public: ~tst_Spdy(); private Q_SLOTS: + void initTestCase(); void settingsAndNegotiation_data(); void settingsAndNegotiation(); void download_data(); @@ -103,6 +104,11 @@ tst_Spdy::~tst_Spdy() { } +void tst_Spdy::initTestCase() +{ + QVERIFY(QtNetworkSettings::verifyTestNetworkSettings()); +} + void tst_Spdy::settingsAndNegotiation_data() { QTest::addColumn("url"); From 32794abe722161e1224920865c77c37d74ab977b Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 24 Feb 2014 17:09:24 +0100 Subject: [PATCH 082/124] network: fix doc typo in QNetworkConfigurationManager Change-Id: I6d3e7e4fb62dfc13f3cc156138604cabea119b75 Reviewed-by: Richard J. Moore --- src/network/bearer/qnetworkconfigmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index dc36443718..855ab4e485 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -132,7 +132,7 @@ QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate() Some configuration updates may require some time to perform updates. A WLAN scan is such an example. Unless the platform performs internal updates it may be required to manually trigger configuration updates via QNetworkConfigurationManager::updateConfigurations(). - The completion of the update process is indicted by emitting the updateCompleted() + The completion of the update process is indicated by emitting the updateCompleted() signal. The update process ensures that every existing QNetworkConfiguration instance is updated. There is no need to ask for a renewed configuration list via allConfigurations(). From a0ebaca9cbffe11d9854d65157c9c2486451e298 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 25 Feb 2014 09:27:35 +0100 Subject: [PATCH 083/124] Windows file dialogs: Use FOS_NOREADONLYRETURN only for mode AcceptSave. Task-number: QTBUG-36886 Change-Id: I727abb92675187f15d1357b1df60f2fb609dc4d5 Reviewed-by: Andy Shaw Reviewed-by: Shawn Rutledge --- .../platforms/windows/qwindowsdialoghelpers.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 7307d52cf9..b6ff3dc3ce 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -880,7 +880,7 @@ public: inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data); virtual void setWindowTitle(const QString &title); - inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::FileDialogOptions options); + inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options); inline void setDirectory(const QString &directory); inline void updateDirectory() { setDirectory(m_data.directory().toLocalFile()); } inline QString directory() const; @@ -1037,14 +1037,17 @@ void QWindowsNativeFileDialogBase::doExec(HWND owner) } } -void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::FileDialogOptions options) +void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode, + QFileDialogOptions::AcceptMode acceptMode, + QFileDialogOptions::FileDialogOptions options) { DWORD flags = FOS_PATHMUSTEXIST | FOS_FORCESHOWHIDDEN; if (options & QFileDialogOptions::DontResolveSymlinks) flags |= FOS_NODEREFERENCELINKS; switch (mode) { case QFileDialogOptions::AnyFile: - flags |= FOS_NOREADONLYRETURN; + if (acceptMode == QFileDialogOptions::AcceptSave) + flags |= FOS_NOREADONLYRETURN; if (!(options & QFileDialogOptions::DontConfirmOverwrite)) flags |= FOS_OVERWRITEPROMPT; break; @@ -1059,8 +1062,9 @@ void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode, QF flags |= FOS_FILEMUSTEXIST | FOS_ALLOWMULTISELECT; break; } - qCDebug(lcQpaDialogs) << __FUNCTION__ << " mode=" << mode << " options" - << options << " results in 0x" << flags; + qCDebug(lcQpaDialogs) << __FUNCTION__ << "mode=" << mode + << "acceptMode=" << acceptMode << "options=" << options + << "results in" << showbase << hex << flags; if (FAILED(m_fileDialog->SetOptions(flags))) qErrnoWarning("%s: SetOptions() failed", __FUNCTION__); @@ -1592,7 +1596,7 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog() m_data.fromOptions(opts); const QFileDialogOptions::FileMode mode = opts->fileMode(); result->setWindowTitle(opts->windowTitle()); - result->setMode(mode, opts->options()); + result->setMode(mode, opts->acceptMode(), opts->options()); result->setHideFiltersDetails(opts->testOption(QFileDialogOptions::HideNameFilterDetails)); const QStringList nameFilters = opts->nameFilters(); if (!nameFilters.isEmpty()) From e1fd82981c0b35d7aef3ceab66af1a712d1bc226 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 21 Feb 2014 11:31:18 +0100 Subject: [PATCH 084/124] Revert "Fix application font removal when using FontConfig" This reverts commit a4ff400e25c76a32ec8252285dda043f07b19c15. The patch caused a regression for bold fonts which is currently blocking the alpha of Qt 5.3, so lets revert it and try resubmitting a fixed version later to avoid delaying any release. Task-number: QTBUG-36929 Change-Id: I8d474b09b2270eb2f861853e60605429be08e2d9 Reviewed-by: Lars Knoll Reviewed-by: Konstantin Ritt --- .../fontconfig/qfontconfigdatabase.cpp | 240 ++++++++---------- .../auto/gui/text/qfontdatabase/FreeMono.ttf | Bin 0 -> 267400 bytes .../auto/gui/text/qfontdatabase/LED_REAL.TTF | Bin 4708 -> 0 bytes .../text/qfontdatabase/LED_REAL_readme.txt | 34 --- .../text/qfontdatabase/tst_qfontdatabase.cpp | 2 +- 5 files changed, 113 insertions(+), 163 deletions(-) create mode 100644 tests/auto/gui/text/qfontdatabase/FreeMono.ttf delete mode 100644 tests/auto/gui/text/qfontdatabase/LED_REAL.TTF delete mode 100644 tests/auto/gui/text/qfontdatabase/LED_REAL_readme.txt diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 8b16e7520a..a9a85f1316 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -331,8 +331,10 @@ static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) return stylehint; } -static void populateFromPattern(FcPattern *pattern) +void QFontconfigDatabase::populateFontDatabase() { + FcFontSet *fonts; + QString familyName; FcChar8 *value = 0; int weight_value; @@ -346,110 +348,6 @@ static void populateFromPattern(FcPattern *pattern) FcBool scalable; FcBool antialias; - if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch) - return; - - familyName = QString::fromUtf8((const char *)value); - - slant_value = FC_SLANT_ROMAN; - weight_value = FC_WEIGHT_REGULAR; - spacing_value = FC_PROPORTIONAL; - file_value = 0; - indexValue = 0; - scalable = FcTrue; - - - if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch) - slant_value = FC_SLANT_ROMAN; - if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch) - weight_value = FC_WEIGHT_REGULAR; - if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch) - width_value = FC_WIDTH_NORMAL; - if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch) - spacing_value = FC_PROPORTIONAL; - if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch) - file_value = 0; - if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch) - indexValue = 0; - if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch) - scalable = FcTrue; - if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) - foundry_value = 0; - if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch) - style_value = 0; - if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch) - antialias = true; - - QSupportedWritingSystems writingSystems; - FcLangSet *langset = 0; - FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset); - if (res == FcResultMatch) { - bool hasLang = false; - for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { - const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; - if (lang) { - FcLangResult langRes = FcLangSetHasLang(langset, lang); - if (langRes != FcLangDifferentLang) { - writingSystems.setSupported(QFontDatabase::WritingSystem(j)); - hasLang = true; - } - } - } - if (!hasLang) - // none of our known languages, add it to the other set - writingSystems.setSupported(QFontDatabase::Other); - } else { - // we set Other to supported for symbol fonts. It makes no - // sense to merge these with other ones, as they are - // special in a way. - writingSystems.setSupported(QFontDatabase::Other); - } - -#if FC_VERSION >= 20297 - for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { - if (writingSystems.supported(QFontDatabase::WritingSystem(j)) - && requiresOpenType(j) && openType[j]) { - FcChar8 *cap; - res = FcPatternGetString (pattern, FC_CAPABILITY, 0, &cap); - if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) - writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); - } - } -#endif - - FontFile *fontFile = new FontFile; - fontFile->fileName = QLatin1String((const char *)file_value); - fontFile->indexValue = indexValue; - - QFont::Style style = (slant_value == FC_SLANT_ITALIC) - ? QFont::StyleItalic - : ((slant_value == FC_SLANT_OBLIQUE) - ? QFont::StyleOblique - : QFont::StyleNormal); - // Note: weight should really be an int but registerFont incorrectly uses an enum - QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value)); - - double pixel_size = 0; - if (!scalable) - FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size); - - bool fixedPitch = spacing_value >= FC_MONO; - // Note: stretch should really be an int but registerFont incorrectly uses an enum - QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value)); - QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); - QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); -// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; - - for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) - QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value)); - -} - -void QFontconfigDatabase::populateFontDatabase() -{ - FcInitReinitialize(); - FcFontSet *fonts; - { FcObjectSet *os = FcObjectSetCreate(); FcPattern *pattern = FcPatternCreate(); @@ -473,8 +371,103 @@ void QFontconfigDatabase::populateFontDatabase() FcPatternDestroy(pattern); } - for (int i = 0; i < fonts->nfont; i++) - populateFromPattern(fonts->fonts[i]); + for (int i = 0; i < fonts->nfont; i++) { + if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) + continue; + // capitalize(value); + familyName = QString::fromUtf8((const char *)value); + slant_value = FC_SLANT_ROMAN; + weight_value = FC_WEIGHT_REGULAR; + spacing_value = FC_PROPORTIONAL; + file_value = 0; + indexValue = 0; + scalable = FcTrue; + + + if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch) + slant_value = FC_SLANT_ROMAN; + if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) + weight_value = FC_WEIGHT_REGULAR; + if (FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width_value) != FcResultMatch) + width_value = FC_WIDTH_NORMAL; + if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) + spacing_value = FC_PROPORTIONAL; + if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) + file_value = 0; + if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch) + indexValue = 0; + if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch) + scalable = FcTrue; + if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) + foundry_value = 0; + if (FcPatternGetString(fonts->fonts[i], FC_STYLE, 0, &style_value) != FcResultMatch) + style_value = 0; + if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch) + antialias = true; + + QSupportedWritingSystems writingSystems; + FcLangSet *langset = 0; + FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); + if (res == FcResultMatch) { + bool hasLang = false; + for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { + const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; + if (lang) { + FcLangResult langRes = FcLangSetHasLang(langset, lang); + if (langRes != FcLangDifferentLang) { + writingSystems.setSupported(QFontDatabase::WritingSystem(j)); + hasLang = true; + } + } + } + if (!hasLang) + // none of our known languages, add it to the other set + writingSystems.setSupported(QFontDatabase::Other); + } else { + // we set Other to supported for symbol fonts. It makes no + // sense to merge these with other ones, as they are + // special in a way. + writingSystems.setSupported(QFontDatabase::Other); + } + +#if FC_VERSION >= 20297 + for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { + if (writingSystems.supported(QFontDatabase::WritingSystem(j)) + && requiresOpenType(j) && openType[j]) { + FcChar8 *cap; + res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); + if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) + writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); + } + } +#endif + + FontFile *fontFile = new FontFile; + fontFile->fileName = QLatin1String((const char *)file_value); + fontFile->indexValue = indexValue; + + QFont::Style style = (slant_value == FC_SLANT_ITALIC) + ? QFont::StyleItalic + : ((slant_value == FC_SLANT_OBLIQUE) + ? QFont::StyleOblique + : QFont::StyleNormal); + // Note: weight should really be an int but registerFont incorrectly uses an enum + QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value)); + + double pixel_size = 0; + if (!scalable) + FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); + + bool fixedPitch = spacing_value >= FC_MONO; + // Note: stretch should really be an int but registerFont incorrectly uses an enum + QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value)); + QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); + QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); +// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; + + for (int k = 1; FcPatternGetString(fonts->fonts[i], FC_FAMILY, k, &value) == FcResultMatch; ++k) + QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value)); + } FcFontSetDestroy (fonts); @@ -522,12 +515,14 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) return 0; QFontDef fontDef = f; + QFontEngineFT *engine; FontFile *fontfile = static_cast (usrPtr); QFontEngine::FaceId fid; fid.filename = QFile::encodeName(fontfile->fileName); fid.index = fontfile->indexValue; bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + engine = new QFontEngineFT(fontDef); QFontEngineFT::GlyphFormat format; // try and get the pattern @@ -552,19 +547,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) FcDefaultSubstitute(pattern); FcPattern *match = FcFontMatch(0, pattern, &result); - - QFontEngineFT *engine = new QFontEngineFT(fontDef); - if (match) { - //Respect the file and index of the font config match - FcChar8 *file_value; - int indexValue; - - if (FcPatternGetString(match, FC_FILE, 0, &file_value) == FcResultMatch) - fid.filename = (const char *)file_value; - if (FcPatternGetInteger(match, FC_INDEX, 0, &indexValue) == FcResultMatch) - fid.index = indexValue; - QFontEngineFT::HintStyle default_hint_style; if (f.hintingPreference != QFont::PreferDefaultHinting) { switch (f.hintingPreference) { @@ -641,14 +624,12 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) format = subpixelType == QFontEngineFT::Subpixel_None ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_A32; engine->subpixelType = subpixelType; - } else { + } else format = QFontEngineFT::Format_Mono; - } FcPatternDestroy(match); - } else { + } else format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; - } FcPatternDestroy(pattern); @@ -762,7 +743,6 @@ static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) { QStringList families; - FcFontSet *set = FcConfigGetFonts(0, FcSetApplication); if (!set) { FcConfigAppFontAddFile(0, (const FcChar8 *)":/non-existent"); @@ -775,24 +755,28 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, FcBlanks *blanks = FcConfigGetBlanks(0); int count = 0; - FcPattern *pattern; + FcPattern *pattern = 0; do { pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(), fontData, id, blanks, &count); if (!pattern) return families; + FcPatternDel(pattern, FC_FILE); + QByteArray cs = fileName.toUtf8(); + FcPatternAddString(pattern, FC_FILE, (const FcChar8 *) cs.constData()); + FcChar8 *fam = 0; if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) { QString family = QString::fromUtf8(reinterpret_cast(fam)); families << family; } - populateFromPattern(pattern); - FcFontSetAdd(set, pattern); + if (!FcFontSetAdd(set, pattern)) + return families; ++id; - } while (id < count); + } while (pattern && id < count); return families; } diff --git a/tests/auto/gui/text/qfontdatabase/FreeMono.ttf b/tests/auto/gui/text/qfontdatabase/FreeMono.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d7ce52ddc7c0de0dc51e5aec29609b7913c2e0d5 GIT binary patch literal 267400 zcmeFad3;pW{qX-ece3xxOtuMGCdp)9$i9(;5JCtLR@r4UB2Yv`L7JBg7erC5jC>k@T;2t(0kuk zTp!K#BZG$*mv(Nse<#=Gb3XE#>nG2C?ZYj5MA8aG{7+poZ*H2T8@Gx$6S(eo-Q=5Q zyWQmE7sIIpT{rXAsrRP`tRt&Vu?&fscJ1WOV@E$9#kFstavBkSp@Ba~emUov)2^R8 zf92_r>o|W;BxU@}8?Kog@#dokk)JG*({}yj`LjcQXFSSvtzX)#$=6?d-P+FcVtEAp zVqckk!%cI?_P_OIvFt$J#J5D-u4@01@_645Cq~wPWrSKjBS!W;@bX|^c=30x*Ns>F zdUCFPqVF)jEots*8Ebjz;_uuK8?Sid&5QcWzlV+qiB_M;e7Q^f#W3&EcQ;899VqouRZ#;zN(&+bTb@;47>nmVJ(b@8(|bohtp`_BwPnNz76j5hR3{dI$kpZCV{?B zhbz6u`kFr0>F)w9qYOG=1?cp_kPnUCP#^owD>(Ma_r--07YAC7j`M|De=R=;v`nk_ zSYN*mTM`JhtcN_I`%CY!zDLW`HfS9*S}&hITJAdUxjxqUYrTB;>2&&D@-X$$I;D8g zd24QhH@rF!n!fh=UhAY~==(`)>eg&f{9n_n@!)Wcuv6G7KY4_p;Es zXteLUqwn*T!<908*L->TLY==)XKlMqcV(#a^5y@1p_Zl7X!~{OJO59iPW$iBwrCl? zQ2Scj`=7!dq*(-7*LC32qm^TwpO*1`VYxT0zOH?u^SvT;zuPTN`%e4o%23xAU1mC8 zt;3a}mapsf4~1H$zNgI+=?T5(IscoXmGrvZY5jcYd~bp)!|B9ftNSEjf#+C?yrHj* zv@Mjedp}{V_gV{~*0mJ0Jwc%ROMOoX1j5sx%S@;9`CZ>13Oc>^vrj*5yKc{vp{a}Z ze?9noHI?I`pk+mSLw!$<_gMF%Tyvix)G~c`PU3h7OoY*(ZSkG2;Fx^Oe&z_r`o6QE z`vy%S_aUg6+tE516Z@9nOSPp=;ewLg3^e4(%Y=xg2a`OlY!FVwbayVgN> zoqhL45wG>tXkTBMkJhcik}ko}W_gM5CDR69e!j4ibh;d_wAHJJ`vTXx*Y_)J_LX59 z>9ow*p#AA<-@dZ)>F3MWXXn2Qeb=v2Yqjk~k#)q$tYdtjG z$4`CjCNC2Sb^Z0BZPa=92W`)ASOYp<>#ajy+FXux-Tn>exqvP|FG}|Ty06n?Dwu7f zTPP=qhpu$5aNZr#%6UMBdGCE3>$nf$1rb*t*yjyvJmJMZd(XEJGT(H~gslwBM&GB?X&Jg7)#-KpSOhw+VPJy^ps)GJ;y4u?-ng;eP~YQAqw8xk422;u z27K3a7zElMO`z+O)MZJTaOI@CVWbxO<7_osP}by_V)r_mHb4TOTv z&pKY;r+uPz)iNU>$9vqLGCRz%AL#y1->cJW9raie4*EWA(@dBHRiNdCfiBbDUbIj3 z_@L{Hj??$)P?xQ?aVnsX`x{Sa>Zto)ZJ$QxsePdHX(!zQLM>0{rO|rn{JCc4t8Le; z16?l3pwnnQw4b!?I@ERqdBa#jUm5Crbb76yPN!vG8S4AAojMzL9l%<&wXW3bL!+p2wZMQFCYL-=Sr5SsPKr>jpl zT^F?fy6dFN!zU}0V_jC-_gWucsO``;Yu{*nOJP8_(3g+TCtAOWpl#9eyN6n?KJOmt za@IO%x%%3bVSnPZOs${RCD)7ACl+-1X>|M5*K{4#HrhbzE1>%eeeFl!yOz$ePNUnd zE)(59UyO^O@Gk! zP|K(W9jA|*LH8AvFb-}99j~un4LT3sxt6cF4)k?x>#d;EOb6{_t=BPlfw3c!@IfyR zc+WrJyc_PndamoV=2+9|xvr0mK#qF?@|5l~>b)%QcD#*a-?_F|pZn5v54)%996Q+@VJ-z2z7nX z_+;tuSvU?pIfP2LRUNkgw65K*$-|sK3X9=+Z`yA;)?>Gh*ZS=Qt%KG}hZ|rPtOYGk zr~eRMhv_gHv|jqy4uc>Wv^*W}z0cI^8P2udBjLZjXg|yYEnE9D7<4_+bvEvMLS3gu zc;of4PWOK*)HY~Y8eM<2?Ee(rNSg8B3x7x-EmNoap)izd--q^r*5QXj?YHiI*Olj5 zpDX?7^WXP{TF2|)KZU+B`k^of89ML(6zcNUb=DVJz32Za)N-}0zEB@)wC*>3PpEa# z=)82gHqhm*^KCQkC%oT`^PK;uc;9tj*zJC4lVHe~#(&F=GF~)gr2XF^2dO_q8Irnx z8quNK$NjDQU+yLD*(Mq80=e(f$Ni@Jb$6S)S|b&gf83wBKXG5@9%T~lj*+MNtdW%_ zgXIQ^kwEu7?!_i`?piGB`f%?N_Z0UK_nq!r(EPHG``7M)?q2R+Tpla=?!USJ;GXCn z=3e1m=&pCSn>J`&wO%@JE!`)nn|(UncWnGmw)o_D!|%=eQXat)>~^_bl(1XAMx)i2 zJmo&f=Y;zNG4JtNA~X1mm$5PlZsZfj=S@DFyL7jS%{->e+=uwQj=a_KMc4Iw_fb6m zk^8UGO6=Eoe5Gl-66O9<`N^GfC*N0lKZ|6MyiNH#*k6B(INx`p%936(TUNNglu{KZ zZ-`T(WV#HNeXQ1gDKE-%eD9M(vO|AVh#Z&o@+;ZT*)G`)FYx^@40E}X%O_9Tfvad21=aGTNfco)<)Z7)jpnx# zNjHK1E+fv<7AA4DQI6rY0NP6y&pNDT8lCq_Q|2u1_bgMN9DJ!ip1aF9>fW+F#}#O- z(fS=CWrzHPk1t(<=ubwskIw6dK33|^RH>5XDqeEBgWM|Lxg3x;Re}Cc_D7{&S@cJ4 zf($i6rl}Ep?>6zn%k^dr3FgQFUH?=9wU&R~Lyn2{#CxxO@3~IXJzba3{{sgqLCzxP zDB)2)=D#00{%&@pk4!n+7@WLe0=xL?lE}Q`_BmHp02a5<5KzV=UI8y zjNKp`Xb*{Ii9aPz$p}8b=5s3_T@Q3z4WI3_zzH(ZjMMRBx{mZ&w-5Pm@T!x+u?g3G z8ob?gRO-D;x?+4%d}&MNHa?})`eJH@Zsqgo7k#pvTp7YAr7PyreI7|xnP+~QWCfo} zKG!3mm(1j&B^UA$^K7R4$n#ON8KLgI^!dMi?#;a`|4TXlzd8E9ZQp;A|Nq9yf0N5P zIYqx3!pC2JBik4O#+rSQ?uUGzc>1$4#ukk)Zn=51O_ocXJbp!NJvCFOEMrXC)^#m~ z(L)%sJS2Obc>5hEMnBa~7C*l?X|Y9|1oDJ?v5{(&8RLz4#!rm3#)HOI<7dWe#&3*2 z8Gkm;SfVXTw=16mczRNLO1dLGGd(*! zKfN@)BK?N+-#f$+?uc~Q9I1{HM}?!x(aX`-(dHQL80(ngxXv-taf9O)#~qG49S=L6 zb?kK8Hn#t>toG2d8i+;2Q&JZZdQ95miD{U!J- z-I8so@cL^R{<_EVxaB?k^^u=={WaTfwcmSw-}v|RpX~n=|L6Q)@qf?%Y~1D)N!gq# zsR^lRscor4y#AV)x+L|b)V-+(Q$I}oQ|cF~=hC9m;_+8WT1{F@T3g!ew7F@Iclk@w z{qa{+dJofI&h%WYX4@K77{hd)>f92q>5@(IG(K$W)WR95rk_-M9dR(Z+UriVK zTxiw)a{tx6-@Vtp#l6}6sQY2}Cig?`jm)-x?7q#t$UVz_wR?nnuzP^J(Ov1TaEt3} z*E!c$t}k8xbe(mbcD?0#!?n-#nrn}1i|aAhqpoSL39j+3Dp#c|-{t)8g(qj8oOW`` z$w?*+!6!RT4m>&FWbMhCla(h6PZpfaKIuGZ zoRkx%PnN?mDsZ#GNNroLGM1_7k_Am~^7)MBEA63G0d2 z6EP=3PlTKZKH-1DI3dUXb^OcY|2Tf;`03++KYrr)ACLdx_&dknJihz*&f^P@-+KJ! z<2N4v(eWvN{o=1@|9a-w_G8Tz5&I%u3yJZxQ)<}%|L=e30Tn<$wswb3{pf3kY~IJ)IOf0G7cX3L z^W14SJV+Pl=N}Ll6dV#779J596&(|6wZ+9JBqrIDd!(eMr8_b*vz*yExq0~og+;|B zJxj~VD=Mq1YijH2do?sR^=|INn^yhW`nL}lIH+UrkfFndkGN{&sL^A_jvIgVgo%?T z%ZfXHa@V>C9(jDr)+e9%+0TEmZTr*DKJ(o3FTA+(rCq<=^UAAxWlra{(`Ei+vwtM> zX2{Bo%)8|}o-Ofj<|27&_m8icrH`+_O{Oee{!@LZ|Gg})dk%!z5i5e#cig?|-Zl5# zvwnlzzv#6u|~w zSW5xoqfjMk1{@NJ9t%fAVz?Hwi1)oHx7c>rD`G`I>k>dW+mj-3$caO@cxIdN$caBA zlF$LjNi2o=@Dz|fi5YFucp(2Is)c=)_L0K})Xz(JAJFd%&@$7$%7wgqRR zQ#$rLxaPPYTp}6Ud8Li`%*BAbtUTDpyKE6a9!~Vj=KkzeK>8fwb4Z&@n7dabZ>31S z6DEihRKrG*!l`gxq-YL20?&vPFM}sVN_{^ z0H;Oj{2&QRU@J?fdKdx7sz+8m_SECoUU_g7(4!#;QlK2#0eu^xDHCb|zct~5rbVz8 zo`StVp1nEm&3SLmd+YO4BFzHW-MmJm4?6b2?mpRL-0RKh@*0t&FxT3|fP6=^4~{W&-YN8t;R0YQ)km9R@>Ao&eMkAbU22BFs=bRV=2 zK7=#8e;EMC=|FZzD@=fSfF2#_(SaTv=rI@>gAV}t3?`o;A>aV)95Mu^!IvUKm%&Cr zuc2?k$8b($7=9VHR%AGGhGYBiCGY@{ZaC?NlWsWaMv!g=+dT9j~nY8#sU7lj=ZlUziHD%rlZ&N#qh1j4Dy@toXC$x z(7_wW;w z&F~VuBQk#}!$UG`Wh_9?1+Bn+3y`xg0p`Lokwq=SA`}jaEFKTXMQ)z}E|Dc0MSk1~ z3t$bP{@;Z&}sR3krmjuVui?^F|bKwCHbx--<6}`Talm4hkIZvpyy9M zfKwu>q(9RV|72|NJg zyY>Kl1ZPCnbpp2D9|s#m);9riHjsY9Igy`+z)OJq2bKXkJcvFU^8mj*)BrZ0ZxlN zITDVF{0w`3Ru4x2y`LhFpI5^Hk!{$y4STi`|BFd*63&ZkCy(t8SO%OweUHd9Nw5+g zft@1HlHap$i#&&)p6A;0J4ANi_Z{Pb;}?+k0=kn_cHS@Y;u7HeC2V`Maf-?spEiM)>fujB96XTesH{Uw0D`_XUzY*-1KfwcS4eLr&cyF`8!0od`YDX<;T z=U4B*QIP}4K7btuHUhf6VL%LQfgK_T(|~*q&IjZld_d&a?J!p4%@EiLZv(cyi67qz z1IqTTYQUzq4v4(H7|`W6fb&1# z|3B;#`H1kN@h}sX0%`t;j6Z(NX6r1GKOyr^l*z{n;0(A#{)|3F0$op{$H~JYpQ8Jxgr7CRCnA3% z{%@o?H5bVH@7VeG%_66ZU>;D0r%#Lg_b!n$vjH9d@r=k>E3ATVMLwSol-=j2;JnBe zAutlAiu^MSk^y`EiTp1YiF_q6N90@rV8_>SfX?4w+c%WKH#0>3#kGH}VR^y5=L?`7 zhQSn(3*3KUD?bfE_ivB!F5Er9xhn~<)xDUtZZ&)ar$nila8{JDLX?Gg%My4~l%Erp ziSlP{?7vx5z%)^TTn~caQrImjBohvb3T=U7qQa)YX;I;$;fSb+kw6&9c@#^bsHb2T zAU~RXVk%)Zd@L%q8McYCBGXEKHbNWe;}T${sQ3uDhi&v6An(L_KvvRhQFhWM$BF9U z2Uf^~CiqNL$|5)~Ds`@?v;eqYR61$XH;8gLV2h}XBv=Da!X7vb+?(-@sLUWpfpXX> zDysm{HET4?f@QD~o`Zex9-M@4MLF@E6MdZxFaq#Zb~SWBCoBN+%_iS$^35jSZ1QCt zqjIc(9XZ&MGZHALoO7ab=K|OBxHk{|@>jueQ3a$aI4`Pj9*}ntIu@Zz@i0Jc2|AQ~ zEUM=~K#x-7mU3RkdD$2IbZ80?RxA-!83Xvbl6IJ$sW+v%q{&eXz3+K4^)92jGaPzU{D2 zRBJV?6xGiO&xmT{yzPECD~h?k>OUX2-v5B8c4W67hc87jpH~Ck6g4meW{Da!1dfR6 zz@CnmL=8>=@*I3j)R1z(zeCV#D91yQGnBlBo)R@I2k_0XjiQDJKofi{YQ$*xOw?5k z@Bu&jLf*(}fS*RKf_M0NRSE18H6{Ycm-(||-mJ#%7d37?91%5shN!Et`|2ftya`i* zdnXb<3Hv6^hclukqr>E-uoJLx3jUbV4h!IIQP)HPx?IEgHBZ4YQJu)`Y=hOX2TqB) zwg}Mk+6{mouKh?9U6Gnv3yXlb>t?|wK#ytIJgpV(2YfsY8PhqRJ_(+IPejddzz9Is z8CwCFKMH|T7z^`&v_B$#Ch}(H0REVXEiIsUz_q!1;X^nr z>SjMkhH@APVNP7!uZz1h1 zm4Mt^NP7#q-Gba(kbBD>K>u6t>3jo{paj}r5|DO2Y3Cz%K62+DfwQ7+4FcreiriZ} zU@9zz4e$&cgro3Fqj6UU2s2agZ=OkAa^19E=2A^NV|lzOGvwfGG0QtEy2G_kh^3L9EQ)pCF;jU=?hE-GIK!(07?j)bcnef>xLSbAhzWNxPi1%SpTZl&BR3Bta>(1O8nx5AJ~{ zVK00LXGGl@04Y!j9WWIZ!v=T;4#LN9PSnaUa6l~#gBh?CHo^{g8;-$wQ9p@+JZOfo zFb7t_7T67k;gqOV1|&f#w8Ipj-mtDztSc4kO2xWTv945i`2lI~DuGrQ56Hc1B|HK< z;cYku=S8iKfjnr2u|V3@t6(#{1n&T8SAQew?g(%~1B`@OumX^KH*)Vr?%kgNez*re z+~a_1=zyuP7&gE&a1cHQ(%y^Qdo!UHh5%{rT?A|4DcB1i!WmI(0w4t{0l8~Py9T*y z?uTu#4@kS_w5aMOAm7I~!<%qc6w4E} z6@9mk0IqM{4(Rkm5TO4PCBVjCegvlh-|j+(UGrcUoEPm=X&5*Fe|(CrpLPOiKSR!E1#m#r-?;y8(_k@tA?j2RP{00O z3fo1Uj)1vvMAUyb0lJ^T7iYNk56=HVzGu1T>`pi;>hk~~fA$g77YBj3e?9}`^<@z} z3GcusqP}Va(tfoGNb}WRI49~HKKz>ezvld#@vsfZ_nU7-{i^|10Cn{IK2aBt`|Vay z7hSw#`ivN|PYj%G7_(rR7?vj3DTZGW92UcW5}XkuV7C~790ygyRxyHWf$PDai4igu z-Vq~|YoTk!2rGa!a88Wy1@NsH5sTow7?I=|c>q2VBWgU%0nVcnU?n^vMob!Te{2ja z5yNVQLt?OxV8qqKE;uSiya7&Vg&FVw90c-BD217@4P0U*w!xEPBq1|tAfS((V>`Or z=fehg2|fh$OiqC&=!6Ag^aubaw8B(a0dI?u5&@Mk1dx-m8Fs@bK)$I7!1dITFdMKd zb-x&CAy5m%ry(m1|D};Wo%HGGo=zU=$V$h*juI~;2xkF)V!y+1?12yAtQZ-{%gBUb zumqk1bjUdB1r{GQaObllbk z0qo5_E=CSI;P&GC;HP5Zi}7PI zb`^giMoAL1!(4a-4#T%%^hEcbV*%Mc(XZ#nVw6TeJz!_)b8t+IGW0DYUD*o2hVl@o zhI`-xF)Hv|#Zq_)-T}&|;+zL8GgXVgY@3=}{sOagpYO}c8*Rbyv0dRCtoqlR=fq7)Wa}0HiVJsl8Z6n}| zHm^Hv#vzbG;q;1CT$U1V#Yz2XOy@ zV`2=P1DnMdjt6`+ECNQuV&MK^_+j`YAl-;4z+WR4 z!45bn##Q8Z6}nt?KWvBn@R1lJ8=w!a|BIjCknYuxY>(Jr4fv^hDeOef_!5TO$#`HWfW@L)-qck`x#`U|!nDvYp zH{iP)&~$jbiVnt81p!u z$MG%5xn&WMWp;Y~3Xj22@dx-UfMh0lqx$O>DsJ>jQbkISepqu#8@{|jQi1NJ$bA@AjXEL#Q5oI zF&@|i==LBs@x0OCd84tB_=k}F5NS4%&nD78JOYl3@yH`$JX!>wiLrT$7>})hQ(|mc zAjacCuwRU=`0fevd4l67(e-DQa8`_`wu$lcHDYXQ7vmSm*pBa>b^tP-!LDaW`|K1T z?Q`43cz&uFI|jm0F?EZI|Yu2@yh*T?CB8W)p9ZR zV#8~Ba8itY?}+g_e%OyKze0}#yTy3pZ83fw0Ql+GTf}&i<2N_Jc`@EvCC1wcfc)Q} z|8EY8@yS@oZ#<1t z|3b$jey~@JKak%?E5!IC`Tddnj*{P>$nQ_&_c1>IGxz=Z12I0?CB|Rc#9$6-9NQzt zU&;IUSTRnZ^GSyopOygfKASJb-#9*nPNxou@po)JjqLy4D#n=!V*I07jI&NLK1Zi7 zkp0gbF}~#ZtJy%F=cd3}F}_CEZ>r%7G5*Ez`Fq5;kOD`<_;#%r7ss#bWzbEO9T1B_3G`Tu)ppmZbS&v9AYg*kvF_oP_z&WWXA8>>h}$K|96LagSIAhXB4B62Y80UD)t8uwHmO z{COqC^*aLnATw7-tt5g4Gpt>2+^d|7mQbXIzFdb%3q`ap%c zzA`pmoT`7@ZOB>o=W3cUgWpPJAm0*@;mEc)E6S@X%Sz+pY=IUtum%R?D@V2&uZG1a zYpjY<_JF|TU_%v#XGHj?g@%S_hWn+47-g>A$;qlUFt|sMkrWUZ=}J!t4o&A$a0uT* zj%!t&I%td+e}0c8v1Ne)j_fM)d+id3U%8*>+ZcZ_GxH+oJI1^Bt8a}v`OOke_b;i+ z2-Ipid#S1nM@4yESAfnvRA8CbU5BMMYkpT?-VvJ-Sf+YMjf=FzL|IhSD7$@3aEIMK zGzyC%$3>}FYt$IKeO&MmyL~uu5&kN9T=2NOPydn>Wmtkfwpkb3tba*Nw0vxSS#680 zw!b7rSk!%sMahlst?E&vs@w0t0MTBKg?x zZ=j6}y_CMqbHrWxT3KmTrP|vsZ0vY@OjAao&03M;A7I2cH!up*thBv{9|poNzQ(G@&4s@d%1rPi+>M$y*)177G9i` zT4nQ#wdN=156g}9zr}99#o`PIjI!GY+Y_@BqRSI;wv6I$z$xPzey^9xZ*UrADAwtk zfy&wtZDG9E6s>9nmRtVA^>}~Ztyy?P%Tm*uGi~K*&Zew5zDp9q@~rX2iDCJ%>$=Am zC597Um=vBL`*+v!Aipp_YT?2lzi^8>U742C%Nbvhmfe&U@659%^i0$;$`eA>!&Rx- zjaj}+xi)<%$CkjQ6ALU679%2Hfk6;XJ)7=6t3EaYrAnGb(zAV9R#th75@o##M=Eat zrmD&+Pels|jMoPl#VWv4vSp>}C#i*fS_;zp#l#i*sq(b!^z_)k2tO5-mXe;I6kc#c zYGl6M9u}8sciQbYPH&6}D56YCn(7NGN92bFw#NmA^vaC0hDKT}VZl*JPHS9h-{)&v zt+wI$xmMfACn9QNVtZxSsC%brQ!~vrhs-Ku z+C}2EOta4WdJb=;riQFT+|?GpE`gprrfGQ_wgm)sNsRSmgtojweV&#yUjH^rd0LOR zJF-S9pTfn;R{)+$F@i#M~j2M2uBg)etJ$;QwAG4%YlhwA< zZr^FM?xf4}f7@<<+h%>sZhy;a(^lN+zJcE~-X|d}pjEKsO4%A+CKZ{p4>3f5fuWl<}3q0m}IXFDhPx-5U zW@y}cu`MRjF#N)dT{>h&g@n(M;2SG^6{nY?^tCeC^aDK{o{5Ce~;5G{4ov&UNjD6I!QsuJ2zsq2HoO^#jH%?w#Wew6=KSQ=?OO!$n1# z?$&;(Q_;R+uTs4!N!RPi$#*RaGs69q&FH-N2ECuv@XMoNTOtFwRd_3gHa$b~7;C(G zn%ylOZn~!|(<`XFX2+%bWRLi1MRh}m)fA@MM=lwxYHe26ywhW%f~s;#+KOy}0g+TN z^+(Xh*kY)D0V7mfjc@tNg|%1-8|7^czq@#}$y)IACa5M(@%lyS*`? zBEnMZC>UB08%jMkqN41@jX7nlg`q))b6|Y@@Tx**qD?oC-0JM&<^qS!8X8{~7Tzn} zT4XgMnVItIX6>)>)O*@>R(eHjnd$v}W%G1%W+7BWXIRvH*XPGaIP7)@{M2qAnDE}u zi+S2O&t_esOX25gvg^@HJ{ZrhoJHYaERNQ-8;Rb!*HxnCxz7u#zP8>L9Brti0i=qmViLdkg8sE{mE)mH$NVr%`uGhn2hA)fxR#O z%c?NnpP6h|TTJ9v+%-t)>c{D0oY~!Ky5-8z`HFLO%j}l&K4Yr$W>4{JDs3EInKLF} zSX)j)O-4amZam+E@{{VEJ=+VC>z%5m?AqZKIlX%}be7i*9ax&(P*gL#lum=;w;{t; zmXg`*jCUQccI36>CRJtT_jB?x+7)G>$DXd*?dyiFC<{Fe@=cIP`^dj30@c#J2y%Y7 z1k{3VC18lzld8u&^WN|FrLq61clCC%-`CfwLfz-am_2VyAokzINHBrCLWFnnx{U?j z&E$8!(P62l5BG}i8Y_&D%S2O?+W6Z^A@t7Fq%6;ztkBn|2ZpOSBP5(3S_Qc#sx3^E z0#vx`VRcP-pNK%i|Fh5hBmFF)fp5H_bu5#;MwYsT5lGj`t}!UE>&OUkwJ;j(q0jY% zszZ-TYs{fZG3za0yfpRj_H^N0gG`}vc7*w%hI-63A;^zWCR|I@>fy+>+gobtqN1BpWAw3Wr6VvnGn6(HoE2ixb$2>z zkB^PnQZ0R$4%0llhC5p{Z7yF`bk*THCM%wL+cgUM)T^rKYIQ1qa#db?S?h?R9Jg-+yS}-GYk}b-$t1P}pWn3_NGm|g|8)f*BB~(_rcQs`8-m#vU z48GI)n^D;oI`r+XbCrY5zC87X`F8s|Z)Dl+o9Nj4&5oS8XPxfT)n9DZi|6#w9+l<# zBP(Fts~bJYNB_-;B5HTEIeMjgipA3@nN^6~JmXou(lY~dJgKT&R7sUG#+IgDb$erB zjq8xzK5^aXoS3Tg+^uSGzrxn_@Ab{HoY7nVJfnNJMo+4!)HRb(6yZsKkT~E2Ya>~{@b*m-+E}vD&$$#_avY%WI-e=aAs84;>=E^*D zd6iOLvuaRFtHnU}{^aC{v6Jub-*Z5} zY1j0@LS{*g1xEbB^8EhGt5edH+MvyTy8N2viS4rnwpB*3&bKEP*<-P{g0jn|?8?w3 z{W}IzjOJ`5y}M@KNs;M(M(Z!|?&{>^!bH2BmQ$%BIOhQQ_Ph1@B|lhg@4v4#aiwa{ zXm5LFy815#Trt!2wj_#GHQkk*?0TJr3#O{ZXuRp$`qO%5MsdTyM88ZK=&HQrDW| zJvE{p>6BL04>~BTTgmD9t+^h~H@7sN7+|+=^HdLl0V<&|IeA`ka@5EDbF-_f?eR&Ir zebOYmohqqawV6ekr>f&DrT3kTp;*J)@mc)wf$n8#dZ|v?m8aTYeo3_!JsQ-WoQ!)M zl=L+ZZ|tOuX~{&i2k8lKSE0DJs`0);R(~N+JsB+}PX{{-8J-o5x9|04sl1_C+0<9% zu6Oa-26Cb*%}_nP*{W|`J$+ts1*vz<@?rF*^s{J9dY49Yx8qx!ec%3!Dwx&3nJ(-{ z{rmDgwxPPMZqVq)n*Oy$)74ikSTbtR*pc&>jT)3Yw7v7DL5)M&r`$TQm#2qgEmOw2 z!1)8Uz?*IMrLO*oOWnfRiPg@w>H&AG7+R82lU=g@)4e`BnhI(L_sq^Mcd&&+(Q0e% zHm&I?z4e&uTOTy)s^r^X&;~|&W;!}M-$1L^Q&-M-RYPh2m|!N-p<^f36nP9E)-s_o z$DUtei%fKe`*W=@%^sVVTH4JUW32vc3WNmpwoUGsfIslcog>>UIYBW&@j+aPiH(R1 zHD-U;OU59)l&$A4-`iG9FJ0C=im7eB!LeIQ`DR3Q&RtbG_R>_lz2>T_9@)$0OsGh$ z$}W8H!eO89>Iy0*mt@sukFwe}mD*!+%X(y%XYzIod!}dEGi}msru%Lre!8q1_06(< z+mQIrGmLcKetd6G?4)bb6I*-s9$8O?vns#(jDle~wgFL-raF=aRSuZZ$oLtnEWHb= z#}y?#*qR(@wdJMu>?lmDi?!RYvnSM~#8f0Zn(P6#`26(pktOMEp3$@}BfdHfZQCgJ zD7@AKZ7&;ed}Eq9jQ3I*s`qre{es;-{b#i2H?7eY^(0$ix^4Hj+vm)&TP=S5k(Wbz zC_x@$Wmj+L=>fgHd9-(%qFZE!`e*;jw#l^x-Ui*6TRFHmt=(+hbRy4AsVnGT)n5(O zP0sb~u;SE){3_3x?wfq`EmqCxmTnzkY?*huWwvYT;G2{t%jH44Ew6W&4LtRIBgB-M z>gmldp40Le8VpvH%-^J}yF7X(yXq$2k`byF)JLLaa`M&Hvm36jq1&U|h-_$@eUn#k zrdsKmua4?WE}m0sT)Yh>Imp)@(qo>tqc(fe?Cvwgs_bq##d~+#Jsniv*P`wAWp;bR z6IcM*Qa#;Z_y8%eK7gb#>;eHlGS}g zspxKOw=4rQRI|6}Uq~>;J0Dn|lblS339jGk41TY|wCunBm2a!kKD>^v&&h-BxLj4y zZK16^^Cz47+%-?Nx&Fy~=xWz4Rcp1?sdp?4Opn&O%KaF*5y0Q(TBcrQMIt8F=ZDQSZ&4;&q&;DpDng)S+2Yt*F&lwy^0YY?0VT>Z|fSXF17{hJ>eK* zS4aS%*83rHZ1Uvj?;RD)piISka~y80pe%DtPu{4euv2!Oxo-1y{Fin|t5m^`U~?yQ z-MV1CDHLp6_verx4#Ho4Ih+eYA-uEorTY$})BPgzdGW_L?4+$3z=Jcbi#mlaw@Vab zZmMaHqu6K6{yBmEw!qLiVTcJd=5+@72gF!{J41C}OYuq@t+0oBmbzBO-M&2uuMaP+ zo6J7RvvAVgx2ovA_OHBcerC-0!URUaiDRZt%(V`y98fo?J~^XjYaAQnY;D)K%qfhm zOGq6(FhVWp5ff0IlI8l!YU?w+R}bgl9J{SwnJpwCDAMBkW^80td~&rdxKU34Bu;CG zmy^uB!RW3{aoq)as=deQdH~W-YJ7e4nzor!o66dI4V%?E(L3XfzN#XpxhH!kxqV8E z@vhTT)u3L(uj^AiZ8W=)H0}@kl=dD~mD^m}G_HzCHM^4J9gk<2(|cF#zJcv~duQJW zXT;|Xo<66kczCaoSJUP449Kq`uk5>($MCY1zusdI;YE^-wl&`SGD&VI;)Md+pxP& z&&ClIxh>dz@wZmnnCSzWuDZ5Q)wI(dtH)I4G?(@sUr94J%r#mNR;TDc%8`}s-Dtaf z@b-=G{^{O5AS1{%DPlxX?a02N!65;Zcw4`gS#9+lO(SnC^Xn+?bSEa7VaMz zZQ9#vlwxnDxyq^VPAPrsK}I6IP2RPAprD6@CE{vur;>Kh`X z#}?}Oyk0%3v<5qWDieun!{mPx?c5or__2jWzm8j`<$gs zQge3ckL~s)&1un=IyE1i`iv<^v{@^YGmO<*o^NF_Ue6a$pnFw_?mp^y9`X71OkVaj z|A|k>v0k#_1vH~i)xh4PrnOY_&E9w4vOc4$^ZS;mXFD23Uemi~VB=Mt zeX4Wmwntay_Ac!`u9CNG7%^H+`}AL{?J5J`QmgwU<_89jUhUR|8BHYv>xa$mGsSLa zJ#X&HM31U)_9#e$|Fs09p)0#>L)eoE5$9R5BMJD6eC{vTc!CU(3b*8i2kNFG*Rh`Y9E<-)>lr30 zENDEtAeWXizK&HL=pWvBtv#Zppzf-2a}@ROV|NV82yeW%(B4zEm$y!$M`u5Ma&ljLd`V1DZe(n3WMW86dQBgvy)u*+M(lBcxrxz5=Cj{? zwAE{6`V;Rqt8c+^#c0puWGD; z=@!3$D8qwa7UExzzb|i zox{oFCfZu_u%;ePOduXRBF=ZoINV2A=Xd78J zrf;cv%!1Q((JOnO@Iqduy7Cxd%%?%P}`&^-@Al$IS=%o_!bdslKkj zYF$EBNJy%Gkken~rdk3Ls*)q~(p6AmR%mE(d~$-(79JQH6_N0CiQPXS*%=)Aba8kH z&n>Mz6H_@1RsO*dfgzERiBH$3(0hB#*+n zn(v$FR}6Sa&NQ)0MbDIl`tDf=c}>c2yz%eVo%X+{Eo1lx>RUBlmv0tR4d2@|+FRZ} z@Ulr=e4JXE>P*n9qRc|4v%04>Ffc78F4)hH`Fe6eNp@4uD9gp76#lmoBRZ?FIM?6E zP4Uw&B}Jr{muItpru#Zs^wE{d zQyX#1jl~56ZPvzI|419VHi5PA_E7~%P1&W*CDz~=Rb5_W>H_zSecA(hv1InLy8kzy zJ$W7)dipHiI;+c9dMR+wX82uWw~zI&`8Fji*xxT8#>lnCyI!@&Whck`O|#o4*lV(i zn~S1(tt8NzRZx)J+5V|LrpWUb-b)#PO|+~yl0BF)vdr|>dZbW^8duUH=Zx+Wxu zEwIq)3`Z4w^n%$x z{b{y&kg#SJP5r|xn)V`J)Lqt(~CPc(OYY+rMUU!CdQ8c$E6I~H$WlBh2A zDY{p2eZ{gM)b8r=9#B5b{2!Ka#yH-k(C=?r1I_xu(_QoBP2bYryYo?HR-!uPsocIT zRCCf1=-J05VK(KZ7jr}#aZ|%<9C`2BtWVS?h762P>wQnPEh)Uhk^6zw_EcGNSaE8< z>YE}hD;ksgN5wRa$Os6li1xd!VaUsEVR80`^w=8`68hyt#b%dA#$*oZQyLd+#3j^b z#9yC~(AODbO?Sj+r#94v)`W+|W%UdR$t+4$J%WPr`(^Mn&ydy1t$u5G-r$tjE1nHd z3SBKhuX^|Ll5UTX(9{V39wDD~J2tLK4GvAwvHDu~WBMbD`*ULiZBf68(%T z+m-YBYquVv>rr1>>3@1tRQ)_9udHv8qdKc7zbG??4KrTqtVxOP*(0OK5fc=#V9}_n z#*SJzf7Hk^BNyB-uaqW;C#8#cIa4XXRT4UpA}uJ?z(g zUwrpHt5>gz3TjLWO^T0itgL8>52{PgO)ks{3%Atvyuu=U(Pm&%Q~c@AZyL??PsOZ`^z4 zi;toA-fQ*@;kGNz-+#l54}0q8VR|<(^xzfewDdN4iZ#_sdgZCij+AHb^rGrh*CN^v z50lm1HtRo`elk9J-(X~XVy94ex87SP^jiT9x=raP$@+BzPv5||x8`}D6mrSg{W(bY zK~-1GD_=7HTc*`I$!1GPu-R7iP7W&%4o*u7iH@{dvui3Fs|Q3FIT2BV`usrsP{!2E z%nO;tw#2e{KTA?hRBGlev6*>6L0RGczxd(W!EUILz+P~ZIZw&Zrj%OMmeY3oX}gh- zqqo$lKVwO;=zqEnrH0mKm$c_6*W{E`r$+Nmw)t%=B9?3Q&YrFLDY?Z-DK)-}V>ppy}cC^{Pa>QgJ1b&@2I+N;AK)fFO{moEq42soX70;$8ua3P+ZBg z{GS}_dEb(^MSQj1d{2^>3243<-+4!JcSd?{l_NH}$L$+3PcEzQH!`DR3*-DOei0Ey zc#o9i!lab6^o+R{3M7AFg*6~B(;A!^7)<3*{NFJb)MoOcg?Zlyq=3CWQTN`68sh7D zGrZ%rr+ZZexygDjFfTQwp+|U8ZF#D*A}==DFEKT%Br&WoF3}bj5L^)H?~E{->><%{ zv5`f##QfCE@~Sjzazto^B{DWMIwsE+!W)uGrG5$Tw4>xMk7Cybsesc3m&Hea$I-j)D6(}YB1wdI5XsIbMMYG>8+}y0_t}Ye0w~+ z_ZOYvc`eBti=!(%(|Ts0$xA8{MpO@eGcmDOLsHU|1Z8WpC9X(HnmoiAUFT4KK`p7- z#Y6LwSz_#BfQ>PXwu`%r7=~Kab|I)VJ}Ij#UB4@FO#YzeG56Iz@(mueYR?o#UH%5L z8h_a<$lQI{JzU*N|GT@Wy|>6-`z_7q>&sOofV*ptj^j1RT#;W*~mFz!SNPL z;?QDM>hE6=sOgEv5F@~MucI6`s+8~HmYQ`&*=R>Y`KL4@_W?g^z2`dQkz{`mloSIIlVSLw$yI) zuFEd%SCCSd-Lqd|N>)j7Iu}cl(|VC63eugvqrPTteXRNZZO5ML9wChm(+yY5`)8SwySJ4#*cIX z#6+vhieQ>+iuoWZL_K1LuKY+t)i^#nl3A1aN|&+G3mc-DX)vOE_bv7;Z2I0B zaH)R@2>hWQO`W(xao7Li?M>htt;+rJoHtvWq)pP~O`5!E(T4@06+JCKT4aNo_XKrob#M#UmhyN8`g1js>fa|fdAq`9Ls$Dm~_!%vZ-g3hK_K& zX*bRY5+sS!?~gjZzXQDZy^>P4qhNp9iXH5GrnkEbwyW^CaU)O9u4UiDZHbZ2p(hP# zx~HCIqiUlvtWx40>9Pg;-tJXeFz8{~ieS)z3A04upiM5b9u9g*ry&@0V5HoQV9*-I zV8&wS#Y%GFppbG(aY7479!p58;1B+Ag=7N1)W^LTpU*yJy1B^sO!ilW}Q;Vy4{KKs3*<1^W}3dhBXzD*}8o^m?2>lO9sNj@8qXn1;V9D7)F9JYhP zaq;vlJsnR0UeFJUM2(PTPc@`M8>jOI%Z2u(yUFxGTpr)ZMXe94MraBw!9Ur(Vr10> z#iqvDxzV2eH;}-1>s)`DA!rZ*jB8i!?mKn$1h68|(ZB28{qif5BlENd5$DD+`yImU zPQEf8pQf%j%2$Bk0?f{h&u4#8bX;4pVZOLGCVIMYl;0Z@?E^-EkLQ^7uwSs}xo<)v zpgEl>7a^hMk0E=k<$5PKr-08wv@3PsH+^^9aDxM34ybg>?IX_XZ{QXa8s^rO8!)ZH z?4)SuWcCM$syPl(cu88hu=8{ya830n3%nPW9ir@78eu6@CEe@BOA)P6vSMQ0^vBA1}GmnSL+y6ek|G9B({|m>p{WpvYjN>~kMnRpWI{tL+DMK6+af`SYBu-J; zMPuPq#8YLz22I*;W`@AQS0j;YZYl^Kyke_Hkr1*|5I@L$A$ae0%HpKhH}0?P)t=3* zGMd25ef~#fuR{G`-#W1=ZdHQTu4;FCxMrZLT*Nu`4Ai&HK?uBQAl5t(_4>>0PPZH3 z7T!;u+~z|xTv879MxkU>W>#}x9~-X^A(3XNVes$?UDe%HwEw*Vq0v@&r z(|XfZorWW8SzMl=7O$a6{lsk%EC{Z`tvxD+8?7QfVHL@RG@zqTJ@$WQeU)dpuGCgN zR9=38Y-X8^eJ~PBv?5B!!WvV}D>}{QWZ&3gQ+TFxw6UexA8KeWv%{A9?=6Y`PNz-o zuB_@DLPy84Cb@cxpIs2~*?P)7<8I66!qq3W2O4D$(kZL!R#?cX9hw@c>m02MxrU${ zhV13$%%6`di`Z;(d?4&vX}kKQYWJ-~FE)UGQA`fBYl_LS7w{#n1_~rnIg`MfWlYXs z0S`#QhUrrUdupt4gIbsszXysZLF(`j2nPLTpn)F{< zn=l0TR8{1Hdw@q2+fyR&sD^L@Ysnj(|7Ee!8FS$%#~2G?jCg{GTHyF8)7(Gt=jKKQ zein|-{H|~=f9{*~T+9Wpn$7+JmW%_Y4zecmNbzn60HeY-1Ttw<3RN_$Z_rev-a?xY zlM~}!Cb#W79#KH7bpDhE_twD$a`KNYO%9hh(o@?cE0Ul}jV^zw&h53jeCCcO2BKeP ziSM`~)qd$@iwFTo+U&bKo0!{zEb}Y!!U3?auwNjih~K%l>CUayZ>>k1L7djVu3&Wj z#bTo~rovJFToXOl_yoR#CfY%a;?~ZZLfF9wEK)(zDH&`&2=e#aRqL8268j3i>$%0h zf|0k{;i!Sxm)B{~KEw8qyaqlX`~g3s@KoJx{DwED!Rw;zTkn} zwk7jU62~(2G_%*!Z=4GEgp2(T)1GeT`=1+~|4y;dnZFc{@|}K%c3M1vdv*D9k&S~< zU_UUJ$An00L?nh5m!p|7jD8XBfA3lrO!yvRLZmg>!kCcH%l?1KiwVKH1$;UD0DKtb z8jJLgp!IW4?E%z6UlE+eN2A&AV^r`PF*gILcVjlgr7`2|Q!smDmR7FL&hC}ANL`q{ z+4O+PB%aOh^j@h2baV{8qBTt*APZ{)*VzaSz(mMBrz&i{iKAN9j}{FYPdTj3fsoDO zG}rn4;||v8@(jP908ytLt#rELZj0ONvbWpq9Z`G9v13NDn>@=*m302bcL;%v80Ybv z2Hb#sC2#f&Drt}wQ8;_1oc7Z&n`A3#$x2eJaV}0(S}G@8G|c62%pT>*v(>pL=d_vG z?C&`opcE>6pOLoX1SeTv_G_@+L)ybQAvQD!e7~9FxE3**L>8pU7&Qq-sGlKDRMj%n zUq$0bDd6e&=~H)&_aK1wlvxB%Uqd555rL!#phX~Q31UU&{PNnJAi)SFJpn1E&3ZH` zg0Z&uG!T@0RRXi$Ak0qcYbrs$FfjYigxP|BiMax^-{3o7oXs)&&$M60+59Bl$Z2hY zxAK$tGo6Gw7q_4mdli>9pGkKB&&3@W#VAF(c2l&TwGiKpdlry2xk~UiZghv+(5%J3 zqIkCf%X_Lrr_JcWuX%B?J*#Bjn|e6xg*sxVV%CLm5e>U37bEMgX$6&vvy(-DthS#5 zr?SiUhVKznd0?&>b(VK%xHQ%Ztz2?^Bwt-^Nz5KRb zhaARZMftKvl0CBj_~Zq~Kws=Bw`Lf0bz$QWGGk6p5i+Bg%ej<^?y_-ij!PNm3S2T; zL&TGFxI_{r#jWgRZ{Y-C3t4s#dwPW#Ot5BAl)}KL*r$y*5Bw$bt6T==;lq(w%4N%4 zGvXh@NCxs1^*ephU|Crlv|u~Y0>mmeQGWEXVSu-YtaucR1qwg`%>P^n!ZRW&`mVd_ z_4dt!%K$)(9m1tuzDS@9$p2f!H|uA?Zxq+t$x@`oBE!B~fiL{U@ECH9m^%e>vB>AZ zENF!eP9V@ zk76A83Vi%+J`Rru#=-xk3U&`v6~uwjJbbU>Z=274lD`d@j&Xh)I7OSsH=<~e#%Ml& zE`OiN%%7{y&jt{eFW&bjKCaHk^J`T4`cU=($OQWHC6kzMx`xXRx%sFE0E@%C@Me{KXWW3#h#?$Hnp?D6!BAU5XQSRF0q`WQ9$vk2|^Vcr?RdSV%WKBf3|B#}0 zx=M$U4};z3)=~Ae-r=VOD&FVIPfceChBZDL-tud{zpEp z&c|*Fo;;f^{`A@0)3e{@d;d|K6#g~JeNARw;8Y=y?dO@wI5Vrb$?zNKE@quR3^FZS zM!2ALah_H6l$4CZ&0ai%8II9Z*m;wS^(yhEV(H9BzOlNc+G}@sfgkB?Kl?f4DD004 z3qnK5hIGvA0$C$S>26jcfJq}4tXP795gIm!T!JEL1`n$6;G9IBb&gM^`00^0oAfh$ukN5e{obE2(ju&H~zz3lC> z#z1t7|6{2{q$8T>sIBU(X2WMp44gLfqzU8SDt~aFTbiHP^nuBa8ULOSRC{i{ zb-a6gTYq9SJ-(waj?*OSvs%54xAHv)o?(0gzZv{Cx@gZg^3i78I%Ia!tutBpty5?7 z+xRfQjW6(Vb-w;|XbMH2K5KY7&(~IA$@1Af{H;9iL1>nLC0LgDXm0il;3YY>aQ2Kg zoA^AUF8(HsajPy5jur<~XyL?p8SI-PxRLM*RyZ+E;ms5tR;nfmJCR+xVL?Vf0sJdZ8Oid(N(>kK>gwL!+v}|YtUs#@7 zQWH>fOIrMnMo)#BTQXB87u|=_mb{D;;6M%|W=$o_Fyd0sk69b(rviUwVe3Y|J!t<0 zHi{`nelFdI>?HYXX!Nx=FuIA40(&J7$4m{6wb^e-Hfb-v4>x9?6Z5h6d_HJXBPhZ$ zjR~?J*G2?(aXLlu`^cq6{PpgWL~cLm%n7;tezrC#cqx+Bzp&Dn<*#Mg;2!!k+k+Yb zr#hCPuW5&+@pnOp@Jbj;ZxXpR@N)iy{#%}VGY`qv2W1O6Hs|`~y~#@o6L2m|V&9UW z{~ZQR2UZfko0MP7HJw+;iYu&$Vs4Iu80T_L=M~~0#<@lgVw}x6$SXt>471IhI1ikg z>EjqT&b}KMu;~@@_84ay`HgWl=QrGfgxNULBy{oiGx7)B z40;W_R1RB(*>1!oby{r=ffELs;i!RZKW8ku5T72dy3k`L`&>&&X&VxsN{&*1A@kWy zQv=mep5Y2eTcFcGFDasHX?8{xtXym!7i)657yEUA-qlzvU#ceMEKmT8Cr~;4)s?O? z;y8ZXr73=wG`}j~#5m8c5>^u~6M$}EvVe6EPQqF! z{~8u$HUC&3B*7W4a-mr2X4%de!?(-ZbNqE2Up8Oma3l_wQo{rPp% z*cbDvs=X90E0bbws|;^rQ)P9J;sTz)QXo}>CrHwdKncj-A*v?0NoS+zU5&ny>ro!=K~nhtHFzt{i^tmY!2KRV=Y2XcZ_jipn}@H&Z%%jn%U2^I)#}@2-#Zs z!uWK=SBe$@Vk=V-A~hpgqinEA#nx4fF29{rx@iuxmR>c>-~8+#fiI?v2J3AzH>BAibL;e47OUb}ye9a@o^ zSl`<;MOpqyq_ZIQ9mOp-e*obE9~kdG5s*z~yCoa@rpGBgAkDEae}$kWt&#S1(v*Zm z#G%D#3fK{VolG)Qd^_n}qW%`_bw(;lh@$G_x)-RI$2n>jLH#>vTG}xP8!Br&FYZwf1hYj^6U)fRZ;Km;8*(SW#ChaG=r?5tgcH6sq^99SCzyPbppE^oP zW~$3beGqn?3Ss=AfuUsAK){X++a3q&57%shk^Xhnu4Cr5C{=A-C?s0v4-YM|S@X4W zr^Qm4`utY&V5!Zo7pQrw+hxD@b0~K(j9egz*D?8Y_8s;%b}nR~^q`59*6Q`sbs!qf z-mY%#UlDN)hncc(sx#@a!x}y14%LoDYT1YV{>+L^4IZkvl&kQWz!#1bD&bPSain&r zVle)SIHolo%z(AUvwfn?Crd|oNJ*4KP0FpeyPPfJF0wz%u{k0>UFMsoQvm(85hMo8-mdS z22Id&?*(o=FjT+sM=!Wz*Q9h^OTeW+SzP+%HF(;n#!11of7MuyrvXKJ*nPPx4|t$S zkrxEfJiI0XwyNN8bpI}#1nf&5t8JH7s%R&wE5HTtiCqe7^jM`=Y5A`v{|CN_pVCSP zvKgsf+Q+N+0DBM{stTfRh6*83Cel_0nNy9gh&OP2^EKooM4n6C^>0b1HJw8C>&|qPl;KF&hRh?V#!?}( z5BBv45wQ!8MJZ@3b?RI$${A|M5{%>(StBXMVKjte>lS6M_ZETCP@idRv zu084{o7i#~hd1ceod`xVU|ffeXIx`jCS!6sFU%Ag71cB(&L>g8Ko{b=QvY>QOXXDa z$nLhtOp~Q?-;z=yMrzVWtHY(tye>U|#$e-y^y-)tJY#tMHPbEoN0)A% zYOG$lQVwX&?BPF}f!f=;Ei>PFwEmI;2gr{KU-fl95C@HL|3xa9bYC>^}~v_)nBFEmW2 zEn+qIi_nD8T(}qklzB|{PqO*%QR3K4*JFu2DzsXnS*=? zoBPntO)YXyb?nM3wzP(Jl(~DNb!8sK4}mCJQxgi;oj!`sw*;U+TUuN7kE1UpD}wa_ zS95n&Vx?j+S0DILLkNjs4QHQ|Y;sdZ9guwdu!M;RNKDT=$9C(y2?XKJJazkmAkepzGa%wZ9D250be{29f|q7 zDyu6|cUbWajwZXeBuZspqO!I?5hALtRTYE6DQY0)prPs&dEk($ajfOApKPqydt9It zr6ISpz$gO4#u6L-Caog)SSTFMlwWtBwZGjj?jtZY{h3uz5ii;0NRJ zCr2SrLh0pBsyy0y`f|d=?&1ZhRWFw0SWb{cfohG;69x(&)_!iU)+kW1tzRP7hVmW(@+t0mW(BSC;|7Lg#dJM}m@?I65rfw7$H&WK5<8o;q9 z=e^6J&V2$`q=B3d@5r|`G{M`*Gj_K0O&-ap2XN#`m6}CW8`MZkz65dfI^G2*2KnY# zb-kCLo_b!=h?FL5)?#8*!;=bCzE9~Wk{J6r{9W_QeM;ecJ6flVE?cN9Tg0tY09{&f z5p-*yWkjSw(x*7}O{=HXMK&6uv%xNvAh%P|1<3VezfqNb-l}2KuA1=0KKZ-nL><%B zHQV=8mkw7qMP9H}_&&I%t@h+(Z0ll2>wkP`&?oKOt0*^q*10!Yx2HR3b{>dEwswU} zEuXzHXi@g=^vv{5-P|WThu~HuEPqRC1SY}zQ%76EZxZo*FV7Apjh?h?odmF!ll_(* z5wFGG{qS90DXp-`b<7f8}#<)i4mq{bg#c$Iqi+@hN%a2tS;10wP7(*n7T5UY@)(?o_qXc=uxxk4cY-*I9 zu^)H?dA(Fq@yO}eYqZ7a1p<$T*?-f^0?y=D3@iW-sLjq3wE}N477$zx9i5Kw`gL)w z*Vq=1`|5jh{mGDG4j)d>15_wIbIvD_D!l(XQ9S($1WmHg>r^uR^MgN4enZqye~Mcu zxTg^w*(lDwSEnBIEOckp0{zm^`eFGJPV_x)GIaGF0z_u%1Yg>rAE_65t+r5(H^`6m|2<>pVR@b<# zrw%$TA&(F1geZr`wzCzLC)bv-<_g)o0@YTW zw~LJ_jh!8({~Ed#@+AcC^UD^L+NB1$+2eLwnYVtU!?~)Wgas^wd55xZqAvh>RS*dv zb&Ub{R2?Y5z6h%@vMPdgI=;ElHb=-ExqxU?xFhtUVf&3tUfJsjFLlWB>Ro#6;^Vtk z9<(_RZ<2pGIMY{Z4mv$UnHy(_6jIsZnPfjZuzi{;E9q7FC|bN&eNV~sL(I7hwl_QU zGkum_n|)a_iT~>bK^3hqDC!YruLRBCj{ajNm9VM{;r~<>F*QjuC9|<_AsU$eOX?pO zM8p$8(_R7q3?2G#y9$U%MQi;uJVGieO&s^r0pMU0KfXP>( zDBJJ9f4ia#)}MzuS|Pu;CMs<{rPS#)mu%i#f@nvF^T<#^ckySR9kyt07WEk5YovE z@+Lyigy4NcZ789X#R}mHii=bvpW+!fP%{X$SKDs=tuT$E5SW`Wy`T=ixgdYz{bg^k zV`XlT5S0Hq91^Ef4$Y=4&IOShb(|(^N`}x%IZsKL^E5!Q6=(s-H%XjOpsSbNY9Dr) z+mS^A+ww+_zb~A+w^>p4DM|&}d~dzCDH4I7Add9Y&`y6)JBwQstB3tCvzA~Y{LduW zXUTVx>8fKCYfZK*I-xi;MbLB9;C?q)j($|^rtat9(?RkAZ!Y$nY6m}5cx3E183dWA z@Kmxd6Fke0&1@=DVe3Xt9?5&8-Z+4Yk>_Is=)K5* zeuJWAO{atELtnutS+c979Xy8iXBeI0qo-q~uSmJM#+5IeEA02VxyIOj z{#+A17qR_#8|lFvhUY?o!l=k!=X2koxrmd{=9*U`uZEyOK|<3f46`3WB=70(9Kh(a zhS{IT>~ql7v^RgYImE}GHhpaQeC&p)*nF(D3Zm zm&=Vr_4IZzqwMayv{z$070N8+sc&e>?^?&qUo zwp;A8>AN0@{mL-=V%lfhFh+mPM@4qV6*Ov^#51nuqoTgbA8GWjk7D!zNE9N$I&A(NRlY%ib?GvsWWEzyLQKHLv3!l-lKkb zMUftvqT>YhvT$XhnUdv9yrUS(`6lTVpqES*0TKv&^*eDeB(Se$$ouGiOV2m z5+4fU)t!)E=>&i~T*)uGIN%^6h((W(6$$fW-%CmSTo<@$NlKu2R#x$*Kj76N(C_ zk}8{S7qNA{f0rD3(Ywo?q4y?cavWDN-*nD*ieNrQRm=wk^5B+C!7>F3WQ@llZxYEq z1ri{+>5McdgOV&{H8S}6dxCy0&;=roUhWe4V;1~lrLet7t#!$&nq+>EHeKB z%s(g@=kq8?vv__5&o@f)_i~;t(fk8aCC_D;<>Ml1l5$xNf|gRonsNRqe0;$$e-G~S zE9&!Oe7;e>63?&U^M!;Zq%raQ&CBMC=WjC1&*fVlkm7v4M#CwWQ#>E}B!E++;?!Z+ z_Dhr; zL2hB1^s{Vb@2|JiA>+c%PQSlKQ(rPJjN)y4+*?;gal3VS#9P3fbJ>|S8CyG#IG23AsxylF~Go1#jYz8tmqGnKm z5N37V>Phd<4@uCA&bhhq9dlJ*3_=Y(9&_n+4Qf1szJhTM=C0D*Iq#iN!B_C4a?QUu8$o)e78Xuzy_3eh(=d z8h$T#02~8S3YO(f&Ikv^vIM9okoQAm%s#z5=pbRWIp(D?clsk{bZT{cWZvtKl(k${ z@$w2XLQgOHge;$EQf7$r*I zAY^9L(jl37o@+WMA`XDM@j_bF;{aksy7EE=($Ip1gwsEBS3#FvV-0}^?)<|oqIX64@JRp0lR=$f@dG|@5!7Bs0Hw1my_ChcWdx8R^ZhwQ%e6y?qt z`E4$DPH@|1U1QhU0ynu8ZMTf)un}K7?ZhJ9gh?{l$X+#AF-@;5(drBWpW)W z;z}^$-kuXn!vh=3%J+1~SGA9B?5Gs6Nu$S|HQu>)Xv5iSqUGk3gWWbZ+cvVVJK7pl zDwS=KNLlZ?p^XPe+sDG?$dbc3ZOC3Eg>g=z(pk>2m1maF-R*{`6+NH@M5`W!AmE6d zeYnS`6-Cus8_%T{dgRDlsN_MBHq>~TWu(vMxwxgvPzIIvINsAyGc_M^4*Dxkbng1#R%bYAuss|cjN~m z0_H=89?3^8&?8_3&OZbHD#tXEx%7R5qgRbjEQOB*^& zudS^5;yTIDce>nNJr}k)9-5zN9jFETYJ?%80y27TTQ2T!TFBNp+u6}?E@IA$N!Xeo z%DxtDT0pnTj>{^fWx$u+oCMO|jipT`b1W4r-Kmk;1(;$48xr$oor`gDj@8~QV(Hb#F$O|K^jQ8^!fO;}V zy#YA!+>Yhn*Z}OIx+~Vko|TN3@T$AX61a?85iR63iH-_2Gg?Cr`sLy<=Gi~{5G|USTn-te$km9pvapAE*KvbQ z8D<-5$wz(nkh4ekq`-#EGo{Ij+ z^|cui4cX<>wQW7;g>9AFWv>}otLN0OZyW91*q2H={Qk)b$tqcDeNLQfH+mx_fj5n0 zJ*k63Rv-%5m&|%g0s)UP9?E9}&Zm02S+n_*DV~1jex@!`=9L=Vmb%ZQWh!E@I`8sZ zD#|T&Y(00ET{zceiF-=Wh}4`~#jfOIt6F1dEf@nFsqE`gJ-Zv$LRfYwxf#MHX#iL> zXsu2^fJ2=2+H(pYncDH67B)tbHp^H%&;hI=hi^rCwkd>=Q|D~=bc@r>utjc*5?dM@ zTZ%t5lyH_exNYnvH%0h{Yi&~d*2Cio|EN-Z&9?RsdTvtpV7I%!|Lnzc(|&u4*LN-` zM{{-sWRZJ7`R1i{Tow_%7aMRt;HAuY+42l^2JBC0@uW~;h;`-p+m@Ak)GmM|IL0w6 zKITLaenHMOR(=HjbwTc?I3dWodRCVTgP}B+p2?{)x`Lz{!$R1mJecxwI}2LU>#GoH zo+@OSPv@t4&KbMZ8&klzL<+mdX|Qxden&xZ#6WOdRc)S{3xMeGgFEyUdn;T~vu2Po&+H9UHTde-fD?GO7{PXEnvk+Zt9$#8v=283$;u7OQdLEn_ zM~dgF>-W-q6qzOhdcGlA_M*5noV095W83OFIJ!U4=Fc_1t!~hErzxbj!2KVzxedJm zZ|pbgnBE0f`37y+D+$pFmv{qo1)iJNOmaAE3_3`J+k*Y%0izSRAcfiR#>Ru}rP8pE zfVxY_hbW^N$=rs+OQplk7XPYXX+=8<2$VWg?5VP=0n+oR4S=aXCSZQt<`3AqDxC+@ zPAfCF$6Xfe)K!R)W{@h;(M*rzQzHU2(>TE=F(E0^yL0lP781Q1AtSmV$l&YWCH3N& z!~?k%AiAS{rUE8IOoGSegp)*a7UqMv+uPn@rQQ>B zaknScOCbtjB~ITB8Ic19BL+K30Gs)5s6j&nEPX=c1%ecExsjRcG;;&XehKhXJ|b)| z4Al^GKky<_A-LWkZ`n5F@A}UBwQqsmMH(Pdz`0K#B>M zbs*lt11bJYIf~d()M}LO0YtDX6GVAjDIb=+rlAgTyZ%b{}lTGR5`i`0jxWpt>)iz1< zSYrc^J>^0$xA#(fzZ%TNB^~vfC>B{qHC8BVe2|r$+`pEk{qh%hoB8?Ys6OPg*R5z` z(c0US5cdwW4%hs!< zB;%|IsRl#@xn&Oy!~{vA_319C)tpU1sIublc_j}BR;R6vwZ&W08|!?VqmAN2>!jDy z*|P?UZFZH+fda*5o5sKZeZ^u_75=Yx-I87(S?WvKX8zX9N%UF@%-yHG3U#?S9eJ4I9dd6fvR2K%tI-oY zNPlJFT8q5;`TVuA2Mj>adV#$*?0(o}Y7`!4!eBKagsU(laIuH^$|f38A4J^vM2+_` z#V`LzQz3uEE9|OILez5=Dyf>jLh<(8`Y1*4{AQjRL&%t)C&|?!E<~s`6tt|$UXGXe z2faNHg@k=R#-Y6MAyw>Oh6Lv$}35R${Aa zs_sSr`I&W|vhz|E*4rDXCNM0c1REemh6KBZ$7z#=0M>F)kiWx6CHTK47134WE{|FA!y z1ni9=Z<|b*t<`uT%vKFtMR*quUxQz(>XOH*3dH=(fqV{ieNH*gy%CzH{zhT5&~LBc znSx0nIjP9oQ9|bA@K}KA*iZ?9p{hki*&!8zvCS`!%XYPp0JgTglo>!VtiI7GEds^p zf~(8{;r0+`^JGVx;Cg-GnuQQ_j{={SY54p>5xUhgH z`#P`gi5=n*mYha(0|0>`st_Z548o|TR{%kga)B}E>mUdw&*~#FPtWY*6{lDQ0&LH0 z%={jaFMHOrX21MjYD(V?vVXPgKL`KabpzsEwqh@;K@A2tzuF>gR{2$KY^y#7J_Y{@ zc$jIs7{i{e#h4u{sE6L5LN0VyUO7airg>>`Y+|dTyojjeTh!`47o3}nL=GxS<;PAZ z`SbLjk^$w3C-Box89?x;Ne|%-@X2V}&M<=$Z@Eh?M}(w@1o~$3ooYD>qiR7Nd7iby zDhT%gr10RUv)^Q2o4Lp&1D-Q2TRR1qUhEh-V+wyDZPeP zVSzJ^)Nzup5ujsteO?L_rlf=D{!-)fEYz3xR zA&c{>8QN=sFw2_C<@YoX802(g8#(4O_By}UD62QZ$D-FHA(&PIjx6vw4EYXn7kaj< zx(7)hTnd4zPevSaR|rZ?g+h6SjNYE>xi<34jm?4i(*_zkGJoPa%F?CBRoW(e!RuM{ zuFD=@6SR?y-D^&TqkXa1d|y0Bn#$MOUFDr+mdyXGzoXR!Ah@OYZ1y^7!IUqI&Ec9u zp1K0=1V%}+JMEaNx!^0m;UvlD+mzF*xsiBzjWg9~d{o==Z@JyLNR>0)kX+2#OsiNA zj4Q={!Y))tVT;9tJIH%Ha1q;z3DEz9v5enZ2%7AZziIWGgBJ$Oa6H!eNyXbAV8Pbk zw8~O&KYjJrlR|h=fO*a4*00?GdZ_Du&;t)2hJ=LQu$n+A1lgc-z7bMe)+ES=3GGhMZgTpHWM2^7IdkrB)BY!6@k>*^ie}3G(Bl z>c(2xt=vp~(P`>Qk;q9ZT}1-< zNkwUEk6%8O;5ik|l#fbbhcpTcY-)r}p`ZJ&eOyabl{8I`>qVYhoo*DB^K;!)TDPvr z>+Pxbb%v|sLGMp0AIdziP9fLu-*|f4x4oOX`^9C`!bIrm2C_; zZO^D#dYz-v?8w&3Mqt*UxaVEcFo$UiC`chhIcVOat&(mdlAcxj8w`gk+!Hna%3;MV z;GPyRGjk+Ta;WU6tdl1|e-$yu3*K!#HIO`?UmB`g+tSCEbthlZ(e0X=0km_BEsU(E z#WK^sVgD5ozoc32b%_uTKFz?UX<2lmB}IrnkpJdn|3!*&QBLZq5HkB8wc_%>)dU`9 zs>GX6Er3*4O)?M4KIm^kNjTP9(+z1e5(IPVlhg&@$#~3*68n8kDHL|e!O|V99*WW* zhMH1(ZOo3!s1uz*oNTnE2Eu&~yxC}3M+kpo<7I3`vsNY(`|?-z8aqe&sHp_dCisg{ z%VvIYQ;8GxV%TeUxxF?}!~A(&d?meURxa3NC3??GB~k+YV157o5k3%O9jMq;8~O^mhqL#R^&XugYo-JbomiQ~V$fN7!mb!pnp(Gw)^Z2d{3Yp9WFDB97WSI!DBjCj zuB2MTcIU|_JE@vznRMv^CpGbg(Mo`KwqGWHtMX4Pl#q+jeo zCEys7E~MBqzEkATO|daZ>pp4sE-^K-1_yBKNVBhxg3 zr#^$#-6`EkHc-SJpr}T=n_oviyZjL}?n+K5QYC)i6DF9R!CLQ>PNmuKBEbXAdsyS& z{f9RBRCTg8_uKrOwTI^ZK^IdWi)Txx@)zXZ!eJUiHoFQ_N~@sL&6JUReym* zxkK6wi}NyTGiyPQ-zo>1_*$zR((Y)fvzk89cRFjj33QL#RH38LQoT$XZs`e^>7}7~ z#VAoXO1h<04(lbLV#X>_gs14j_b4z6Yc0~10n`A-z5T|P3xg$&c4Z*f+^#!jvASc8 z)ZyVK#5R0WIu5xY{N8Jl6YZF4Mp4Nh+wVhJZ-~8#>TtNXx-1m%Ae*VaIvnhaO0Cr> z?k;(iVALD-`Q(rs^3@QTzL~%x^#~%%;gB z4-oyxe1*M+z8f@hjyi%lVnmuzNBSj8_EhOO+~h6V90_;lgGe-eZZoiF<9Mh@O-?=Y7w@A+K9zc+T4R?Zm6_@%C{02g0#<4<8|9@ zC6yiv!}}|1edTtmEoG6qFbPxp6j!@U`*SYd-znXKIh#}%#r~X+k*#?n*h6Vn9l@?* zpV0zETFKWTAvNi>Y%S=$lWvk(?jU^RG~aIc{1c1S2@Y_c_ys;tUP^qRQvHoPPbY|7 z)bL!#IiY(BI!}y<(|C^anHOEyhtkqr{Fmbo;urr`;*{39?5Mk6y2Dvw{3QnUGrJc# zK6FAjZ~g2990y=az-d~RgzY=q!OqLRjEpphm}YJq)oz96=U4ePSCJ-+h38TCXae^S zpiZD75__Sb*u01!MX4;7`Bb()dlPUD99)k^@5&)S<_p5U*(hw9YP-4)&1jkX_s9;j z>v9<$kh6Q8DrCRLoXDpcx|%dm4|{V#c6}D>1g>77oqBd}7Sc3!X)`}{mRZ3<*%R3~ z@e)Kwfxo5vkH4-cucPD=SP9EGOs{8eWPbX4gL-QYXFi8pv#7kzc}-^01pH?=lB`sx zH^k67VPsAe)q=kuiVD9h$^l=dHjBWm{J!adY?>W5{_9?p@e)>oBY$QdYP-nLmIAca z`x*M@&eA8S_hP9N(5d&H=(QPg+R^Ft@82i6#_n~qBe>~LV6QF`dxgt}n17rr&LwA| z%sUtM>boBdGrh@PWOLw(BvWv$ga9Wgh)LxV>odFfPxhk6B7M}se_(m0YuOR@ob&|# z70<#E?K3Dp0~p)ekY`rO-w7f)Y|`vCeM&(gyVm(}`F`mt!_<;Kt0 z2HtaKL0W}dcVXtO?2|YSSneP{{lfHL>>RcovfugiJ&Sx~{}Dd^k9ZF1^YG{V6Q6%O zABT*I{ADrz79YQp#!VOS>g!J+kK&@=BR4|&G#`b8OLbEKHN5zkMOh})XH+5|DR?O? z3{n`{StayPgGB+x3$m|p5ij=CHIc|`;V>HGgxObL*W5C|hcdP?=!*eU7F+_1Ssxi$V>)fc`&^?S4Bob$N6loz2EtAjg^7(J~A@b7g zyWQ_Q^We%{0cS(0=U*sNRcmWig~fg-Bq<#oit@wb4Aq+(jfI{8{ptL~3ECEY@2O`k z&yvU9Yx`D{zxT$iQzKu^i31CYf`BW11C@^}%Bm;b`ccp((st6WIk8KqM2`2sri|}6 z6=dSl_fEcR&wM4eZ?;uqrp+SPA&lQv`g70>-|;TOmaOUnAK@ z)Exjq5;x;f1>6Y9bF66y#y|?DeoFzCwuCC|lESV>xG3yMhkbUYq%&{#C}8VB_ETto zfk1_ni3k1oh=GjS&5}H3cst&Ux9`Ib)QTlZp^>F~4SN$biw3(g20}(&5ITngj(mRX90xexj@qm>@=0+MCf%z^)0m#$%KBMw<+W~UhuoDUPc(0f5S zc?>iBd_rNM=$b@2=Pt+{LLxVzOY1ZP5ki~*+kcsmZ@(9qY)cF@k9S-hvZkB61K$Hr zg;aalQYyZxdrilg1F@mje>hG}tGVWp$*#er&bsr1k@>#1N3Ibf*RJCn8~Vr38c6Qw z9p65Yq8lqH$G4I1wLgn&c!_fgelO}IK5C*-&JRS!mvk@a{)Mq}aGU%1oxdrYVZW28 zrpATMVT?W~=qJU;h`Dt%7u$ljiM}2D304{voI}(erO}HrzsKkoaONVL<^MRp3~!~X z-a*()6TDxpdIl77qDr3Jc|ooz_*8fp0;liZfOf9HJR)3h3~+lFTe;K_Xe{?0A95nU zW?;-4VO3{UGK)O8qo&z&X3(~(XH!qz#qp%aEN=)p%3Qsb()N*f>u{~h8Xc}`Jbf@3 zx|xhcOxk#A)R~y}g))016Kw;hhV2yynUhN^1HsWSS*wNtc?=dIa9gTiXVxL5YXPa0 zmv6-%sDvs1EX9J}$H&nea-{x!fv+TiSi0+A@#Ni>l&8TP{GC`d=^+{nSVyBS} z60r0f9KuAgG+G(^=%2t#cRafkDDMo_SP#@j5lrf{ST2E&Iev+)WKC0eJlrgG@$z_| zT^MWZABlN`azlHcuiVCD-)McaG}h30#)fzUph?p`M-&u79N#sjR7icth$00kob);#{P~AnJiOgi5Y+DFUIZudHexJ3ig8 zx^3))?uKU;8$+3&4AphwH>(}0W5@6L@LcPT>3w@{S=qW{CbRK`p?RP0lJTU}fKTBt zKGE*~Z)XQ^PJvsChj$656}T0N8ZwGB(Qh0is_+I45_7{>sNNEJg|wDB|MpudyN2H1 z&qFXnK=Pvqj7LHPk{V?Htpv5!+lDeGC@>$7bpiQvZ?P)AL1#8rZSf2XB%60So9mVuHBmQZk*(>Ae;gBbl~vK7NskyEA~p zfUQUtQ}LHzL-i>G@&aSi-TYpv*D_Z|SSGAzwavkBx8QHx|K?$9YLfS|dbf(v?adzZ zMf=i;OXbRziO3U#_}9j4X7+SjxLmMR%ZFWM6P1qr?JUinE?LLdgP%Mq5;WH*JZP$CjPI^j^OLFH@aq(YYeoS`&`#jGM$_U* zBoWW)D!@IL<;u>~MdY$jn0UfuAxTfus0=BhgNacp~m3(5j(+$Hjfq zrGw}(?w3;oFO)D)564AeJCoM=P(7FIL0y5;%PboQy1r<;wKtTAL{=z4e~0xkt94I< zhjo_w=6$N6ugdAM*0Z5BcBdKH;4*S`+@z%u*VTNjboGN=2qaESC4NCi*)d#I zm9DD$Wx$_&m7GJ#f3ap3&P&>0DKJW<4b(<3=v@heJU7y;R?o+ZVA zOR)>e-Oa77OZ640n%eEDiePHj{)qkBl@*qa_L9yk&Msr$`WE`Eza8*relZj*VdpOe zEB`cFR(|_hJIg$dU5kQi(5^x6@)7htjo4vXW{yXM+-6P*R8rMzM&;+Rk6$a+*LvU0 z-6X58y6K8WvEbW2%Fa(_{`hOGH1lSr+>G22(|-cpd>KaG#5msA3a;5BBmis}5SgzG z>jU1!A=FiO_{Jf(vsKWHrmm24NwEZ52cpSFG1NSt@HIvv>kdr>Y*LND zqa#0W3xrq%EhpYuUFW-B4BkIn)A%RY1bH-Ll6{7B8WmH8<&cOo=jG!1@Dvs;n1}Ei zAQ4-@EKMfmp?3eWu_e;$i$qR=y`Xbobau}B;eU`25JzLj7=v#mMC8KpIi@C+Y>xpdT zmY+e=7QXXC=mkdkosVW{6!N=9D}@G7PO|=Ed^9KPU+AJyF_$7clVWZyjeZH#l`<7x zXRjku!3pjNX$Oppt~c<3=)PY?6E5WlaZ?q35+YxMPPIF6_q88g5sZX4G@)~{bn`z} zTE<)YJ?C{PW2triO>NPyT<4ppN(4}J{iE#askNb!Q(}wp+W6{n@A|gr&1+8h_~z-M zhTa1=p5G>qpiw7L!wFUTfIUl%m=kFegesiWsU#And5r)H*)gBtVfGpEuDy^%AeHP$ zhe~4tKU#t|YkVJs5{M?7lAcP7q5GYeJT1PNse z1eAkqv5<{uDMsTC?BH7P+athw@7drM5&v zg1?h+3Ql%ay^+HA+%^=g3h&re9lIKxFIc$0kof(nKs^$L}SUXW-Ls!=nJ6`tR1pCvgLIhO1 zxHd8mWQkV2NZ(=V-%9cre>zpKn{1)_Kaeu@(Vx*RHeDn}0ZB>rT(~BCh(cNoh?~n3 zgJMhJa3bSc7;F==$jbnI0^4UBEUTI-Pj*+Vs`ElTJr8PST=k0@+a_P&zNH>81xd9QzX5A8G>cxNu%qn= zG`3i;CT!>q;6e-X(`UFSzQZMc=|)W2plA08->>+E9T)=@s+7jaHmJwK!UTzG_OFJGq3X+dd85(BWhC6cf9^R*X-b zvjX|#dLwI_U#>({>?*sRN5!sL*h^=mcIm?D;5_iX(84Ref0^5D$WtKfzEo>whTF|r zK|v*x4L@dqUEMsJo-6{Y7^F(1T4Dz-I}iF5zA-Mq5RbuH$-1VBRcu3Y?{L#}_tcr; zua%+e<1>J;K(?sM)((kI^QWky*wNaJr#;XwnrjL zI2=ZO9DL=!D<_x1`ig#k{IV!=nS&Ac!(^5waXR@GGc0;rc(i+K< zJO#5l3F-6^2;JaYc6mO5(6fhx`{f}7#4#xziJXH>L$j*W?2QchV||AXyiLv4eZ@2CvzDaz?* z3mY4UZh3y9KFB8bRmWC#)QR&Vvi;5b7OTtu*j24@viIv_d=mYd4L-)N=kWxrqb7TW z)Pr?I$&%XJLArrpIVvjZ{Eq@Vh#`9Y*ZADnJhlZWw;Lw~-^Q(P{h%=v^s_q!Y7yMK z6y-3e;jT`d1CxIPdqun#d$)*pBA1Y;E{;o6i0F%&@kk%(-WrJ^rS98>wgzt03;C0d zm_I^PU+7{xB9W?x;F(zh{r%$FdUODcMEdGRYWk`okv)+}^Z z^E?k%N6^~RFF(yG^>fMI(R2Lr{iCrE_x-(HH#mBk?7w>=T=^WWk7m&-w9b;SY3cEv zTvq2HFvMVl#s!XPFIp-|y)>$n55b4Uw>A2gm2(^_b8qolR`<;BM@4klEzILBecRf? zv-MrWIECJ>P^_?|<4k?2)gE5-R4jGGW(D&dOa%LCk}INK0Xxy9dYk}$|27 zO35$Kd*Dd-ga14z_|Jn!=Rf*|Ey8gC1Nbv}?s?u0bR4wP%fG+;aukz)FI8{BFq-fZ-S=fx1<@5Q{&M77CdqgClr0mCmX zt=+);@>w0bIR_>6ZZR-5{#nqOoW~j8sa9J6@q7|xAmaNhAl5y{*gL`NI7G(tJ36O3 zI!7zUyP%PljpmD9_rKwbPJurVrGV!_jX*J? zHzEWKG}w!{CVXXo%j|>ni5AX~Qb;@rhp)%iIe!2K>6hr-GEwa}SOwA2mDneG3vj58 z(kwJXluq8cYnybCoCK^hd%_;}c;kZ2c0r>D_)J34Dy43!)nU&gN{x^-C&IOmH2w0O zD?PR%aKGIdJsFY&F~uy z+zVfte+&{uX25Ew$}~Q~`Ne%K)KTCe(-oyLzx*;7>lJ&4nx?y^5RBB*c*|T%c(?_M z5lI2E|JkwDfwdjA^m?vh4A)bSCzXEStzEo+7}+Gj^K&GDZ*l_Kd4U?oXYjdXrcu>3 zsS*qx9YCW|McIpBj9wL<|5TJJus{q&b*PNQ!vGtdjSe4K+q3YEr*L;cJq*Dh4H`g2 z5aPZsh?PI|DX|+Fghi6?>Icv)Se#Tqti3U}9rQ}Ve}gVgZdxHtL*wU!QPs5IcYp{+ znFL&}5Jm`Y^xxnJb@o+8c1#Rp-b7qV`E=jh#-5mzOwR4OVX|gnVc!XB>MvG$%4~Dv z8!BbL4V9BpRf$R{7^iN= zC4e7hi#@9^>`ScfU3YGOLYf0MZi+-?`~q@TvgqEn@O0Dg&i1PLM%I7r%GCLDC*8Jg z@a);$My>Rxr;Kd4VY=zW(WN^kNdctjNA#^EdJ5W2N|XB1ATJz~lMJ~(Tfd|^ykbw> zKG9NzoV_!yoan0U?FYWBX_BLd$GgVf5hwK!oU*L;<&Nsw-bA<&edhO~1w&&%?$|lg zfjmrsI>bxBTi^)>Z-Hh9$kyV!T{;8(umG9v8zCnivMNEKaBL7)0j|2GR1Z`mYP4UH zebvzV4~%sMlnpCyu?75_q?`H%(p{mtePdleM)_30yuPP#vg3REC({cf8}A>USAzB7 z@FJ^AZXI;lRuAt)R_~_X#);I}wq6ixv*`eK=yiAGZ+6%Fr_>M@nKY_j=osSAH$TDlC>&JI+~O;yCq=`BG`0T)BhS&YY|W zpx3TB4CBvsQH1DgD~GHs^JrJ8YqE^GZl3{YUIsKF{1%44W%s=+#$J~F{{_?D73k6d zuOVB_aCNsCT!e`E%3i}OH@+u*r5D~+Z{p!n8-EyFkvPoEPQUz!^Q%ubI?E~;6fK^~$ zo>L={#HmfC_DDFq7u>V`L!XEGygL#J+yU<({qc@KB(ggkuK4`b9r!!uMCv|J=1!ne z>8-;fW#vRl4o=)f3%Z&+#Kq6M#(7rf?1;VeR?+!a>oE_#g>qn3imTC4pd}efR1=x1 z!N4jCnj}1MP|wvrL*W*L>i?$JD=hj_5N81H?33$?%K^A*R-?k0W8#TVF$XXUvVrE0 z&b*E9!XZt=?7TmG5%LS617`$ZL|qK1;c!f2+a&TQfE!$ex0Al|cf8-M({)$XkXg?)Q*QhKEWTB||b< z*x}DuMr{UJkll5%K!;QCtK{P7C3bYLgrTY`3({wF2lv!Zp*Frh8uF2sB#|a>ZL_x5G<8|{^1Q6wY@D>nxDA;crOz&gY z2K-kce)!5rr0r^dfZaoMH^bw0*dpjJQC{jxjgUZorXxhV|xEs$Eu-q^!X#`NVly!0WLdr zU}|b9-7wXD(;agI3wwtmM+Er>q%5rM`k zk4hHRkTJo$fT@XZnET|wY>oOF^;g~awkiq{=JfC$pTm;i3`JnW6;Z#p7R44p4@Hdq zBHsP?>Pq7e#lzuK!r^!<96s`gaJVKKiR_O=;t#_Je+qs>tPpEmzJ7W;_IDND{%*Pw z!mDujxtm9nf#af-$S_5rmx2T&9!Q{^R*c1?pNipwqQpj)y%pi@dD}1XLT*&UElO5R zo{vEunw+viVM>|@F&*R>2#@*L%c07;yVpd^ba^Uq8Z0|^OuH<$i6lDm8?C_`gIG6Ju*hGRMqRrQCs_mxO=~i1kT43!%JIX@e>JIK{fdiu zRprL+smOmG42?Wp6L&MspoOjgMG1DC6 z?s7zA0uOVVQ?F2*R6pi&c}8;u_4e#24G(T`mG4PMteH0=5$18MY3^NW4@zdV(+Lb8 zPu(YmH=Med@JPJ-#7sT5`GnTWwt%7k#Hpig!-@x)uO{jLG4~$eZ5G-7u;x{@+$2kK zlWf_RZOOgJvfO(dmn3$2B?-ik1}PBA5^4&)FFmlZKXtWc%c3=FDkx=FH5Q$aA3Qa(+Uz1r$xaUP7WS znjR*XMkhDbc!~n?*RH}|2{}sG!%4`VTxprrF{;-3seONOQw6RaENm|CuYXuGJzRA} zTdh*+C&XMmLG6lwztPHP=W?EBi8)d_g@_XoaZ{J}Fp@)AXVs%F&7$Qqy=kM)Y_S$7 zD$dS6HaolcDMYQ<>Z$(mTIlgyv*n@(x;zDooJOj^BL9{Y+W8YFw}dW><92k~gl|If{U5Q}1H%w| zl)~MSIq+=;mFMiwCpetlZga~tv zRl?|I{)E-fmbk6QgtgEW@tch?OTcWPU4LTiV)=^p zSkonvqx#B(q+7t{in*Msm_wp7G=Eo-oOLe)`Yngz1yS}g$C`;*RKi+XCpE&~)zQtK zINvIE_S6^>SJIRXeQm_)6P^x-!BMPgGg;*vos+n*I-bG&{Jvyb^ot+@wGHA9}_g*WS%~$wb z0m2o~xm?gWM?>c>9+il73aUPFUo1!@%K?pkSPtDJf>Zg=O@$wXil*h*gFnYw$d;&t z+xI_ZEN_Y3Rq&FpPGBT<9p)V}-OQUaFjG((H-z6n^3kx|#LWJ_ZL^RD=)Eg}c;M`0Ye&oa6kqdvsK? z<1o_*mmkGN_=Wb(e~Y4H=v9w7uubZs`j2#fO+7ax93IvNu`r$DBQ-GL=Uc@2J6_sE z3Eq?Ol^8 z!)~;^>koEp#Wr+TLEJX) zyTS6rZ-4vXf@*`I;8AFY1C&og4j1Q3O5*M|#!eDpQ=bl@(NSdLIIf34@DnaJvhH6E zBY0m_(}|*H|Ay09dqIUw+-W?{l~qAk8h6l@#@Yu`_B>5D8c%HT8dkV)qj5#@iB-*4 z(T&DG?I1mrJJf<_?8;R z^T0a0q{?QiieH2PQpQ90b1P^LsR%U1mLUhRz~MK;*+0RB3_7Dnb)CFW8=gP}N5cM6 z1d%wVL?>$#6-`Y#!+6~eOX@(Yq1j)1#aa38j^uao_h6u5`+3nbo(EPml@4_$v-RnQ z{56#EJ5{H;Dw{`wU8$f-$xUEQggi)zpo-#WC1j;Fag;P@(OI2kep-lcMf;F58`*=Q&gAQfvie!b z19VkWdB2QaPV6+#%6}8JRNj2fNUDJ{2<@Gz%Os>GRDJfkimyosrvAbSF9GZ}M?no|EY<+)?oohUv0OfFWj@Mqd}0Nk^x z+;pG`nVrIiNpBV6LbySxRxefVu*|P-+;&^8S>a;_9lNi=tToooNNaRrN8< zFANok|7(`RF-sx5+~Ht_3tdji7cC6DL7lt-ouv8gX1Y1ePw}doW~xd?qZU5JsMMoB zrSQM-Eo`AEtb%i#_qBLD*J{c!+>Jw(ZTwLTKQ9`6B#v+XsA}N(bfgx?KG&o0H5J(A z5{dNjJr2wi(HbsOQ^V6_6Ua#wvmfvM@Fd9x_Zi7>(=s4|Zhes@VMKh6>+p`MFy$d^|3vvcK|^dodW# zvdCPlg}QWyLuC%R>!LX~raeGLdz;WVq#V4 zj&g6hQ}Q_MB_`A(Ton3GPnpfHEkH87-e|0}86EU6c1lu~UZ2yG)G_JVv(*?sy(EC~ zXH7K@Z6@SD+n`F|)Ze1xni+!WW=L)24TqIGe(G();hN4UYmQZhW2#A}chQu$19E=q zwZgvA>^QDK^2N~P5WE!v%MzZ3M1Yg1#c}a);&Ep7(OhTdAe~AcI>gasu99>h`76~~ zX^)P9j(*VLfJNc1L6i<|Qht|+ViY3cH!j)BgU(F67v*_l!i8ML2(ElGZdpYm#$4Bc z5%<9RCq$<-mr&^^?F0}vcodSrrn&ZHsJyk;Wv6r5;SK4w04q*6#IvC(a1%~+o`9ns ztS+#lj81g6Tg-zva=@6D7l-5h$LlD{Azpw&dW#2pNF_?}tgwOz^d&H4B2CQvEct1$ z<=lW*WsEm)w8!n(ZbJW56|-FFgEqU zN`)z_oSAg?cfx6YMPX=Lit)@lX$dUG5sWvBc%@P8hj(w?JNe+zCHr+;?t$wDb%nk{ zuueMBNnS#kx4A}6wVMd8#P2{#erG1`T{lj7Q9v=*i5Ea*FZ!Q@{^{+T3H={x-L6^v z*d>!Q6Du;!g>RlhP`4YD-nF}$>TV~E9x`7qMjyY4_%nvjnJ#s&QZ7PFI{q&*@rIl@ z#gjOGWmjzuC|DrIpFqJ+GeA&Kxe75XWldsN-lKowZZd!45MCjX1ET-Pw}@%Szyaj! z4i!ZvMCnRif(O*`0q*%CqHHV(tW+4Y5009IOTfPc(I9YxD6=#N77Yt#Oy;rmOErxctTGRw_FS zOPL3{vk*sNZZ#&-tF6K?qs?wF&&dzgYB0#9#0v9}% z>D&^aMNAD zYveys5b!6KLbLwIALA3Z_0dN@Ua!I1I&@0FsBP8}{~)opdzSN184A{UJl$71e%a@C zUyaABAE@_uE^@nrKDLWGpnNRQM#! z#b+^Q8Pgu!=STX-U^RVW0#%Q%ll{=aZn7Vmz$oust z#QC-Or@BNCJIPTU_MT+fALrTAP8=EsSnk~6Ea3S$io!ja7agRYG*WB(CSkGjd620r8@&tadM7eISB|zJoi{^0D+=$W_WS7Tj21b9q+dW64 zIb|{35Ox#O8k|tM8@qE9?^r2g?kI^S%c(4eGWGIZ7bU8pb16_*I>gQ)AO#L07Wgb> zm-ROfA*f-$;dlOLm5L{m?0P4v-AnnY$)$*Ya1TMArU`q3EE%^D20Lc|Nj!~}E#7BB zsF9bN=C+$N5CY+5LW@I*d_ea;&}~7yW8pWG3zZi=&SGBw{ZC-WDf@#S~R@94T1JnC9Om8%0Bo5`kQoj==w+?R% z%xhnGR839*74LA(8e4j^T1FCv0D}atMQmxM?4^d+l=$Nmse#)6g7Fll^3W|N0i*WG zg4!g6o#)gvy zej>yFq5B)b zi)6?GH`M8Fe2Gt=a3z6@+a0|x67MlsfAtL(xKUb#AnILp{k3DT3s~$~ZugMo4t97f zFDBo@meCqOvDgpMZv*m+C2TTvWqe7R9B?b{to?&h!qT{M0$0Hv^to}rrYzIMG9+Rr+6W&T(oaehM}Tr(pFbbEt*K5FA&xEFp$aPRxoJ0_}<#B)oFD zv=-3)yaj&xR^k;3b?+eQh;ReAD^bah*W+iRcjd)kNDT8B{+%*jrP5i5U50f1XzN1` z#To$|Lrpb6??YQiTt#u8fppjDR>b3q@#tQT;ezL)x;k#5;;b(!ucHNCTb9#^d^|^(8U)z0sQEh&2MN?o-wYR5?^N#aFkuRivF6XG=NAyIr{yYv9_rjyN(!V&A z-+55^j21FE6x@aUwnHYHb-j@47aS_?Q+>mszXdL0QE*@2#@f~3YTDJ}{v8^yM2D(+ z+IFQy9QxnUc10bBSi1*!Z!00mA2scwus3K(2EDT-j*C}UBN zu0D8j=%^94=@-i;yC#XCzS^v*=7wMl&lgjUTdEI*nw@#IYg$TtJbOBf=jg}EZ8JO` zq*9CKdwyZRv?S1Hn-iMGX7Qk6&-@zi%94EbuXQcQrb`)=ODzM{VX2oQPpU6T+K2@) z;u+M*)5aT7@1+5fN}ut8NsxI{Itcmo)gMp$2k;PwG3lzU)3$P6RmE@0ZMI8C};={r2Me!rrR3 zMfF9!I7}=~an4rwpvh0f^FZZ~h6l9VW0~9Q9E*`H!l?J+!c|9E<63_jE?t5JzQG2m z_k^mzBQB@HfjPAWt9%~Lf##!H%h7icEQm6@kO65!oXA~@ER+m|8iQfg0pF6 z%gm!XYiG91TGLU@22L1knKy0aiGwZk`{aeb9H(=O)0y8CU<0e$tB0Fs9o11i17SDS zJHHRL2l$?f5dmBcqw7zJF|P}!198v8?6M^H%a3F09m}xC+}UAPD!=>s?4(v#@-*n% zhoop@W%Av#5l#qguY;7K^{TeJ?1IChi$kh87FIG+iKOC3Hv1D)T-~vQg3oLmsN)I_ z4NrxA&67H@wnDxz)~7~;)KbPGC5EfLN}e}V7yaxzK)$^ zec{S%znkgTI$bM5c03XG*JP8eq`sy!o1HkL*56mxE%W^Z*4o^W3vYoDy z(YnHJe<|O>ismmnL4_B!QE-NJvRX9=;K}ckVb&>C+ zQH%vjO!ovP*s55wPZqZebH>UICw7n9m@XA_-{BqzG%c(u+@K5%CXH=^>?;>$ ze1=T=*)5^G-n!A}<-56e<>h$BK0m`_f?Zdmx_YV9hIluZ&Ux?}uj2JOM}mo)6aDJH z@Wh;afy0Sys9LRU2ekGq`H@%*$oFcj`f#lwtJWs!4<+(LyWKz8T8cPPIaX%F{o!Ar zSOi$`2ao6MmczAE-mc}vc|BYLe1q0rN3W=n}cqxM+NFHrB=GP$!`mpxs8L8 z=y^i*B)7>-RiLp{e7>-3=q|VW_Eo;Lw!-3v;LqowmVUbJh`?@tNey$lnltn2JvNs! zR8rSlX*Ja>yH&iZ0{xY`r2+VGa$#UF-<9JfbtrXIMWHe(m{_ngspg=?a|)Q; zr1Tk?xxa*;*?B^!w!)v8nbeRryEt{UdDg0`+>P#>>u0pgIcmmCd6wH1O6l~avqjsF zEzEIbE*@^I%SsBL+fcf(tzt$+bD;E?j@tg|@~?`LEDJyox3g*Rd|1<{UMRuNlteQZ zjL%Q|nQX6^-=U2tt>YUC4Pa)+e0z&KyFs1VxudJYJce1FTp&XS62-cBOT7WBvC2e? z0uR6njGY{a$f}Vu^g{;`;1o(Fa-q}FGURj)v*sM{8&2mNEh+jFmbTS(I8SabZ$6RX z>LZ))bS*1N4@^t9!>v8$bp2&kl~=sog%Nv$K z&1fQR3N*~EK{VyQYDFM7#o;Y#uobp$QiG?N^~H<56>L`dDNbicnn~W%(!3ZPUINa3 zD;>tIpSMaZRFsVe`N|y1_djTjCSp1K#2o_=f~ggu#4FuZ<;&dJD>};DZN+7yHMtgN zpkrh~qrW>nz18Om=M`miKMpqQ>fE+-dg^_Fa!+APp{piSaxQl|Ypa{f!W}iqW=}_H zabJ0+QF6E{=wQAs1AJ+LZ^FzMy-lfgqbhIWoE94|Xjr|tsdACqeXHAD5-zJ>7O>6a zabD5mp_apjn+J#~xXQn0C|J6(H17yVu&-JCHH9Bp2qa``B zX>dn_Yq%??KVNcW6!%YWX)LbWIK6G4E!&4;`2nXTrKWtRCpACCZmal3ZTX6B9%sNS z;=MZ_4XCx?U0T0HZ{2WOw7@mJO*4;dqS>D`r7uu7yE-4CFU8&Lq~&dOvqA%ED6phD zx4WWI{6$t#5qTChx`&i#*O@L+ERPAlgl=JF1+&69KC12?WF|UgDSc($(Qn)E*tcsdPG50Eg&xG;&wPUx#X47LkcdcyU^zdODT8J4px!ns&`~&!n zYWvK^?K%dxLBF$;)`TlHTxqSTH_Eq?n`TR<1scRs0Nm+{jHB9h12nV&3ajy;eja_2 ztKcsr!Hbr{uOcAjnqyYHIRa%VyS%XOQaH~)t*$F~rJ9qH{OwEq$=#*;KKZTu%x7=z z^3<9~T88gu)%9%toRu@GovzX{_hBA)K~k})`lx00FSCxXKeI7&aYN~I;7K=_(h=#^27H(K1}h9R^m@mi8+3{%q%|1XOpp#S_Wx5FgmeQ z>8QUt+??k!d0WaydrPz03j9O9jOL<%CpR=uo*T$-%&<$d%d)$Q>-%brrs@+$s%&Oc zS5dmNu#FYho<1GI@p$_G z?POk|dwh+AtumcnHywPibFHiA>lLy>z64fk1FBEM3Dr<)oYHnWc`LsibGzA&`HbRN z$v&rX0L6#oA91XQjdj%YHZ8yrBWCh=Hmt=eV5qENVQs-1OKS7`E17dmYe1hzx{#+I zY#LhB8Pa3X>2&#x!;OQBYjgGTgT}7%jcnL}WWu~!oRO38KOJWJK16rW7)@pkjvyg< z5i-+MOtDs$>d`?Uj?FZ(;iFpvBaPEH_ps}nPI(Lj?(^g{FLOGV&1?R8ZGPe6I`7(I z?=On1Qr}Qr&#K1aMP~<4dD4aGB=G0;&HiVO&9}6c)*n%vx;O_~9A6_=uUiuNn#qX4 zE3v+z3MYIPOuXTeMJFbRI*N?4AS)bt1xxkH3d>9JnxAgHG~C?pu_k?Q3{%u>h3A>gZX++u*Mf@YQ38a?{}Rht?ifsa z268QMc{6;e=?x+Jr6@JMz6m=V!}Ld}p{t@BCX|;e^=wQh~Lh1 zIm?>*`anqoUeBsx_wjuPm>D7jdU93~;lwNzo^%umG*=@V8m%eJbTk(f_txSLFs6j- zcDUUi;bo=fZ1;+Oc3*dO_naJk&ieKuM|VvPuKCefGd$Cn;c_lKoV2R~efP7yN=}6L zE(XcXLAk>tJRym0%G6YI4yC5XCe2K-y~s>GEc$l-&t!=yrYi&;y`V$Yam5j9sZb{% zv(`z270`LEH8pDksaQBJg;##b0G-BsjE9y~XQxt8%^S`e+N$hhDpIek3 z_IOsZqu~-RuW@9pn!`Nqcbu-);qLrWc76Gkh$4Sz%}!c+fk*JaSDKD-(~He`Y1{|D zqGrwEazlI;#wCskxv1%$EefwkH}oPY(Zq&5muS<0w>udtRCv8)xP1HoJ5HMlWV%x^ zw#P9>2YzC$?utu3xq|HRryrI7=5~i$u#fgMn=XG;1{VDti%#$-1Zm}iYDy_WXX2tM zb%HR*C7cv7vEHLglffuB%%Yauf}WOC2ZPM8&J!Y<$@VUBXUa0kk;BIb@$6{WjLwgGxKbykkxxw*bGVJL2QQuW7+&%kd~#n|V_-Ot+vS7xh>TJjDyTtv znv7DM2@!phCzI$JJY+XnCg~BE^O8)*uarE}uR6+=JQC+T>Z%=@^P+!|>YJMLr@P&6 z|0LgUFaP6ANPG}{cd=V>i=4DHPFEmj$>o-DY;e&6kLPse^xTQ164LIj@#pbPJ-*ov zis5HV)RZ62S4<=^sIJYZZ>&%4*X~WKMFtvXqa;49=7wT5W=y){g>3%8Sx z{{L@ikRp*n>`hE&xx%e}R{jUFT;l$SbT}-fh2Hro0heR*3NHJT0O&J_0tK*Xl7Tos zDN-g%lt7~J7n%J&X~aEa+KE^c&Z%kZwK!LJO>VQP$KpJ$_vo%#pL_MR`X2M*Z~%|% zV#W9fxPTWyMpvQ)@5Y{zqybBk%VV_UnA$B?d%u2m`aT1bKvFZJV2tCn`$!RC#o9R%(0S``EEDf2dD_;)(!79#HTwWkDxgeONrJ`EOf0mu2LW=6}Pw7Dz|2_>d$gmlVa zrO-;cH-pysv09gtgrQiXA}+-`MQ9nqi?u-{-_X^yImxTi!gz;t&WJJz!bnHw9+87r zSJL$Gp_xgeDQ5XDyr@2d+iE#C(Pi=oO+mV)ksfvhJPiJzBdrKMkSw4D2la;!LO)p(XK-$H*8X%Sa2u&i{y3B zn0o}MUC=aRi^p^9(uQKtJT@1b4_kb0mqKXWrZ&GMmG@M)%df+yEaM&pJx=F7aWDD) zFr7m|_=?_0Ams8z0zq9+MAuE5UATrL&F-APu{T(gQhMh>hf_WgNriX22J3o$QJe8c zV|JR}y0IrX+Oc4yDZTVA(vtVPhF3I}9D|M&`~AteccOc3oMi6Rc+{!wcOK2WOm`R` z?ekPE)ClEJ2Ilb5vJo+oldFtbFG*rRwI4p;7byKG&GhjVT+bh{^z}QP{l#fXY4RYA z!;1E1L*7^~{M`7P>!fz(m=K8vLkPe{Bo0g4NE=9Q_nlay$Kr9kIw3#K<8d2)dy>cF z_|4@M?*%_WF}W0#ZGk#h#ETQw260Ch%trpsV^qeHJx;Px%bQJ3%j}K?5V?Fr_80AT zA7s5LnE6&rz-^T_hja`{eOgs=PfZKNeK_5QA#ZJkw6TM(#5%a^!%dSsO>8+nRZu*0 zO<9^W3RiR`s-catR(F19c~+@L?v0fQ~!y$2o)OydAYGnx7}JC``#TJ4Y?4l5~N4JJ^2Ac10K<98Ik4*`8Cm&BnDo z4?)L|ac%{%_IM4}s;eUhsBQr=E(>_Z<>$q&8YYXLvDlgzyK4A2nf=5fSJ2UkN?-My zjv-FRFCbZ`h^S)z-7jLcta{1mk*`BUg_QJ}ALSwbbh5cv&C1*P%tW>`3VvZ8)y_=O zNr~$Sx6oiG6AKEAf;2|)fVfG9Klrlg_SiZ$;I~^?G?&p(AN!YJh!y3!XVjLN*j_AZ zIY`$hAJ@c0ct1RtZmHg}K<{S=?7D9hq%3I+IzAJ+l*B5!-_EoUYD+Vkda5 zoDPD_=YZFgpXlNFi6ANxqUIJY3q(o_bLZq)3G(3aH%TU@DY9m^hNj3+%&lp|YWx$F zFhHtet|LcDRivBhDqC|VPf`pmt##{n@}}tE5aDUQDtTRR^;jDURx##yLI<>v#B=H{0PTax|ox@g<3+ zN1SXh@*GY?Akk!0rY&{#NwrF1twA1@nI`5k7$$t~(E?AvA6X`r$??#r?i%#*q|!$X z^mPQ@KA~lQ!rzJio=Ax=0skA9S#lYSoUm}TbC=?u8q06a!u?p+Ss8kp^!*g%w&9`*-e$l%e^Zl0 zI)1gnY1#$HepHq!NX*NEpr|wx8JhU_d(|KculAlzwAG?}{Csf=>W;)2GLXh;TqSOic{~HM=-9_LxRdNKAe!-1ynqg3}}* zo1PSee&K>3&+x}cG201V7Mn0B2x;$wiJcZ7lz?Z0vxD3)l zVfTWw#M5}||4E)E%9Zm}wa{ZVhO9O16VY9i-K|=+iL)2dJ>4JJAWNfBC^iwzwZ%z~ zrD=mvi)(wge)Zw+aXQk-&R#_q8```WUterwg`3LRG-7Tq(z)+_4E~%K$B5D zCfzRR7+=JH>KIO@d88g8^F(e*B^qy#D0OVvLtBm(-*l)0R>nIr^%o^|h6BAm#F!IC zi!`X1lA_~herr{RsWi=Qt#FtVe{3m9O)s~bi_>gnb~CG@pBenG3^RC>Cf&q_q(4ut z3qsTQr}Ss&bo6hst~N}a9>^1sId)6yv#1CsohA^biJ%HeE>t9hw=MEB{7&g(m2T*c zzqHMnWMb|WPE$y*d^tPGXgI|LsQlM4yFrC+JH^Ca&5!^ruD3f*6MAvm;UP&n#gqg% z!$E~K+i61Pw;k1Rib^=Q>mZRyw1-RnePRFOlhR zN0i6BOiV{L#3HllT4->8K}Kk9n#t<+S+fU4x3e!vW5wjz(v98)#d!^$G=tvN?X~7v z&Io5FCE?72=>NR5^h+)w8(_9GQ(X4;B8{Bj1zBwLf*<@D6D~5gQ&xxg5Uj?vSn!!W z6di1aUOr4v1Hnh7Z>MpFCs-Bg9f9GhjfE(UNB@hme}&e((^8K znPbp~u!+}g;r^AKdVGOZ!9% zTPz-lEkDj=MTvF8Y1iGh-d)ISqC@$`#>^xu2+A;8JY`lJvz=!_#agp*m;B;w;P{=o z_o7l$gR__?3392W8)H&C0A}OF;)}{~NXH{3>|2Zn@%vOfR_&h6J2S^9zRAeQ{8q<7 zm5H0P^JPWfa4td69OW7O9q&WQ7mI06HKw7urmgLiZC1^SRwkkk1_MApl>!Fa?ZjBl(kBd=x1AVD_5@fbD z`D`ucAckPU2<2(z!)Ga+d}vL+=L@(-!NM|9&KFruS^2P*n|$`bJwG9_7$?$9-c4e4BW%l9o0VMZv`HA4* z7vxPoC#?)v9mV8f*#5)vOXR1xQ;G7E+>F)-=hB`MW*Cil3Mmr_E#M&n>dfOW)vQTd z6dm;)9urx~Z55-&q{}Z#lkQ!U4-)bMR@;t2FZaig@SPhWJ;A-(E~pKRn9fgUd64o3 zMVSY^o(q(zNYPO*#*NvRUZYigi-TSb2|I*WMg1I1c+nXl_;rsmy__-F)R&!WE?U4{ z?9M=HWpTIsy%16vyGW>zJSgS55yTQN4%L1HkXVO*lag?l)1 zP5w=y_g7-<+D|$i^%cs9;^AnX_ zQ3dK^d2cV~V%l~<$Yrq-Ky7EXi?c~M3vQBU3+}N!cNPhxezFb72bC-LbAO}lDGNLB zy#2xuRV7ylV6(4QI=bZ+nPwjsyGedX0WsIPIn>wuU*0m04>p(0DI!2GJX>9)1l9ic zqrx_}4G@u$$ArIBy|eI^dhPtnmo*3NddquxYRJQ0t$NRRxS$?Apnqqw>6Wab2L; zZLC`wZR{_$Kfc%azew&svQ~C1UT-ntkD%FvWuS9;o1wuVEgLT`h6H|ve}9?(J5HlI zI7XO%KFrbf#gND83uy7p$TjS2y^~I_GBX{Xa3RCw3bV7XMd|Zvua&y?%IW&8d-vAt zJz+1DPPZp=HM>>s)|u$M1|2x3^PA#}4t&wU8uRk=^ESQX@x1fSJJQ>}{yh=p8<9?xq1$id(0w^A=L9BUNI5yR|>A|Kqzo{hst z9ImvQct=O+<&+%6)yeuCgn-F8PuA zS=}CMN*$+0ex}BiB@eN^KD(J%2CD7=Z|~(JrAGBG;;zGQXZL>Yc0czVnygpYVy9{G!_J}xZ13D-o{q|)OUCp%AkWC{65qskZUqNCf zBzF6mHQRRJzi;I)w$<#|xsBTR1Z`|a8_;XshWg#j*tu1{hfXKOH$sA;a0vh5*u!SR z-soP<&e>73Z72R?bUQ;sA-9?+zG6MMbK*Fe?3pv=MVfDayRGKT9osZ*P|nbdQEJ*? z(eF!J&K$or?%Vk0O&Hr=g`;M$B+RA2_TIbuwR_*d0fuj0d#>uh>)#!`A6m$Cujsb0 z3#AV786|!gcNV+wnP+zG+Va=G*6e)<|9%TvdjPGON!L;D8?Pg>2mJfo?$zIZtKT|) zD{=E?;5?{z5sr`{Jj8?l@_6>?UGksDZ`E)8?w`>27#58QzJYea!d&LS&qV=j&o26s z^rwP?LT~hoX#Y~Q|03EapTduagC8`DhJrZ98)h%QZSuQ|i``bk(|Xsx(^6|v#{VQ$ zrBqdArr^FjQZ{jy+A;9#P7MZ=wZ_cde zi6%O*orT_BaCNv|D0q3@`d12G$gj+Qq2QIH*N=AFY&A9Qxz^L|1z4^W71@dlYumG} z!&d8RHp6I?A7FF5GjP^wo_xR2$Y#oS=g$}}Snv0k4Kqj5d}&AM^-UX^oAnE4rWL2A z*I)%oK2r4;Mx8~KipIIf^5^n>(D1*1D$`-cC^qZ?`pp%_jwBwt*Ru~2@vLTsZ{;N5 z-}S9Dplv;w@|Z?nh=0R{Z|FmQm-;QwzSV#DR&LR6edC|(`SG*Q{_Z^VbT4Fi2V{w? zG`BqHHH;Tp#dYtFjh>C`)^5NF_I1~9mw&;|-d?kHYxOpEo4j~i^;Xi?zu@~@AW0X< z#zK`$192TK#$k_k`aDt$;qP$C zA?hpH3-Z!9KhC`q`AEelD;}A>ppgd6vY>>EI4WUj)wY8VY^y#~KZCb-J-GWA#*hl` z`spdyEDYRl4`;E*PR9ZF9jBkZW5?-7T)9iXb=Q?OSMECa@vbY;!wvY>Blwm|H@d*E z!|ahuF%!8jm7ct7e5Z8EwyHDUcGW7 zd!G6_sQZvDlRo3KxtiE%;HJWsd6KNYWPK4X*5$%pO03rM6qKl0P1Cn-mu{RrA^nwm z53@fE4+lX!aoHu#jm*7~-Fn9zS=-rN@?1*3N5`*lnB)-5ijKbRZp3XfwpZ=EgK*VY zgvWOrlbwxF5=uOCZw-$>9>Az?0XHchoM_?HGB@&DN~|d`9TSZF+H2i@M9J=Yn6~^T zYPyu!?A*+Mfd=KJFdgz(>a1wu`b@>09A?anVL#jZgU9p3_N8yUzVmVU1K98f*Y5i6 z;D_H`N7SnJu1c1>DM(g{6IjhQ`3rpIBtHA&l{IZIZaR5VqUk9d<3C^VMwcB*CQ(BP zT$aU~B;}fu+*WQTXqEM?G8y{1<=^UrzXlHONE2*kLw7_JU_!@4|(>>pY&*PNV4k^pTp? zt7}G1r|(~WIelOC7+9}rB^{*663UKgG$fVG>{;qwKds#}*gWE1)mEc-p1NqrJbsrn z-?)74rjus28JS7`F=^@arPSgHd_Wg&r3@7rWmC6D^d=Ar%y?# zC`mIGQQ)b28{gZ8??Ee-2$^leMaN4euDn~h<~|LatAJzUI5gcW?PIv?s!Q=SJN}=( zAzzRZ3|Zxy*L%WZZ%a6hbOZZZS_d12)gw9%XCY8vUqAcov%BzrZ0Fzp_Se5X zgoq2T?!u4iVD;&ISH+y=gChzfiVJ5U45x2Nx~Coq?A{%C9fB2ev?zx98 z{P?|RpMCG+kKbj_KFi+y_|;cmMPF*%qxfVV``9V;(cAStyD(Ag zJ9tLlBS%VFg>eM4r1mqmyLX(y;8l0%)5(=Spr5hps_H9u?E2w?}6G!EcR`LScXRNzYXRcJ zQk;OnZUy2)l)4O2gy^UEkm6K|5VOpYv;P>UQ=-ESr^=0 zaKlXZ%o_{tx!`Pn$8*Qcn!CAuSFdMe%f|UVtC@7fjW@20=vd|ryIG<9&!zX>w-k}< zfA7AYwNL*|^Lb~U|GT@U%P(zu^1zwrZ6AAl19VxnPa%C5JSrj*MDb!`L#&3faxN^M z%q}7Xzr$u>tNg!pfprH@!~fyu>dP-Di z1atW)4u;H-Z*~Q@H3eb7Ex7eR>>g{cJ@VesBE2+!{H~;xbJlK|)nbuego^f6Y_*JF9E3t8Tl;Zf(vJN9_yhMpXb#R%zjt6W=)}d36tb>wDTpK!Pc|= zJQ7Oq`)qw-nk`^AiBEQAm5Zh<{z-MNzSQkt>!lo<&u|nfTs7Gw{A@;xx9Wb+_DBXE zW%#pvVRIPmr(1KYQS>6Q#{+5`8uKaQV%N z8bBu|uVFH1cHz#gA6Y8WDzKhG5a?DT@ zxStfk4G&Z=^x+(dZoC&KIgtqCCp#Td9!}8`+%z5p95oLC2e+g=s!Ap;_yJYPbR`^` zi8IT2(x<>)5cx{C6YyyQJF*pUYJEZEhw)Q1`0D{*Ch*6P*5E%O@KKxbhw0>kcfwPsy{0>t_c{;IENMAGUqS6P9VR4&a*Lq+E213S29)YB zP8XEJ28ik#Y)&auxp`fsd+lS)6hee=f%_ z(w+Pr)%R1eaZ3@c1DcNwk0>p@qHSq9M!#5t9aLzUjhrB|4Y!)tHWJr!2cK> ztA%r`w~@H@rx;&2_6d=DC&fPD5e;@EkrwR1aXtpAt~De&9g-tjuy7`>N6t`aUkutw z162G?3jSi?lLn~x#1~#6`YZIx{-(4}z4F(ae}F{UCo#%35-sDKwfOUkd4YxdNrr;=KM}%5MQ3;?NM<@QaqI_8w`yqCtK|%g4E{3=3>%IjSv_HtQrl zMg^b4g_e(VxPq^?u3I-*>!<*EFs}8vqIIlMH}G1JYU>0?>wq84;VLypDb&nQpoZW? z&HRX#n$3|jc#UqKv=|qwG422lRgHY!Qq?XT|d$9MZYIRo?&6&Un=kcKd6Tv zC%Eofz<X78w7^$zxWG>a&t?lwK1ZBHDhpaE zpxoO%N8S!M+M-bIr!lH{TvU&g7D%Y5s^Vgdv*YwvX_?^Mrd7QbZPV$Vdd(bA$9p83 z$)hTk(t>endp3t=qK$gdwlV`K*u+=SwxW$H{u2T}Is>Tq;4R?;KF)cl;`b`;liwj8 zs`%io;*Z8TT;TJH3i|sL?X3g;Rh&+KlOaxfAL4L(8jLBBom_~Z)+&aG98FMMwY zc~hK&C3%SYrDO%Y9grQ)$P!evPS|8ilVP9mObi>Ago;qyl5QdSV^^S{6k zMAl2FMJnus_uHgUj|h-~znJaB{J)691CdPvpU*}V7pVA~1iqxk3o3q4!6$mCUll*7 z;H&Y7ijRsD`pv@PbpL?-L>vHa!h8KU#f*=x1QhlI9tQxe)gK|K*F^vqbECk9M0D#Y z3T9XZ13L+F8j&7=2VAUM2ue^C3{ce4L8Y`J4t*X_%(8?FIf=NN^p51DU<2MleBt^? zaDk5nj?^b&H}W5J^Ca3f`TpJxvVEL605pcny~hOH6P`)L(ps{vwUWRaSM^M}DG7eo0|N0H_81pglxSd0f1N1ZUuZXpYZ-)uo$V%X<<2xL; z#T0D7KU3r*oDU)KhhRNcKzd{sOEI$xcN( z+y?Xu06$8q)m;X-ich`1#o=>xX$km%^BHh1;5&G~oJxHghrgtI0`OY|JmE2 zI@o0Ry;vJ2;2U&;9@du7{u+gzTN2v85^&fZYfiwYb`~SkbaM=!+i_H9j24A@THkV= zF+pdH;0m-(@a9QntX*j1In7u_}xalF^!Z&$`z z8cz?_U}CIi#M->Z7VwV z2-lgrV{I!sRyip?)i@*_)8HHGIE^#dF`!Y~{*4^IRQEpM8hkz1vB+0k$F%rd$09#) z9aHc*FS(A_GNn9L-Q+JT-0N^&oABZ?=j)ITZ4dUog@sYt+=vl<+(c)|U z!Iet;z*l7T4Cnn`P5WAZkcbc4NyJxVwTR0~i!Wrgh|5abzSbXT@wu!J|C2vZ@rge% zf6x%)j*yj(WF_KSivH&-YmT?cj@c2>v7RZtLw*7t0&5z!Dmqqy-;4X!@%XbielI*h zBK}jPe|n$pV1~B+S^8EE_vlUpT+_Z{_f8$`UPI6M(sjUJ40<{>^sJZWOT@DUIw#q3 z6n_kLF5Mii8$U9NAB_dMPHAI1B^KmaLV{~!wUtCCZr71dP-8oqON1_Wa@~pH->%=m z`Sv+8qF-18bd#dB&C)+O`~lr@fFH}@6x|)q@q2Y&B;a>&{9fII6YxJFdi1@_2foGH z@6gZZ@D$ypfXCY3qaOf#vF>x-=W+CGmG*M@16*Dz{+M*U^djI35EByL)b_`u4k<+N z$e%b|;EUJ>x+d0?bQTz+6|+9(9wjCevwjdhq$JMH6>RxwdW%Q&dGHzVUcslxE6#4U ztqa}@yVc-pVqYzGEcO++BIkO6t;l3Q_`OY%c5}L8(7}HsLN5kx{`)^B;1aZAQmA)Q zXypXxL9|ftd17w_t%^aBjib1}%jPrLBgV*GpyDi|IPyPH_+UiRz|V-n^X2e!efnOPij};{7!8~s&kZ+F6j?x3qt-!0~3u17bCzDaP{A!HKo~sA;9h~1W z=%6VPx(m4Z2TTdL1g)49>YWr?8G}Y%0&Nz-L-|cU_VYLopN_%@<(D;Z%-jlozI>7f z4iBKfE96ZYcnse=1%9O#9~I^L;X}9%=9B#I;ye*h(yPHz(l#yhGUADCd=hBIq)_jq z(8>wW2-+?1CiX_qs-!41@+rpcSNQi0ANK{EfBU2GLHRQc9BUZ`KVQB|1IKznfmg^E zYv3__?-clzaroHbMms_WFXXx==*ft}tK?&2aNRwTA5dAA^ZOm*_dT57G3emiG3X^6 zm)rbP!~ubOP83?9fyQvX8fXl+QUe{~EpVHEJ=WXCD6~og#W)Zb37dCwK3&8qHb>!u z5nBu%!M`f_`SR~H@YAC33VE*v9>e!efnOPik2NmZ7yN#V^Oe&R!Kzw;SIO7L;7Y#n zd}xtf{ug+7Kc}8nRW>e#K@)L63+4R&hWMQbt(X+*ofKLbgGN3@Z#-564MJxx=Q{gN z6h0__$ax~*M?~TI@?{$MXcS%{pQC}F9ff=4hcxgLqwq@k-WVKlz;~#<#&z&V8vP@j zCo$-tArZ=X@-^{9i%ZaoNul0Jp_LP$TnBOIEWTYn?|dJHMqY$13H}YrZ}4$k!}*6u zT!B}}J2Y@)AQX6|e7pt@F9!J26mLXwbz_J>_b4MjAO!?Jbkyq;3DCimL@4LS_rwn^ zF6YO$lR>?cLMtagIX}2YYTM=fkfJn1KEpUN6d(8xKECTYKmIEUACy1Rz*j`!`HJrn z_;aH03i&(@K4x{LeXnAB0)J~1UMb(N!AFdv;1|e`M_R!Zfj<<5SIKwA;L2VzajX4* zh+EpYhoA!*sFrTL$K316b|sSFyW z+x+>H8YtOu%s;%Kv;ZhFSBiB~Ax@B31lsVF6_DJP{e(=D-rl+#;C*Q5`41-SN~YTqns(1;=}N}nnvbb*E)qW>Fk#yroO>`gP~ zSwGeMF5NSct|4zyay}svy7qU{PvJ>p-tlFw8yqThj{IwMok_l!>l}yPq~Ov@m1Lb^ zdpiLaP~kI8S%e#bMk}l1cKMH7kAxqK!3W~te+9muM^x?dw;W&ivKV|o3&&_oz~_4B zc@4Ax8z)ZRU>~qsp)aYtJ__nF)iAoDMD?Yq9(%n0uv={@`XV~54OGx($&@!qw#9% zUS~k}_v($X#Ei(-w7+kH6#$N1YOG(mpLw19jEI{!RQQ?K$b|@PSAa4jH}#8UAJp8M@S31}>#GC;LrIhUW%7X*I5#5}fZ%jTd2Id1g*y zZc1SxTtqt6fQj!TUV;<*_?1?I$7p(q6JSCokkpNk;M+oiIE_pa9OM!d5h|CUOcGS* zQLG7t1Z9$-1}a@j5|rOhfN}}SBte1eLXB95$gX8m9_>NiTMRm=feIS9v}KaEwl^+q znWQbCL6}yFM%vf#b_FyhZ4Qm>vkn9nf&WG{Og0T zWL{&F%Jajm%HyPoxVc7h~sK#x^xzM|=#w|rFeaz8%OYQIf|DuKI{sHS4 z;?}`y(ec9h+|B)i41w_vX(#zF$-qCMha$$~(FTvY-cqy>aU1Lhew(1twGTye-1BoN zkB<1hML^=(B9XSJ>m_3}^l z0r$B4gTAGSFW5x8pQkl-mSErb_Bjl97jQlY@fD-@G5D)d>_Pb}JO-8FW)fBQC6BG( z!TyIh=LZ<-HnD2_J(JU}{GHIwKjjT*=Q1}l@^;W4!}k`l>UcbM`7|Wn&q;KooV!f@B}QwE=7hGW z3Wrj3q$Kw1?o-cAanJymSN%;|_I0L1Z!nlXRDKdwkqg+r`G`OjRr2^*EnS+}5M-r{ z596KBb>WoA)9ihWH=Ax?pb8yb)mNV*LPffwklj~wigO1ZS2)AtIm78X!_6+R8`uqQ z_l+b>R3ZIKxS;lupu$@@ft}U!XpTiQ+@CHr00BXT-Jr2d4|2+~9Kl0qwu6 zyO3SPX7f8X39&7!4(8davptP@={4DGc2#yBeygU>H1egv$Tw06PIOWQ>KgDa;oH2T zhZ3VxWSsan6$Ht%TKVUj_{_Ij3kdQD{z>qB>%4qiHcV5{@H_nzKGRS`gx~_AgDn(A zzLy%LqZC@GQuPWQ@)nK+nzEEwgO)B7L8dD8)f>VkM4vOUZg3)g;usVE{gT$gj9NU7 zROrBGWv10{cj7Z(V>9IQEPAT}&tIQlK`<)sodWUT6maRNdXKNU&{>yP)KcUq@@F`! z(Rzln)|K?s$x@0Wr5a9_Y^i&u#44KdU%)*H+?x~S-iU4`;=gVGIrq$s8vdA2L6!dF zWd*=n`Zx74b{@P#6!h{5E#IPWdMzdn@N*gZi^4X+xz?hRCi+i^ptT6_pehBDMNyf} z5f#j%+CP3Ki~km6f|U)m2K>JeNJEfql&D!Q5&mh3%81pvVt>Hmeh)u*k?^-vVMy^e z%s#E1Ryi&Zeoq$zQ6!O`Hj0GXmqUDKxQP(|uno z-h{JBkIsJn&Nq^+r~;OJ@x{pqCoQROKF@!q+OTciE! zCEk=J`J#)hN#H3p1zsmvFGkZD`eYsM_HV*F2%q8xH&uxa(M>eeQ-lHNRWFh0GNS;T zP>yJ&=w$At4~@g#%3w|h%V2Jk*^`9B)2Y5RV?lCqYB9=ASzkQVKT1LQQIz!QHz(y; zq+F9ZT`t7L0#>116+YRY5Bbj&*_?$@eIj*ZR6V%yI)Q$@DnYt?$>-`)yu1{f6Vs_0 zs^Syr-$Tsnu1Jxn_6mNKBwaMWqGnBPZgcSfy=143F!ktUsl!**-sg19FES?;qX>mL zsl=*hj~Au&;og&^pJxZN8Upb zB&yz>hZ8(+Q?@QCI!CHzC1uLp$)+?TOJ`3eS@07z5dLC8aoc1o^O#U1m#ir>vV;8+ zo(hoxuSmw3XslBzt(!+x2KIvOT_ohaGx6y)mbtLkPl#07{ zy}Fa2y<%QP=?a#{u0|~hJI{@(>F4N!R(N8MTN{F0=rFrFoSoO1XTxVlzU}DNWXaG+ zAME3nBLeom(z=#a^rL@XhAViYfq#-uyC2rQTiS_wVaWV5tTeKmRPC}M9OU&)I~i_~ zvyKI6di$HHdfURzG?spNwUqj9M!FvVzc<4sois3jb{;}i=c^H0N;(hPG2^m5Y5-7U zDDxZNDjQk1?&_UkSE@c)FS+o;wi1o{ua-LRw|w+&20U>GHEu(pHCXh6sML6qw2E%g zGK?3bg#?Xw7pYz~74j~WG!_pj!{m!tgS#xnWYOP}&TOZbr5H_31sP3wC9M^y$;Par zvJR)I+sIzYG-qFrj*hUi25<2IN>HSj(#-apP=<3D(X#G7os2PU(G_Z5G4*4*BDQlg z6%IvpZRA;aWpZ4*2M$}>U}hP`Ce|BpR|cnN;vwSFrTNJn)!nvslSwMgFj?B%K9{t` zh0^(YOM7{vDcqOkF;^F6vm=TtOiP+8)G;)?HSU4NnP?jTZRF5j+_u(6GdrH>Bcdd4Y=3rr+Z!Wexn**gf+7i zksb}y;XKU=f3rnhweG^!0()0$O>TaZ*S0!rmAp1*mEBmLoK~KhRGwxJ*$iF>dpxf- z?6m`_CEpvw60<7H)3B+^oK)nn`csmtQ}s6lZ0XfDd@Z#oD;@mahw<$NzticSFKWfY zJ5vp6&;!nfO=flKAVDiG+>iGM`6`cv3^_iBK4Us7b(mOb>d|GvE>8+repsHhqo$+L zWUFD_emC0_aHh`%Pdi*@M}wYqdI}_B_)$gWhNUePxi(WrIgVX3-5%D1eTixGJ_}yJ z=1(2+;=*JYq-jE@S-X@jNyt~t#p^$FGi+?WU7yJwT1hp4SK?2UiFPfp<6tar@ga6A zdzW%SSlOW+vW^#l@CyG9un7@$LD^-%laYHtrh+i(H3ll1PEUj3JK)Gm4t?g!_|~6Y zzjsQRuQ=Fy8Fo8Mmzwo9dj|SqR^6v;i*!4$0w~txBvk&M1DMFHl^&3IMyfo{|A)Lc0dK3g_P{mw zYTv9~wk0pJY)Rf1S(Y6qu@gJ1V`pCT$DI;>T{ARo)PX^;ApeWGO zB+BG9LB9e)wzA69=y26nn(Uzf3nEB!%w8k0P>1X)Z|$ydmjr_YepV%Wu1-0PakJ}M zujKJE@8c!tj+i@|3YK4o6q>R8bbN&Uhv9LLY(B#vEB#1$Vtjyo!*H8NHk_xXJb;w1 z@|3gGlpl}xvRiq|*=oweB#dCQqIYhn$E7{rM9an zKOLWjJl{p09cs!8DD@Lw>Rd`8PQmH_T4b3^>r7mQwQf{{#liO1uTVjj0U z?U0%WT3SM-sW6kg&;u4vS-i<1T~O+`IczZ)Jswk~%MAS{SGq7;HA|Zu7Und{o3=)x z(a)*L)mhFc>7wizaP! z*UQEGL`d<#O?HY%4)c>=-GNy9>O~OsEhSMlkA^GdM;Egm{6IG40Q=GPHv3oTNs_;! z-lC8XH%}Vgfqk+esh?u$Xt#8Ov1za(yRj=vw<&;4gfko#F#*Y00)7#*B^Jb2z!FoL zh_Xtd#PA6lM+WTG2r*Sz8DvIZwQID0;l??*n${=D{cTg$_SV>0b$}VY%InO8aRIlM zEX>YaHDJRZ|7LG|_Q=3Wzi+DF%TAloKC1$<8!7FKM;10u_4ye6UzbhJwmIyecHj7I zfd6Wo{GA4LxXT{bO!99P+9a4UFUC+8+^z>2Vjf#Ymm*=b!f*)TId-NBWqmtS;bFiB zw}Gyk(N){~xfPvt^O~izB9TsWp9WVL+Mb~C18@lK>Hg8#OG48IPID*`_K0JodzSr# z!3L7alJS4y4A0rPBcRu?f!6FbimOtjle$8`YPv(7FsoPfG9PS7!>AWV3whMWY3eUr zx~Zz95PD~NytQ{E8JmT$Z)I?q z$J$r!C=ZAGx-x@dYj3PR+6>tUPO-`^ncZ8_Fc7vT9nNfjNojRoqHS4ISsg0yPxHuu zq}@0aC|&6{C7tX`$~q^Q*-{O>5i{!ol)_h&_v{jLa=kGqI9QD?u>x{Ln<2ZYNGGUL_%a5CM{#uolV}F&CE~4e)JUy3p*dxqwmJhO9JwaooBHu%Ygr9~XOd4^-5 z6^?>mQq#CvkMN}r8vBZ+FgrmC*~3GP6;o2}^O`EBBs+Sm{q4~h)-pOGKRKG5{k(|% zSXpnfV@^|LZ?b((b7fsy6mv5yOI1&cdC&S(!8);s8A)brSRq;k8gyZ8=nUu?ZYDv+ z@h&38PBv8+pM60gk`-WyXV8zLo5}A%bCiFJFgFxf{tGb%O=9|=bu=nHRz#%_3#JM* zX`3)x*ziB27G@GWZVPt8NNfpKZ6x>!3{o#_r!>v4aeWC9OSLprbCf^njhsweZ-pXY zqIY935_vij>3AD<=#EIFtR)ip60DQAJ0g+&(P(|DO|sMOf)`$(PX%{52LtcED~t-I zioHc+bNl!^Qj640x3;UhD8Z@PU#=SX3Lf1?j5U-j?>$Y`b8iB72hc2=eYIwR8zXIK zRjJixYbXiy49{uvnM!Pd#)kBiu96a8Z!}_B9Cg-2+*V^SV3X3ZcvYrcstg&u9!u4+ zRi~amqcqUl9l-9)(q^fn^}Mfasd0Nub$*Z4Zo*1Lt=-xY4>LFJdqh0R4`4y3Y1T-M z6VuUvMEZl94g@I4S`1{2Q@l)Yrd|R4Ts48izMjK6qnQmvLdj^j%%hpgE4bYoS}`MG zIcbjGM9xf4kEG){^O$G}zb&`wX(kKF*2o0KWzqCjft61HYsM|X#%`P(D6-@MRMe#b z#r7W=s^*hh{5q&4!`b8Su-{8NFr(`Nr*RiCrx2%)7zU_uP9kks$dQTzXfYo;yC>jC zPi^?J*BD7#YZp%GPB#qha<`T%4~ZnMqkNLhIvE_e3>OA3uMh|rUi9cGR=*9 z+;lFi#5`!YUx}nfea&v|DKBXWN6M<2TFXDU01|P$y)9U>!*3j{N;K32jLP35k*Rf& z$VlnDrh(1r(x#~+$4rfRB^%~%f9a_8-V%*nH8s*4sa_EbklYYtmH40;PK_avlTw&q zd1>{=3+5ptl#9ZV$Q@(zqtV@wNKNNhHWGO;5(%f$RHtHP&yg&SeZ>BvOw&uEk!IY| ze6*E-M{7Dok;|$Lp;Dm>(3U!kfX%u4gBZV#U;W+@D8A6Rc!)h6B-y<88Ehr#e0-|K zS{rhO0%4=EiaoQ-js_Rr|}r z(Wt-D%Kj^rI?xaZH|C+zm=)*k zSh0N7^3R>NVAi5}>(5#+uy{U`H`dnvs}`F`lXMkLgVkE+GTpsu#f}SBEM2+sT$HL` zJb%L}!?TypJ@M29n5;;K&hgDsC8FJTkbYDxX$sw{sT(dxn3(8bMQm5Ft;(ycGnsRc zN|oImOHYwfbtS>owVpYpm0M4;x~6%YZNc(sUQ{h1id|AYQ|950Se)@4Gl~e0O4Q_t1=B`R>aqtLwYp-J{J! z`)McCsN&0$#Ne55}gJ_JiO_Mm18ieLp)vM2jfPs->|3&Ym^g@zBQsH z_2iVjAQ+q8G0#Wq#g1c+?`c^)=Y%cuW-S?9)0K)eLZr(QE)(80S4aE}Ro6CluI%fX zH)S~8R6loB0Kph!yLCqJgpoCutQbCK`Hst%&y`bFpEYd78=v1@;<&nE(foDiE|?ZY zK<5AIU+VWtaw<&W%Tiul8ia_wDj)?EYyh4D* zfPPdX;GH8&hEC$Wn_GneNy)!2zPNXk&$2CuK@EzF)fzGD zhTI`uIP{8z5cyJ<-~UBF3uNYaN~DAE5V4B`%e>5Ax1@S$osaqHx7&^%y-OEQ_51B5 ze#xgGtJjTdIgz}1Gd|`i2fbd;hd=)DhxEpycs)P^*pUn?ZSg@F3kmo+=QNm|49gx)mwf zraof-UThe-3)k$O7d&B6dHLrSlviz#@px11@oS^eT|<$WZ9ryM`y|_=$M&aAT3umh zUo%?p_}62%1%hA0n#3j};SdI13#AQ+E^@Zve&t`-Q^-$88LT{gBht?rUxfgEx%ZZo zS(N(_bU-=yo`0y|9AvH>rK6mhUPJle>E^YdJu~JwE2Z^R-}vJ3@mxO10;It#uh?wi?IIN?o?2Tx2Xb6?YB9Wn?2)k_4rjIvmlG6Hm>$$8xLtGJeY+Ub5)|N}j z=g+QZK%o+@D=2M1pHgPApEOXr>@5YL3qN}k+AG5Ysi1fgw>-f%m!Y%xoQGOt{~a%v zVwLP(i_>emvx?P4nrfV1zRC#{LQJv38TSbbsg*;U)PX)Z8~}BagDapW+GF2?pgq!| zWMy_YV2)&+nj7h zTD8TgKx)^5cA<%IJxd&hCxyw^;U>ouIo$b7r&02zf4#Np^!jgAqjfJKxNIm~AxY)s z&F0?e&Kl;3MCPVaym@L%2ZqU`qXDRl4ZYkR?cg(1YPJ#7)Y-lkbu{Gtn8Xx^a_|Rk zX5dnYY_b9O%{A@Vkt#1gH5v_Fb4^Wo`6cD$9Xob(mY3sxn1+Vvwwc#lL#+DDGh`Sa z_<)G=%rhE8fo(rHK-vbnMQY=62ah+Pv*KeGD8!)yXXRv01)%_*th$b(!yz08_^kVb zXtc2r_tZop=^Z;TZTkoWD606b5 z2wDL?hRS;-w5Ced(SQ+s$M1M!SC;SGS^k9>r1``0^6Cv6aAt8^d3nvwouO#-nDX+# zh7G0InP!YeWA*KlT~Dt(RGI*SZnV-wr~0&*&#HeA&zRBRy*A2ek>MT4PcfQ#BxlHP zz2Q!rX1I#vSJ=O;xot-!T-C*~Zs))>7RhwVDW(#m z?6714!7iG)KWs>_nQ?hdE|cV3$Cj6uEBCH-2AoemX(sJg2I%?#T|KC$L8lqM1%xbs_EZ7wQ|nwsWbK*& zdzZytK;t4z%%F4=wVuO7_}_?3c{l`Su*W%Wf+$C>_!SNvn^Fv&@@yVD!hM@z6MK&R zOwT#IN%VLAn>`1AfX(qil@u8jt{n2S&7m2%5>S|lcmZ7*g=R@ z_>Js0s1rjA)|`27YY3&Y8Fr-&dm!+rcfe5mN>4E7R;aplOt4SM>+>jhG48 z><6o{+-CMof7Q(xlLN++4$#pU!w$nK?AL4`?MxEhbKEwV$iN3i-|#49I71{8J6r;8 zgmd#qeZTSGgpJE+-g3~+eoVk0I9WE~ev{u!GuutF?3Sty^4c#%?QgJW#hGQILJ6Z0 zn16%E!hBYQv@Z6n+sy0-PBQuBl2@mDC9BoQSoJ{%($TK{gKC$3}?$h z7_SUE@)oI$T~D5WjoWkwX*m1xCeyl~TqQz6R>6rQ)&5e~saO|ut$nk_?4&n!Cq*LX zH=A!k>#})no;kd-1j#EIBP`x2JcGdMblcU@fTJGvX3i~->7;jKNA zXC)J7w-=iQ9JO$BeyPRGt``mF*> z2^jmB1u5itRZk()1G=lJp|afU@`OqqX1J_;^_5YJ%ad^1?5R~{<==6ath1U-IQVF6 zuTTD}IcaiMlt{tSa!+Hz?39dlv!luB_n9zdde(uZFxhN6u@S=o_1vA{psP3saaR-O zGF(_e4!ypbz(LU2_i<%)%ZQGJsO#2_d{Z42{worBMI94X2#&hN zx*bMvz4ga?ijOebKweynHk$9|cHSvkqo`X4x2D5XM}cq=a6Qt-2lb77%vG)@z}aSX z)V)&-&FeYXC*;Ow4s`-hcM#OM(NJg2ia}5efs>>Dks#C-f?2sP2eV}O`uHzVa}zwc z&@*|XIM>Q#oLeyF{s1KYYoz*UBQGY3!N6NwA0B1+)j0BD_>!?Fkyujnc##~($l*`> zCWU(DzF4VzN+_y)pkqqAMTSl1ngaj6JR^be6ie)hIT1TsZ|MzK^P&v0VKAsQTiY?h zB3qk}MgjHg4i-n{tkHw#JSmf=yxg=#YqGb6f1NR{}7P`{(SOW5LtxZD;)I4Ao zcw!{tC=()m+DI9C((ez4?2dRO=ro!_6>BM2id6cQpzleS+w5A`YOzFvKBv`I5%l8I zRckS=b2*L1>Wd=5pE<#zuC-wnF0Zs;|4t3Yp&-Ucj0DcbPTMJ_Fw9+_R9R-0S!KBi zeI#|+%pQwWGOxq|GhL?s3qw{6uq0N(lECaigX^dx_@rHi5&d{RqF=w(1vI$XEk^Wv zv=ROK;x4944v$H=`UR8aqpbp;)l5gzo(qlAGk>-9txEh zy&HaYk;UzoUOsSZsMf(kWMAGs)D6bUVOE5MVqLLk}YZb6Av{_6{T@o$O zJ=g;c+{|6d!(MDHm)N#Ws~wXen$-N&i9NpS*z5p6Q?6g@=JTefp5(S>y`fTa3L50b zm;A=F0%dbZXslTRb!9hfI~=&C2^eGWCCFKg~}1On$~$_v|uhY4B+nv-u%5$jb1N(h_N%ob=) zK0END@xR#S*4JQ>Zcgib^LcGSP%_9ob4wgs%~Hr}?dq+U)=uwS9tb!unwHwx-LEKX z-BxGKg^}QsHj~E)QX4n+0$I8TY!kd4y%0>21QV5 z#|-zm$O*9N_@oNtbz7Uv)>oZIzgfo23TMRvP&&%V=o6Y@;gB$k+!78?HyLqlDowJ` zdIFx&E~y7{gnfog*OyRIRSeY6TM`I1!0id$;7lry>o@2;$q9?X1vSH`>lO!Q@T#FP zm>ae0&Z!JPX~uyq%%87=V7svU3jOA^J1m{TZg?~|nq#u-9rQZ4noGg4=%rq8VNBv4 zd@QxKafKS^V_c3b07n~FXq6$XuHLbi7MrU;9NBK3{+h$&ldUJu4BJ+9%sX>-28Rac zWoNHzDQBMLUB)eD6Ewmr)6FJxSgNXWVai-TG8 zmr(OGY+*u5wgwsUJh3LzM|%P5L=BeEa*7iCqm@vC-%_j3Jm>@c~#FJHkBgP|7Tt%lD#lKUyM*=8}i;n9IR>nRr)&F~1y z&ya%DKCKi6b#5VmlVw0R-=5^Mx|Jz9hYo2?l>*R@hb4IC_Zs>swHvsR>zNi(!m z4O*lsVESHFm#Q!zbzDn@MARF?Qo9s^F9R0dk^Nwr$3W}%yf5lV9}HsgZKrI#|$Tcw_XCz()vJg$3q9y+FPc~A9{`EkCLnQW{0vBNa7(JjohEgFlup$N&rUoGD+K!3 z(#nL1X@((k zIPROC6e2kbr#b81>+#)Lx~axRbBvmqm4RJur`4T!0N|Zk4Bii}P5mkS1dgPb1HOis z%LGd?G^5IMktu9))=UDbvL^vhRZ3NISjn>BkZMLc2M;|2UzF;S0;yCinD;TC@6OY9 zU6uoBM>KkE_^xR5KS8LIYdOpW%&8Y&sKO8oBtn6M2V+({fP;qXHe3g8`6jneHIXXn z9Fc6<#dcx|;O=6a*(g#k^P!bsaaW)t(83+ip$|x(aN9I#@zSW{MeoxDkESOWzG>Fa zMTqqWd@SUzfoBbrn-%d~Yz&!PH8}rqm)AG;weoVQzm`uvs^>)fyId}dD>1gGyc{IU z;XxK~HmNz>i~E|Vv*$fNj>59RrIn z|8k!BFfJ1B_XlfSCc7POw~H?{gEyV#8b40PpCfIGM8+Nm8DR~>OSfwm@wT&8>O=C^ ze8deN^vPWGNiCO~2@DIRSKLEkpbTEUw}?rVhbHva>;@pe6)d{Fh&_utZ&AP}c=HbI zRCqwH#f~#retvWxI;B}V!)LNuC~`XOscRroMzwe9f?G4h(xMh z=y@7jU2cp-hI7FM*wko} zHm^PY+M7qSvoo_-_SAnaVR~pd?vw&SyHQ!Pywcy3Y+u}5{sk=C@fB+9{ZG?vcFZeS zIivq#|E;XTsQh{5V(n8(kNq+b#75c|aF`3auW|g_sNp+UQEMQ7OT7rifiX)}A-b=0 zjN=K@C@ouJxFSBCLH++3vEsP56q<_l`(?L8BKHp;Mq7?rtIN-%s%^hr#w^Q+Z=D|q zn$6fWC>mZD2wIKHl;6Gk?x7c6ASh19om1~hH=+Mp>5e~f^f(aqC&Kv=D0dWAqdN9z z@mUQ{e}KODnZ%jYrbYE-HNU9othKo?cQ-Y)FKF%WZLSwjZJFVg{^`?^rSjPtX~x>A zL#vh|tZk#bz=xgEX8UpT&)jg`{O05edNevW4Q=1BdtUR{_bB7Ypt6(}@A;}@Ghg2} z8w_cG+Fuuw8~@z&XJrbz@@GWe6nk|-K7R}h7-5Z)^yjAgf5x*(4kbxB8E9WAl}bLo zGY2|C%+g>m6#BNvBu5GqVvIXQL59Va1+9Gt#r*T&sk3^9XROhl&glrr>_K&2ZrYlz z7Bkr8bJm7J zCr(#P2ye1=2g|V7diR>7e|lYpejSGuGFAqzHqI}%1%iu{?Z>x91Hm;GjAUe^tNjO? zrh*Rh?}g>Aqi8=)b7GTttX(Veesk$5nTYY>wZnIsXFo3J^N>w^yDt;eyF9(A zs`|9~GmjIrT_E1BXzty2+cv^er6cgHlCWEnP2XOIo)hvwrmFAKK!$vxR;I@Qr>v zef%Os+)GnSEaoRl$xuloF8CSaE)Ks;Isq`Kr?1&l%Kq<~jXz|aCdqAfBh<^cL&hIG zXb!OzaBrC0IKDV;u$YZji3hF94+jBeCC*Fdde*O+vc^a%F8 z8~kDHEdqAfbw&MWWajZPZnZ#fqTF8W37the!+D+i z`8fA;2~fEndPLjK8mDPA>?X0pzPP>f>!Wt4hK8!j=@qV)DV};WDX#y^LKuWQC}WW5tdfFYO zt*m89m1|SDZKOYPYif}vbk1O7&oQkP+qb7SmbNW|hBE<{rGO<24T$}{Vuv*8FZ7-c z0u#A5Mf22sbkLfY!ib~U zA&Cu-eRsIj)?Q-u7{e8CDoaad#{A&p?(y$SHE1(PI>1Cyje4ognmBJ2BO&BwGFUXu z(!)bzKo@K2#5}@baYQAlpBck}`>jPlR)o`?HI6)>HI~-0Xd-K|N=tkpcTgs1F~uq` zmEFY{w6(XF*z`CwH9-PAz+yhI=)nkooS+^bkN8JUk*RbfbB=(Y3<1ANfjs{42`S8M zt_qjc8R^4Rh?yJ<`}0l)XyEvT(jf!1ePkm z#eO<1MaQTR-_BxxMSa2{l!r7)i)NRa)ZVCZD&Z ztU4Bo))mn1jFPst=_j?>%wGiU^fGWo)fSI;ORL>{7O2W7*)$GDn|}H4pkt)7+ACqY%Q4W4{7jKleF^;(o-rR(`%8k2@uLmfAO| zc`BIllq9v0U8)oE(<5_hlPj_T$7SfsLSer+G%wk-A{%y`N}})zOP0=vR4!_Dv#9b` z<(xnW9ZKinAn8&9l3v0kVKsUQhv6aY*xtp%--jt?hbHGq9C}x$GyhB3f2j}a3f9>c z^K7TZ;&lJ-Gy$7kZ9*Irt0^uU>n%>K3ZJi|$-kuY2PCQ?Q_(X!v%y```H)N4OHn<*{yqEL%Ik4rn1D#lVG{6HoVLZv(zZ5Z zO;UZO5yze-cdQfcHEgcQw@I^bJ!jMSgb`ewxvA}up$~KM(w6p8nA5I6By6(>T6$`1 z*6tP`)fmf)K}&JR26krIn`|8Hu!488esc8trm&> zY2>2f4bkAho6-ZsVSy)8b;JtLRs+qdn8iNZ?C=@cNTV-LkLm`aX`b2Pm+KnC6(&=T zF#iPdVUy*H2rMkgU$4oLr%E+nlM%fl8X$OOA~uHkyDLw^@NLOYp1Q=io3dwv^l6dHkiN3;+$p+l=jNc?R-@X_GS<>hM?~R|ct4ZJ`ZLisEPV6ujKN){Zc_LRRK7|X1c@Jo zyGeYr8*?z~`d+2>7isC@>-2&CUv0P^5<}bw52ShqynuS#@&^6Il$^LDqiVm&^@k>8 z?C?YdqOqu)?|>ty7%j)gg-S-{UXI)~g|AfP_$$mg(uO@ax1E8`F5_nb1qbDH&!lv2 z(z(+9R76oJqxY!2OVqoDlMv$rc1@^lRbej$?V%`Y&0q9<)Yd5&x8~Fa&Dr!-Z(BjsuyhYQJC8m$_Ey52D?N$fvhH(+PO02^3 zb0I>%VbzS>aL{S=DOB3KUyDTU>wGH``A3Q?FR5Bf_^6RImb52zQfeU|cZ_}bxeUV% zoJ)k=7PPeob0|MQkCW@$WbT)o`-M}kh593>NBI3coY9qEb9N^z5TaeGq?3T!=>^>q zpt`j{T?yo-zpA6vFLeii`F`3sTLp!Capp&n$g}PLf&z1=#5tI1EJp5b$8M}wGt3R8 z_IlFnL?_E;#Fjff7}yjHEE7jz1_HrNf#B(Z;HU$-3?4?rjt&E3tlaxe+C-x{=XUhN zwa!-o;Qqgao#)0iB4!H?^*(|#95Qp8LdtQW5W6+RW<7v2b4F%-=~p=2Bst7DN{VB; zw0;b%aZj1r1~X|2rJ3K=M*|i7|Fm6`HzWC#Sr$w#5WRY*a)}$E5RKTkd25K;VY6Q{ zqHd@8f&0zWmaKTu0{4H*xFPT_z+{ub0ZiaMM)av1-0UcLNk$C|<-$)vaXoK~RTm*T z_DBwfUclhb!;sbCbu_$>(Qth3$oQWvuw}6#GK}4)l7aSfoguZdz3T2GG3w+xvxH%% z{3K~oE8nf9{FWue$((oJb?u#)bOr6y`u4ZQ!JG>&5C;u)&tw}Fw6F2HrXj+(N+(VG z7oex~X}D;bxzHxxPK+>@zqLLxA>|CdF&M4#gPCZx_?cS&6(aawjkrM>e&!Y<2zi3k zfyBbiA>E`ArVxjPY#;9L;A5v-YXA>z<(b z(_E|(+ohXuFDuqRunGh@MCu4qJ-Sq^vI4&=#y@1wVKtQREmLPq1-&cIZ4^?MJvXr{ zm0wLDFtZeOuk!n15(6$30*pk*=0+mYZ>Qt5)04DzCHfrpr)qx-@1uD7g;@PXc=d>~ z?--x4vn)=(PuJFdSNeh@aW9XDtE;h2)w#l@2chORp6Ez+v9b?JuybzIImZ_kzmH4# z`|6@s$5<;IqZmqLJDZX1QgU!8|{Hs z$4glK-%BglCPS&gBK1klu(E=nSBzjOp8Hy0O(qdKpIo=5IAYazSu(VBKiH4t)G4}jR->EhJ>m}FrT2{Ve@%&{APusqDXxXAw*S9*2FTLb{ zM3Ng`@_)_$_)A~zaATayLr_Yq_mj2GXPu^)YQYw@Yh6BdWZNLlWIV65slN-`J+-%C zVRpEIe{qa4@8lQ<5S6-`uZR>`ccw&*C2WC9KM-b?F#Ob(B+Wfp(^-p0mMqzJ`r^e) z7cuj^ug=?Dxx2TQZQQ-Pch&CQvxi5d=Fx@Qwk=t*Wbw8$mn>Y{+q=8+hPexd7O=(} zcF$ihG=9SkQ-ElHOh4iyyo0b zO?E#uI$^asX>azK6K=1)(Qiq(%h2e8{$&7Qe*aQET&wF`B@JFnt=m)YwcL#6Hw|_J zl=XvCQhErTr8IUlTxzkxB@(=Ju?6beZeOyP-{53jd?_tt%Jy#@ z37<3qd0*8?7q6CB8n!vHaL3%+wz+ZA&Ft9LfK%XD=KRKyG0XP}*_(0FPOula)q>F| z|LZ8c@=aC_ZTd$jLGgXh5y0i4qj!+g;F=@Dl&7{0b3p8cg=MBe^cmqeQu|^@$G#)C zP3yO~T@*W2EuaL}TM_2jn@X`amFkrAymDVkxd+}3T^_{w^TslW*VmR(sC^#y9L8A$SlQhEtJB-Gcln*01cPAB3YyQxwj(l`E-XBBK@*payk~ z5{Sx6D5+9WuA~;3oDO0?s6PgBqg}t$cEb&Kel7JipO?6q)!DKcTWanOyxM4ct5)j$z)(6hL*RKP~@n1IgPg9F$Y@?A{~H&qM|05??~YkB^ZgF za&>YT<3Z~2dVu-;RO+o9kS|aN9XBbMfK%H^K{fz(h+^YJQroD&*LZMjSg5u-ZVgCn zw2^}LP(ZJovt+L2cla)mm4Din&RBx&6j+Vn3DSP^u_GsoY^kktvZlYGm!37;h5I|V z@?I*^`>bU!Y{IRbQz9`$Ca&cw}qqK5xy68qhUQeh#MxrgUk|4S~AIOCY%kj zgX_f~=I%M8NBajZ%;MBZ45t9C=m+ejVZwt9g~nY4+VnE#L?#~!sp&3Df=mt?{_lRX zscX0`KEo@UN1JDN&!5vhYDTD6Jk0H$KRY{W-rm%?u)U^+ZF#e1T4Q(Dtjj#}Vso2tGY=V7^q6}Qh z^@<5QOdukN>l9{XLa7K@VExb-^cGB#iLw6F0ahwKPtvb1%ShS8Sh)Ux@-C?@RXZ58 z(%9JtjRawR4|R`O!A4Y`?bLJ{12Yp7vc3-v)Yn6&Dfi;SU4nq^45_zVU&qxErz?` zb^amloH{i(50DJm@po~a@CnEZ{Pb#>NC{r>UXW{ADEdb&bqib>iTZ1v6KU_V<}@M;G@t3}$An>}f{6!ORr%9whb6ShjI+ z%J7Vp8)x-)_2KMVj$Y^u&{OTJ4?v)uAeW9-^j_Cn$S_(!Cwi~;SLy@hU3euxB(1kW zB~icDU*xm^jqv_S%tf!kX(8+$#3~%(oAHy!BmuHN#I6ZA&3D`(TsJr0ES-e7Eo?1Y zD_k_n1Ih#NNHN3HsN;H32SpbQi|f#cbl8&lbYT_JY}BFLqTC|tU?XgV>R?Ud4(w-o z6cTA**aXCPLrKwF7VY&(k3RX|ih=#@zwh&id~ByYj9w>v8*g>edJS>ZOK(KI5M9)(JWmxbf(gag=(rQNMLcT2a=(dG zd^X5s!OKQF5}PCI1J)1a;eMRzY^Zd24nIhAI0>*&Uy!~^V+W5$O-vPNXA3yg`qfLq zrqq2EHJ5j!aqV+aG8wL8b+vHtPkoRX~F( zD+_h1bx9`)9MH>reTnxdoH8`8MKL`N|6nTx3T%~fXAT9#1{=Q#lvqHt6PJ`^xIO`B z9m$g`*9NTeg2NB?2TF)`XbdWSw@&#UI{dsFl#keGmAvZkb-k>KFsT8> zX2>H3s0(a3#;%3*!)xj{H(gQxpppISF~%j+AU!Xwl&d*a=@wAXPOb*=7%KP!c4lYv zZ={U+#)y~^qxv^&RJ<|7F>0JiZ|c#q6DRZLYIfSTSAFVGv*o@>VRixvuDgu4qklm(=%oeIS30Xr^n)`;Vz{P!ZTa1JZXDte!LPI=(D=h(hYn-2eR(@dCQT*am}t{U0-$lI zpbf@gwGWAhOH)sShea=_+LP0ddWqzWXGu|C?Sr~hYofj)95}C1Mj;Q>q2#_mbz`3t z=S6K=y8&W;^q-KQT-#JDr=Q45I+}!py?MBl#O$bT8rV`kW3T6eq z0ad5vasmqhBC!>+aot&(A`o?$6jJ6eQ4nNApHLoE15qB%S~(pCW+5fU^9U_O)PpTR ze1%+^reUQJ(S2Os;e9@*mNBOCD!#aCdXrS2u2xPxQ7!cdtO;-+iReC&OK3>S#oL9B zCn+MMg9G>}5URQiqJA_8IrT_3@1@2kg;1c)tsQEg3tpbekPx!qb2#TDl#qw=62v6! zC2U+Zzrcw1H|3$c%6k}*h@4pv1aq&0*JD$K8k zhp<#xo)elYkYe~%)j{xZ$s{CzhR`)CPpD%=F@170ht8giKCtv*#pp2}ML6;Ic<-Y} zRh?4U29<$VM`ckij{y=4feJH1LsRD#^c$6duP2DyIXy_?r0POylzKwbNW3qo4EMQc z#dy`FqELT8C9Y0O9DzS_fE}SfwCW*pTwCRU;^JEfQ!#(={-6eUe-HwNwBq^IVU{c> z4hwI91dE9D>G13O4`o$;l0X?qENm+7n?i4JlU-VQ=#cX5Lx<4Q;L6TjZ ziws-jDzIxg_xsUFP}VekP^Pmd#$KaOs_y{CijzQP(JFHBoG0zrv7BI97jFNcE@(y*RmIszj1?rzPfLTT zMJZ)9qz3hIsvxJf-hukq&i%-sj#JPMlA4cvR$N{n0EiEddZ84IJTIJE%!oQsH3+9# zxEumiJAnPE!uJROwsY)Jb{m>dbHewi*#{(9nC*SFTQxZIO}&2}{)9uflvl`a`Bej1uLgo3Ulv`NDIqWu~Ku#Le z5?FPD%o4qj1wc}E-Virg0cE}fhmv~{I}l%uxK4GR@5B<-C2a2ic!~%KKrt<2#8=>! zPHI@R%%xS#yM>aTCdGoPiHCP244lU`dEjyeIKe8M$*D$9ty71hoPGgcl@ciIHnk^IX&}1Nl7jk|@(YMHMubFws;We25R+m+guygljHp4_ zY1*uSDugNnF%N@tL1M-Ten<#Y?%hspcjC~?_Femk|MC_9`7!}BVBm^O5F2bxiiF^% zFJTd2)+jI_76u)PYvFXyV?(rreIU3Q+=6N}3qdt4$oG-669U-V8HenkREBs4i%wd1 z&^JO1w(-A>w@4?;4b+boEPi;Ul{I5`?UCOL94;Ln*WRK`g;u++4EO_HLmNxl z7~F?pHoy`!${&SYQtUSrlZoJK0;Xt{4% zs9)$QN{1G}8@`@^u^F1i3HY1D819j+)#QLAj5zL1NQoH?ij&uCL_Y32%+)KreLP)P zFZb!G_3}|4wbZKha?cv0dh7D_LMlgvw}A9Fc${Ev;-56R0k}D@l{zoL;7lF>*!fNH z#W@ux`;hmTurff?ltxqF!rSD%Q=ji0RNADBk#2Cd5 z;}Rp?TJYx9!@IRNq6hN0kj28wxO8t^V}IxVR{n-Pk$=OUP^RnNY}dWnu3Vve)1-TY ze#*ZwyrsTD=e&jATKk3@^659=cP@P>pFV`&+`?*7wF2=ddPQ&ne^<$INl1SM{=&;j zdlcyQCA#;g5$l_DPirrBQVsA(Gz$$&4J&Z(@9~E9hE0YohST8P-VQB|(Kf06*Z(#h zA)QusC(Exd`&oXoYdSif=Kt7-xnE7WU;nS9b?`qo@XtfK-)xQULA;*$X`o25ME!r0 z!si(-Fnj^`vt4Dl+HjrWM#Fy?zG=ACaHruO!~KQ_4L?Ez(Z>xxHT>N03&V4Umkh5M zertHc@O#6%hCdtrR@gg}QC&-;Z=$+I*E`xfeQ#)KT7KGeqEFM(i_`wUN++(^p!-L> zfj`Ab=&jYq5#IRY}kn4*J+kzz1YVwz~-`bo9RiX^`HIO}Q^43u)d4!FFHb-cwnc15jyR1JyyZ1wLayO~!#-eUx8UAEx!l$?JQaw|9j1|9TAP z5`YJvA8=UnEve8FG`2i692XTIVX?9nHijAaU=Ef^aYG9++RueKg+WSS3In=eGVX;i z)2xR4A^A7Jn%>ocGI&pJ6HLXC3sYQOzEa%ajW}(6EQTm(`0H(>UVItLV5^3PQbWp}^!Z1s5)OvR>Z4mbWy~gH>US9Q z{UsF=75tH=mfZKD)lJ{1AG-)ALU*M32=>&ZGZy@p)0sH#9p=CF&*7r?IAerSIGFZk z;<%YCn3jPh>mL$-_Nd?gp?(vR;?J4v!#@rUojEkb-1I5_P4-(u4_o4iG-F~~WO4R;jPhVETLW-o;}!s7s8pP zO6<|D z_k&kFGN{}#_(S#i40>KW>xx0bYU|+I!7B#UH$8)FaMl&dZ)RPQ&x_Y545s*O{(fkr z?-&ko`2}a+f9TL5$YeehvYSQETk!6cyYEgNO5Ob;a%ghT{R5iZLy_g>p5El-KBJR+ z4F$t7=7`FuK+M|Z}u?35WZeunp{&6`umgKON8 zu?lg8QPu`8Ta}VwHsxa^ASM3}Gv=*(m4d+VJ|!G)JNaBwD-LJOOehfN+>&|mNa?UA>{&I6eZ}*KXqm6@cQiM z*iz-fO9!r+D@x}nWUxt6M)?Gr0iObaiJJL$Xq(0SHi>$7aNvl?T{4JZAy@ z>MTk2y-O~6`)#6TA^qYAb)00UTs-5FOD=hM^H-3AZbmUkMnOG4^Y&n_VPm$jzoKmZ z4O+)L41;*BT!e`X&%$g^v&&J#y@2gnfqx(K65*7Oi1zpKbd_>hh-lXPFCtw3dA%1Y zhw##{1|M&TlG!@%8g>ycD#2$%>G_hTI`8kF!wHoOFP(eUfLfN*25`#;Lkx6j0zm*3 z{Z&4u*7NVdy>-w8M7^dL@JHnA&i$hNbj}Jq%y{ zme!&`6`kog>Z!MubcLs-G}={B(pp-1gac!2D^7(VM+<$rKY!$dTflzR_&?aV)F<=@ z^E+_eYB;YS$7Z82I2@>{FteZ+Ad?QKXsy$K2}=nWy1mtd=WfIdVC5%kg(M4E?3)Cx zVh%5UF5*1a(pMMmjHPDOg}Y+O_A+NfAdGm+^@!VXgmb``Wn#(xL^wlbLaF*d7=`Ks zrLE=8FCJM&)NvF#h<4=`!=R^DAz}2|&Ppqr%zLC`%*`jx>=~M|Sbt>seP#NjCzSIV zRMe@_NFU~p4vVqI69%RZ^)HjpUN~>*@X0uZy<`D)=5m&g&PLD+3T!;tfHTBN}SpBT&%0#BqADTCLzH5w>J*-B=zN({mr5NCAt>S z%_M`EL;C0(P)yZ@IJ|TA$n4Rf&C7;QK5KY3GQheM@<6$~DqFFpb4F&3E|7f7hBlqO za1Nm2mLyiqWPZj4_Bur@*N+2OA$s|%-8B5rFx7+=PufGH{Iew-&GOXFN)L_3Xl*6x zA?YLdiukyAB&7K)YhBadHE-JDb^V#4X-jo{q@2tfk@0TrjIR09mYmSv*`e>j_!tZv zSZp*`N1JxCXZ>`G4xM8Q2V-*C~Qy1FFptYYiG&nkEJ=IE>fO>AK6)UD#DG#dg7qWFR3>!G(j!CtY0TglL@&%ht z8JUf$*%PJ((-)pJm_fzlm9U>aG;_(k^>+IS{h0;53sIFJ4)eGT{YI}!=%Mufw5v-i!zJ@f4-KaI>knD%z5M=h1)*OsCfP3u`RbDudh9mN**46*l9 z=4G>wv)ecHwHj3(X=7Gut1e9UXeTiXA=dzW)M}}bDMKlJA(dx()KX~z4TZ>&5NFLg z2va%$Iab_)LbPv|qq)FLbcf{9C<6oqxtK;4LX(q;(}y?~ty4|BT~25LHxJDwxl&s1 zrL<0ER<-NwYIjmi`S~NXVvHu8Vt!QcrXI5f{-&q|x*YQ%%&rP@V_wWtG4qpfj`vGA z$GezwyWyyoQ*)iiTUG za{;3mc{K!DhbSL+80qp!1~X=*a4UeX$$`=-{2cfqUrD}Io)4Zpa zZ-Qrs#Dw}HaFe(T4>`CpRyi`c|P;%Bb<~SwT(}Z3wjx`q+GewGJS7FEP52gzH ze`&MEm#S=zN=l*hd$cJeAm$bcpEuD=P4DC3 z9GSgz{-$lia~2P+-?4JVs+H$`e&zDjE2Xw2^EaL`GJDC;rqf2|q>z06$`!}1Jnw=P zw3kBbTjAX>WN8ylko=~8c!ba`dxVE3wdap}*lmAA`~uK%&mKM9)sl4}d@xO&SqD!8 z>))fS{v$8ji4M@!GqFuZTYxgurVMWrb@3kF&WGqXx4xQ5T18LC&>C7Lj}X^ijZfYh-n$C2>bClAJu}jxaZNUh>VX(ve z;fJ>2%nbdATyGnhIz;hZy62}(m{xDvHwlgtTFj)?!H7oIIvz=gwM~vAn@%|X&oG=o zQ`P9^N;94%?H??Nq%#4-Lep{*9QB$3a)twrHpV?uQ`j2i+wAX5IhU;|&>!SIfbRlU zsrr_ygQt*rLcV$?BOkPui?Pd*;X}ALP^(@a<+PyY3GZUxR@P9J!lR{06f6iL0`6SLa%|9$ zfE%tRM3V^MUXDSGyAi}~=|wcyV-2TZZ^SjA2EX8srmncFHw4{Bp~W%8!EN7F_zn>k z#T1uf>GOH4sW7)1t|516Si&-)M0i3Teij__Tbe)P7MpC>130hWK%p8M%&Y?^{2O?D zhX!*rpWZ!HOc=$NvQ?MsVr}k7)7pm$@`(woI?)WyNR)Qf)Xz-fli@1sTr*wyW)#dn zbLltfE8dvT#AX&W@|r%|fr3|T7ZWYAu2_RKGeL$Nb_#u0inANwMK) zAYe}H#tc~4H|J5LY>VmUn@tu3W@7WcV@K${Uu5J;IsFU2_4z%L3CX65E<`Ly*(5!B zn#JPA-PJ#JyMJo;lwhkTY=~T|Q$B0EB@&MyMYm>`Ai7i)0u*MC2Fk+gJ#t-A_FTWy zW$HT9={&Q`kZZiJ>NvP=<#GsUCn~rzOqj+H@gbGDurzhUG49Wjft+78cXDY(N097r%5%&G!cvo z#4DQ5O^6?6DKl9jRu;kS7FH>BB-e&B0zYcG$y{NP%FKT_qBjFOWmQcK(hkFv%G)}m zf8nJd?Mxat49^>Gj}ksNIi5_A*~qQcYEy~BJoJp&j$kma#a7FzlKT|LY&FtqQL?-k&@RmGT*ix&!~^|CZ=^s43|vO6qT%ku=?H0G9oMm(s~*D?jmJh ztvs*MDYu!;toD{$HsYtTcCWG@*NS>2gu1`&w%hp6xJbBUgZSPcEbq77oo+{?v!vU~ zuxORSFPF#N>3TL`GzLxV_^kL&iLdPO;v2Y8FM?2@at(ZZ-SFFvU<8AOpC!)X+=Yw4 z@Ej!eMbucjz7feuJY%7m%qv{jC4MzBTFg`*u>PrKxO>r}cZ{{h2CH@BEw`}RR)>V2 z^W-;Ktw2H9FEEpDgCm|NU9KWWxIN+U0X1KbL&Bsa)o61__~~$W-kbFsaa}IEL3|yr zK5E~P%teq)tF+dDNjYpI@P^hoxKTy_Q*}?#5~z?Te)U=ICzmrwwkB!Q5cv2f9@&1< zLqa|uS}DF)3R%{kw6~*1#2>YvBwmghSDQ*)#;M;>AH~;*s9>ZZ@v?TAXT4Lryrvx{ zPaY?XLUkJF;by}8&%8O1#|F2_H9pZ~Q#P_+P$hqQ4 z`G=ZGq{4fQ-MrEiDGFax61LGo><~57WjYZ?kjIS<25`F`f=j34lcastd|)*d72ViN zVpe2PQD5e1k}E=ts?j7@gnhj-5ez2ifwK5~af878fcV<*sV{HQ zn&9oIABQGOyybsVZ9$u~8zMhD^20`@UDOl2by!D-t-@D&~ zCNT~A)g72G&FCI2oI@z9&i;{gRrj3rgK6{2S6%foO`B#N(`)^4@tA;pA!%%^#~B*_ zpR_ag*3c1+r};kvy!(0kUhD#guPGg*m{@e4hsv@w2o>_QD2$*U^ha@u;**r77Re)q z8t9x68l^}h{||fb0Ut+k#gFgIb~Q_uE0{^~1MI(V`B!)O!XqSv;;NGH74hL_nhkg9}LS%-o7v>FJn9nd1 zv6*W@8YbsA$~f2erQTV&!=%_=(<>{6>PBq%=mnz-i9S|Lfu0fvb0YGg6Nba@X~sv5 ztI&r{DR(CqmkxVPOpt7Ga9(7#B+N!patJ{9ixo`LATTHWUxg7fyMam$`BZGg=mle3 zst+yGxf&c%+Pp;nm`OaPc*rnwDA&R8c2U}VMHg1=0@=al!pZ~WL)dDcJOy$g){gem z3b;O88LK(%wIdcxuiJO_sA1)%k*pf$jVmI?r0T+=DMk8tw{T*K`II=ACbWJ&A310I z@Z^|@!}Jj|Dhj3zDI2kN68zTVM7MBCi7~#gNF3ZKwuLlUg@~^Gp_L(5`2QDF|4@*? zoB|y~@&*nEN!kCXAF#`I@sWIoaxupj;WbfQyw2Zeuwep|EuP}j|eAE=1fh} zU1nBaW;BeiB(bU*I(Pg~5*rP5>k(T&Ab+J-L7y5TQC5E+ViEiDV|A9YP9n=aScV&< z5Sd&glYp>A5*FLYti>}%H%^}I%@|WZc|%jNUMWw|IfccG$CfltuiL`Yhb=s*2u4e1 zS2vHOg^iPD@8sVmJ!9;c5y^tW;o|(XjnO-epSY}kf`wV=PW)aw@q6v(db1jr)j=yh zkU0S|v$b=qMuJ>j&t^XmvM+H{l5A;#GO@7Ey0xCPq7Op*ogCr&;ENm4NH6iLFmYzHxM_YD`w2$KCrFwK*jxy~NoOr1Ox z*x9Fk8b~rPP8Ny!KbgPd0sj8YC&w2otDn9w-V7qJ=dn))z1GnM>^pXaPEqh>v;MEq zzP_N`j1R3CIh^0Au5?;a@ys%-fZWON*;_G-|0XuO*Qao=>3!Y{rZoS3K7Xw;m4qKK zoWdFo%Iy<7Hgh_SUXhzcYl=55UVk{Jdthy%u&DQTMx1DMTYKR*5$3SYhX0Lw42R;w z%O-^_4ZL8o3*_g4NWHyvr9*=O*{iOU2Et8g>Ae+h9Srw6w)c2Oi3*e^NwiY%t0Ej6 zFiC*D*l-g8}tC^jzA_1Uwp^DN|P;Pm611Q^gcF&%$?Eu(GAbm(+#iH_g+F8 z6TMF|AD_E*A6f;!u)&^$)XMD?TdDQ`RoZ3sl{O@o{=Zaxd0Bngh0B-EczMQh_|HGg zc$w^5GPUH+n``d56OO%4!Jn%ytGVH7IFfn2Pt}kHps*gk^YjCtz&hC)d=?E z!Q)bTaz*7gQ!6TiBY5D^TTdacg3kOMGhhpswI1xr@Yr-6d8({nD=cLf4lSVYRYda) zdO%rmLGOdTzbq*jLUc-2k=1_19NYu;JP&8hJr{olXV`G~k@>UB;OQ>1RV$=sp=*Fr z9yX3FEhr&PWMN?;aUH7nUfO#(+=ps2x1K_0_`I-PbgXkKa5F_2(-8`H7b)YuxTSpv zkfB?~D!Ob5vaig~mg(Z`OMQt+`x2dK>*+PxyZk%H%MtN{5PI|Ep>|D4>BON8SA~LnaJ${ZBj0hsYz^yYwsg z9P@dFBHsy^2?{sE4`XtQ@E5qLE-B-8ojbmGh|d?J@(?gNp&W<-gRoJCz!SrlYVVL? zeergaAQKrT$wc9EZvtTVsc{^jR%3Z z&-0T%!);A*8R!D;A|v{kLkl7TVd=R8A61BW1@ zl<$L)Ysw3N9niyrlEj2;q*s#oh)l2U8d>Cys%(LuU^XaNL5hZXP@xuuLl7k;I z;(_auu~VSc^!_#wML)b6R;5pA_s|Kl+9qCd}65aa+voG(~bX}9E|$y^-ut4S$xF%ARP znTnZ(b44-HC8U`+2+ni)gkN0;3`)9N_@~aW{H-9x!^pfx z@@^4Wq}Ui~9Tq1aguDkk3+n7txtF@RV!PgNS7*Y27!z_wN!8x!Sk9R;LPB{cPIR$T zD5Zc8X3uS@vye+_Td}$Ce?e1)1?%8Em@HvyA#7W*GA0~I#aCWYQniEXMe6HPlw|dE z5DmqM*-us`DoljDfod{0pQ85QJjhnE+E$_RK#>_g6SbNT+GNdE#j;tR7n!Yybz)%l z{$r%={NTYSP@1%p+mMHjz=4X>j(+Z)!!_4uV-ktI^7;7nk_oHkJb~R4H;NHeJgxDS&O@nWTrt>5|@>~nbuX(;zp>tV(%PeS3Z!1;19(;!=9Idn-5 zz};Mus5(+43j#fadjTCpDPf0!5EJEXN3eTn>wRF2&-#{FrOkFWafz!TVc1xb;pC~^PMTtPQq%UI6<0WE ztH?q2`l}#wAN;5hNVS}-g&>({Ws11GDQZOSqbqeP%WRkp0{wvRs2a+}QU4l?;xI~k z@}5D7TUnKXWx4nCp-GjmY=43|%_9uNfcfFXS2Q^Z0s=O<5vX|Rf`}}{L*A>%p~+kv zsjmmN=0SNrga*vUi$z;w&N05+8CNn7zOFEM4~r6E03}C?+!8K1k8OT;ATtmBHF(tr zRL)edRL7(!O1CU(@YnLxv$Xj|@(1?Zo$9?yvi*0UysPhzwnCIFd09kSPm<)4tphup zw!Q}IUU_B{Y`qxBJSqd05{vzi&+prjd z7)$QMfxlWK$P9B^^)HnlHE)g50<%o8e$|ggKv&_?YhE*3<;TvEohW;01${9NgZUwD zi4zgV-|QKxOX@qx+vC8l{p(T98dW`udc=MQ3r4UhRdKDbY+<;}BhdI_DY4H>kE&m( z{HU)-&rP+N2XmtT2r0QBF5O{(WD!!*V_zATlD(*$tCd$?nw1JG=C8TcEY?rkCO+o& zWuBKY#{e7^Q7Xc(F>@S%J!Bu}^8<|&#IDFZK%JYaWda|9ND2J2*u`Te8)xFDlu@w_ z-yyV08E#%)o{OVwFOQ0@B8T}!T8UdZqY84tK$Cssf-2|v`bM^H#W*KsGtqjMd_V%s z{QP{NyytI)C|UBeNVHtCdH%O~8jGKO&V#6Ym?2NpocKSSr-@h~&KPF5f#HHYd!#rN z$e5WugUCg5&nHfk&nKy75$qM^k8|^~U9>;K_h)41+lLH1- zfSj7Mrw_K?N1hJ)Uhtg=(qq`FoYLyJXr#}?^!Fh!ZsuXb><)&yCa-1|YQ64L4W_cR zV_R%C$=e^l7M9qcqar5fSvh4EKZ+LAxGSxEWVFCtIw)OWXQHqg!_u*EgT3F23nNV! z6@%IZP%DcgB{x$wl$8;%9ZG#_OzdWe*?F|~v-Y+DDZo(ody@ zUvW{OAEy;pex;37edjJ&yel58@~ZlUI+kNVe|F$%<+*%-jd|Kc>S(Z5uVA07EIpTm z*`6dM;~iWA9x}vEFlpp%F79$)NB4z;Tz3FbL*+=dfvjUGV;5K#b3#S0V$AKYhaB*p z$uzb>#1mMQv@1qD5mlo#-EY4+$dWR8hb$?VFXW2X`CB4Nn*6LH$8xCzkyG_SSV)yY z^)`Pcmb-OzNe7=?-2bI4P%xunp{U$X?FA0XLbP0Zqyc@v2d{q(#8 zDKm2@4?k3;P@}9m&d+8H{eq|~N}Q+t`s)#$+%SB)vmp?+ayZ6?0V3`_n%+NN7LX1nTGx#w4MurWRDlME+Wo0s2B#J zbv4iJGfMU4(~%ATY_;d^OMf?cZvWmNi7UcP7(}$`Z>0cmMVS?S;fgXZa#={N@FV9* zq{XC#gu$3kT2_ea17*$s0ah)xsuyJ}&$4{28(`}os!Yk!QddYWZ-R)D$tDII$NQX> zVZJBTJ3@0p>}D$Yf>8VTPfUd!6RC$8v4)<@l4>MZx$l2oit$lgD;A|03_?kg$r<^e z@;z0`-2N$~-%=GNt}3yJ6ZoW*HbmC0vi&4Kl#-pn&dY(yIXLS^$vqfLN9#Z~dx$!j znb}u79$=hOy*Qkpo}i`i0~M(JK}~wkvckRG(0-p!$S5?q6R)wv?Cd zq+XEfJMgrk2H$QwbM)mJ|5*)j{)*Wv?%SDE4!Lc=D*$QT*9viM|~N|2Xgroy68_LlR|l+jzx^S~N)?y3B!uLpYUBSL}?2J0(% z%}2=vbMH7Gs3xJ(@E6&@OiRI}V0-X;+;UvJKBg}}2}U;?+|d(MTO77}Jj z7Lh7MIgw=FdXdQ^^T_d3uOb=10k2^>IOmgR1_94vmPu}bt6_~Mg>ts%T+TWB*txC7 z3zeh3{XEP<$k`(A{}Ve=S7Tk zePjYWca`?`OFke$X4qNmHxp2`o{RUstq^3kQBhlzrC;>x`ihFU15uWNBZDND+?)zxZN@r-$VTm) znS;3c^tCYi#g2B4x#dT=OwfbrDA}%`c^33?#d-F>*mEv-t%Uf;q!w{Lh}PmP9JrOE zH6WXueQP=F8U8S8&w18tyIn9Cf}kG^v%YL0)AGyR!%*je8t0TAhM>Ku_$1*lRJ!7p zbAO+7<{4Oqw>f-PR3j_{;Uwh&H-CQ_Hurkz&bgzb5-|QUX%eUFhnLh z=ha5QvzVQK$eSBH(FAW18^Yi%IkWRz9I3BI$Jczab17aZ-wYuIj9`Xl@{4T{>7?u& zz=bp$LBWyvdRlW<|6JIr&{ zAF6#+4^+o;Efr-i=AA**66MXycKyw=LFVQIm2z;Fjgor6R_g&Q>;y=uq(_YbQ3i%mNT44B&Fel%6H!#ZvsLQ-z z@K%=Rql7tzvJ%lp=U??v)xPRDYHdQSet5Zc&)Wa_6u$e7zRqbe$f2t0p}{vkZf0kf;C|3~_>+!Mv@J_-lL z%s1~GC2Ua}w%84Wm$SwH*k;GY^#|lL*o98|6!+nB$uCq>xP^;%31NacKR=eL#oA$m4M z?=}Cn-jPcm-`-oqtXYf}-_CQQbtSuzzq9!Q_%~NlG{{}l4gYIuuH&4y=bR~BTst=wEJgAnaeWf_1LWN3KbJoI6t&*>1<*KU8YR^aN znll}QqVt5yFEKOgI$R%NMxuPHchFA@w9`i}l}kU_aaw%VElXdVTdvGpx|6r5D*I7D zkNvLesCvxeGqXRO{d82IN8n6IlcaSW-@9-hh!h&~TGvtasLtIiJ4^fNWjzWUN@=#> zccKr<&2M?5eIC_qmL_xcbTXRd&s+o^8u=|kk?tD3BR|MFGM?KwmB_igOI!OT#TRBNI&|JX@SFDrEu~>eyc3C2C+V4odM%!l;-K}d3SmUf z%!h3dk)vivj@XpXGEgM$NX;pE83?d7_bSjpt)qJEz^xU%3Ir}1_9!AvCoKX+edC4N zV^Xp;c zR2o&uNgY1P&%diktV$VW^8rL+adtCb7aXm%R&QLCu9EA*Nn<<&5RXI(xZFf^om|V3s75}X?>u!YO7qf zRJEdxgSp2|C`CYNZC$Z#u6j~3=hsnomRgzvuP1ZqBHNF}>O_22LH?>#Sbc!l>32WH zibUF&($6n@Y?GL&@~+An*ewTgv1UdfOH`F1+bYi`ys&B(v&^iDU*%f$Ruzx4y)!S1 ziO3LDPexj=zvaGsYm09yr~3Ikts5oxfGsVfqf}E5qMlTxQLV1NuKK!MPfGKY#~tqU zQf(>txmZ2OR*xzrlqHL8W%XQgs;>uDA3!V?y*;WXkmq+)ELNVv6x)-&G~V zs~q?XaUgga1SRr|8F8Lu7H#}WNPMy?3@_R1nEzLyI%H!(Ju&cD-_MdKL-pJ%H>y|K zO0A^Eb9JRhSh>m1V$70#u81;E1B*kz1S@A6k6G3OyJpr$gJ||GGi_B$RST+?g1MS2 zV-sx4Iuod zT)BfLc(u!dY^L(ftBRL@<3w6u$$MQfmv`inQ~iA44FkXoQSNV<8%R2k>%ag*MXL{@ zB2e{_dv@g24;biLvs@(#TdrlFkY<6Dr?9Q(i5 zoobtJ>4j0c+=d<*tykGSHKLuj)g!+qS8J8bU0WGP1d{qIco)?M7Bs)Qz41AJg93T24B)J`T@lYNl;X7(ZolDmkCj zCE~*?$eO(i3QKij!(pi2a!g4n)vbbKN-9lww$s!!x|ANM&CvFR+f11}VZ3dPA&Gcp z#SBu$4?Y`ZjIkX^Dp}9&Ijpk69Kd_&f=1h(TJG#rRkaiRd%UV@>26h3yVX`z&l)?V z_oaSbq?3xtb``^SsHp7yNkwI41zA#Au|s-tWvNqGrboZTzEiRQBwI{3f@Jfw=7GsJ zJWKLKedUA{nb8lY*X>eO^#};nSXI@sLw{_a(tBzk$qQ@O0+T+cyZAPkH!wcyv-u=5 z>Ro4Yxtp!(+A$^9fz}`6JTeYvRE+3TvB__qV;s_g$_nNoTR*0ZyD8ePnR!3gcU0yN ziFn{Hl@-H>CBR*of1oE-W-%zb5Zz@b*V=i;*quj@-np{ksH&=?5+lZzPqT~?o%FsM z>RNV}p;Z={Gd1x^WyQLxs&y5W?|aoHg>;Bc%Y1j}-7QdV;3jN#JOeUR(FDj4M*Un8 z(5h(WGCXXms@jy{0kn0q)~^?3+#1c8V?S?0_wenb_Aw!0Z95oZdgs$zc9ZntvUdyyeTBD}b^NH<89?qQJ2fsCa zT>It}&hRN^Iw{o)B_YV(((qCkv3L105Kop#9)W~&V0w%L4yOWldZ4l$NO_{JzOKF; zE`SDiAi4z+uO?9FKbsHY+#I*KVbO?D_V|5<>Ok(Ksm0q(Z0h}jzc!8hfV0rMn2xGi zOiC)@dhg?F##eFvkoIVxo#NUZPJm{{Zaa`lplY*7Xpf&l;G9hZe+ZEqEIVcLoC?<> zRfkkqDNgfXve`6_vfyg(-&U0w!POIvvdFVTDO{WwFDpNW)4!o5Md?wN3)e~2r23N5 zV>r7vtWF+fF^^`NVcd;^K`43+XJ7(@4_{m4q~2#ZadIzcy>dCfJGqzN4Ms!tUQ`#0 zM8RFlv>0f-EC}|&{dAu|FiMq8p5p&6)cqm+_IPtL<4j-kzyKLyxmA-2Dtlk`xv3-? z=V~iIlIM;a8oWlyr21j5JIX*G;j)s?K-QTcD@ZtoF!2JRcVKp5|C>vY9RSW?ZtdMu zU2y!6(%x@4xv%Snxdo#sA*H5UHO(FRHNQ;WICR|9b1x|MqX;ltVik;@R#19w{cy*v z3Vb!tIc?LbG!3XTcx6;;0!$o3U~UW{7IDg{_3B82_AU<8J>yko_E$#^aSD&Qk`wK@ zVJ2J^bY7y32l<#E)r5-mQ^>NKGN2WBe}a^*9ZT96lS~8$BG!U%!NiuTU^j)}70x3Y7BcJDLC zp)Kj~@|h$R%DxjZX(=75m4fV;&jk22VP#d-U6mDgjUG+R%8I9}s-CW>1nVR~j%KkRqSkOb%#M1-;g3s-)~r;~WZ_d|Q{-w))H42$o%Xyiy|eB7Ti zhfXORHRXWbClBT?rY?++;b;4DG~mdviThV?XVvI1ge|S9C2s`RgDA)5Hq2*3EqiwNQZo9;E4RLl&9R1H$Kl1ag90y18XMBM8xVnpgIet z9F%r`aF`GzRH?xUMTXDv(=N)gugY4^>Z^In){1D&Qh}8`#?bQzEFr`eo-09=WVz_T zZKL{h{@K&R!h9QGCe{0jG|>=^A%H^0+2F^PFocH*2UO=tKkpfzNi@`{M5?Y25UMxH zl}Z*v4m5hETY?GMYa-WgT-Ez-Xa_JO0Qhj%9nJDq__Q1isCE)?_7dxP2y$ zNsc~M;JC!lE1Sj@jB$=*$y%5sonA8JoO2jRlhWghD$C}MCkrG6XEMxD+H{a2Na7NH zB2r;zGS{qzPv4pBa)GBlv)V5u`nr_ig7yZU29?Y`+Nd*;$)sJu-s0|M8vI>S6#5m^i8{QMO^WM6u z8dAy?)B7am*F#N*RSKl^bf-kuZS%6;CvRX{`?2$~nF^F*t1t@#LA z&+;8^#UMC>cZYUl@tf;YnE;jb!xQ!D3Ithq`dGL3eLlNB@JmK8aO>LPPzAv})JYkC zY5Su`6K|@(GP>TIj0tsPh_z~jvg-_Gs}U6Scfa< zXN=UiUVY^SkwR!0OfaXgc6k^wYoMvgN_mc?^L={=bssCifuS)|3rbI1JkD=!Kq=n) zA<5L?lWv%?hv}Yw#!yNn_hj{XJGLPfj~jg^!snwC2-N6Y-#46DJ9UY5;?RnnM@de? z=eqADalfM-G1t{rlpvSMQ%+nT0CgV?6O7MeUkcwl#$Lls{7gogX2~~LQy~lnC;*66 z2JAy@pBFY8u9w))VE-J}NoG0)B?oC$4J)7JF3v#ZxS{to<|kLxaJCQpVdCflxkV`Cgi_c8D+i z_2l*wgqW5|8~X3h$rq-k*uwf0*HvfR?ouY5k|NANj- z4*Am(vuEX%ZYd1sk#7aF+~<1tez+bS8iZ{fU*i{o5CegNKE%lz3cxLSjsdwN)JL$R z1lEEk&m|Z=$B>9cBRU$=!rsLe#?8v?MIyHFbFbx|#-ru&z3*o)4ndqB3l7mptF$p% z4Xoj5lYlOiKF|i3FupQ@Ot9q3htkRkl?mIWWKPXQ$8Ibiv1aOQ%bs0GCr+@<>C>l| z_I^rANbw7!#@3XV4xL|NZ)mp2B*z_7Q!})vc+_^W1KG>HpD}znlYB#-qjzh?K$+!u zK2|`!#Aaf>TDk{QDVU~Yp)H%55zh^62>e8FD}h@pdz7wPxnd5N}@{sf+vYX=)c{ByS7qSWZX zb9j$&ynoJCfr^Z0@SI)$qknF*_nQ;&9Il%wJTKRdGmrJp9rhlJ;5od9ziO0h7f#2+tWm>+rl>+iczKpBFNo?b&z^@3EWw^CI?H`wTp1*Dt~Ia_vC-E&sfP zy~pA2FVWyV&JzE6DO@jc`1?!!>o?)`a&3Y0nSWjm?-}ZH9hS5AxQp>R*vLK4KW950 zid_Ew3ih4?u3NSiR9di$|DHxf;*e^*j7? zU-pv!;yGL&Vzcui|NTSu#B+B25dYk_?+{xD*BIwa3dR|Gy&68$+Svsvs-C!4>k)12Y~ z)z#f=+q$Y(gO;n|xTdqEy&JUJ)wANT)|K7W-5u3C?!K&g$JX}N&X)Dnd-SYW-?p-P z*S3|d?Om;KpS8e7H<)pIXur({M`Zt-1;%d&^0UwpW&;bdo6m-KYy>uE`JdkaXWH8C z?v2~ep1o<)rdey+duD;bXRk!BoxNt``dMqcH^93B9Ucz1XOgW0*;ate9YD4n&Y2E3 z!|^b9eFKo_g7XfrC({epHPifh(9sr{b=9EP4qyfKad=PL%5~K%Iy*MCgFZG_AJ(&B zV^?*@5v`q|qt@#6EnAMPUe&P%-n~0~tP=<@Rc}Kbz?P&|xFchWvB?~OiNRcu3ET>r z-VDc$en8lSjqt@zcRCDSe|MYm z-u@lwWGP6^rU46So$zU)#+IcS_s#Ae`sGdR@SzT>P09Wj?-nq#4iX>%Xn<=C`i zuW*a7v#&v`{N2oM?48VV9ok=TwA2sq-T0nGaAdB#mbsmNss0oFLH(ET?>_y0{nl+N z-FM}sJA-U&O0|O&ZJ@pNFs_C%n{dqUw!q&{KyPev1-`6$E7RV)@G74}EpWCP?zIN4 zGR-lIvpa6~eVl2xi)l-kcWmah{Xe0tJwTpLkf;^(!e%L(*=%06f~+i5iJGYfxqILm z3tt>SSNPgx-p@U*4UVhf)eZ1@Q6q1{`?lrG5Phe0o8Ea3&<2~&%uASeOo7o#e>QP1 zV1JK**Vcp1n6zD>2?m@SV3xJ{GK&%6yNL-by;|i%CHKOaF!vV&q_Q~6ym2k?$E>=Z zBzy>Bwqj7kP>$P)12?nNYMA{jnPBl*wAi-B4$)%mK=ZruhHZFXW2_M~b}@D|=E7fS z)Pi2OQ8r-=)vDpXwZ>wjwxM+E);goX@M!@W8XgRqjRnR+qp5mwb%l}Kx|Lbhm|I%< zL0N5Cb?Fm$f3Y}C(K!v z7qDE4@yYpb0m;~yl`bqFs|IO$fHIrSJe>qY^E0e!atuT+76(|&XEPsCeR3zcTG!y( znr-SqO~5V76iL%HSD@a;*ZMpc)429wW4ourIz!8x7sbv9Qm%TC0J*)f1q0 zouo|$xSgs^gWX3nAmq&ix10_2dCaeFlTdfp!AfxhteI^OWy2h8E<8IlUt0kCteT-y zu?Y46dr)ug1W>rMwhPphyFut$0Dr&P?`!92pK70JXK5E{r)rOBuR{WP zC9Ht_Tl*Iz=+|hsX-{iULN9X#Or~=nbUXu7>M8Bl+6&OXdro^EQpwfYOWJR=-)eWj z)cRQaq4u)&JMH%{G2hod)J}s*+XfSrsk~jg3MTO3Fnw9w-vblo2uQ)+gH()Fgx}MS z){fGCu3fDis~w{qryZ|-pnas>Pjq4s6ZW>-#L>RddWlO4NFgcGw!(ub#n2cYLSWMx zDI-HkIjMkE%VA_V89_#pQKU-ykM>_Onv5Z1VJBKOsUhRZ1lU_T=WyOG_=60!%`lk7#7YF|Nt^0xLjvNu^q_96R{{m62%KRJLL zNDd+glS9a%q=l>?E6FO-N>-CKWG!jaenAc+>&SYtLHoP*57JIL$VPHF=_FmGoAi() z$R@Ix97(p2?~$X((c~C%EICfQo*Yk3Am1k^l9R~E

r$IgOl7&LC%!v&av~+2kDZ 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 literal 0 HcmV?d00001 diff --git a/tests/auto/gui/text/qfontdatabase/LED_REAL.TTF b/tests/auto/gui/text/qfontdatabase/LED_REAL.TTF deleted file mode 100644 index f87ea95e0e80c72b0863b39fb6e308a169ba7763..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 zcmeHKU2GIp6h8OPOm_>V-Lj>%fZA>gG(w=z0wRr~Na9a{u~slKMwaf<7W$XA(5;}Y zgrp{7(!@qEJZK^>8YIND(P$qG52T4P)Pxvf`k=8!6JG>NLLz1T&b@cKv)#6W&(3CN z&OPVc^Yfi^@7y6lM2o1OEUMi5;)YGfcb^yl=K}tF8d{?rmSv5AzC$EVHMaB~njZMB zmq_*#Ek4y0kH!w}diDlUt___nO<)91TAyKDgK>FNYj>g~xcohg4`6(urM)3~;`_b^ zqP!d)w?-2k)GZPie~EEPTeLO)_8-q(#P~XV#5>x%x)B$yr8{sdC$i3pL2{Tg&y_tl zzw1yp3reWZsZCxYa%#y{nvytwq5}8`s|i`Fu(T&>1EEBgqRfE@YrTVrBN z`CwgKE`HG6>chg*b-f_45NN`_BS%$Lh%ujFJe*n=l9(K&VIu+h0F4vpIb-s+7__hP zn&ldd0W|yC-EtD*JS0rGa$LoSEQjR~ORCTn!vK0nMMnuSDC?QO6`sc6D8YUp6XzkD(lReTSs^QPi=LPnFudkvRC}()omC_YWx0LSDua}XX#^2X1_llGDn`v)0F50_B zCo@*SrS_O6W2BehVaGi$8# z0G7N)k&^CgovF@)Gw{V^GS%75>C0d{8&z+2Vf6j$XKp0*Y~FvoohIecS4R_#Upu9z zJ0(-wUq`?8{dCmAHSk;g@7=2R)4A7!?ib$0y!_O@@9S!=UgjR??|}QO-s~MY(^6`6 zdNHMTb$=yU&+CS{G`y(CpypqvdPml?XWoWs9jjyVcT~E4&+F{HUe_zF{xfg$RJVBV zbhS>@yGuvmotY%R-LZ~1ZvQ&cx%=Xt=S{_SGxJT`i}<|cd-t$qsouo;WJvG)T=DyB zc{R649YP>YyUZ!w&%-?ZJ!PE*J7!h;g^CtRqS-hL;hMl6J%+PH5T~bf8WzlNg5^L0 zSn$4rXAD`#ls@ZVj2~ZYA@jE|m+i8JF*SRFN3hOwyz4Z5NF($uU8i5^CM89#SRpDz zwRlSG6|aiJqDPz*?}~F`L|hTq#Dw@w+>}`|Ulz+!xlZnsd*nfROb*C%@^kr({88SJ zcdSL$GHbQ9!`g4PS$)>~)~D9j)>Z2lYsz-)Lc84FZr9n(_8ayY`=Wi>9=9j$TTYJi zptIJgadtZ|JIzjy)8`C0XPu9oVdpZ=m_#q(7s6Lqz!cDnKY+UO_tq7q#oTPM($M&> z5ZQ*7_~M!}w1uV55=zuzn;;Y%_K57%IAY)okNaPrr_qo3f zZP8=&m7)2I@{FM!dVo$CIt$-}d_HG80eXhA>pP>dcx$xt2-VUqdK%N}D2|WK7Wx2m zJ#~VPfzyg-CmjK=oetr?8{=;Lnjq`Jct4&k)Id#p;yuQcXNaGTbQEHk*cb2YYHn{U z*|@&4lJ-H;NnO+oqiry<5#OtoRGBi7ibhj2X6``+Xv|~3F5Y;wCEBSnUC83j_Kx1p z=EkOO+KB)=s29ODBb6rPT|%FzfVa^$dKA<_NEbi_iIvckfS?7>x*027Y7_?q48$?q PW6+#+=~X?8nLhjnh|sa8 diff --git a/tests/auto/gui/text/qfontdatabase/LED_REAL_readme.txt b/tests/auto/gui/text/qfontdatabase/LED_REAL_readme.txt deleted file mode 100644 index 06a5b40313..0000000000 --- a/tests/auto/gui/text/qfontdatabase/LED_REAL_readme.txt +++ /dev/null @@ -1,34 +0,0 @@ -Font: LED Real (led_real.ttf) -Created By: Matthew Welch -E-Mail: daffy-duck@worldnet.att.net -Web Address: http://home.att.net/~daffy-duck - (PGP public key available here) - -LED Real, like all of my fonts, is free. You can use it for most -personal or business uses you'd like, and I ask for no money. I -would, however, like to hear from you. If you use my fonts for -something please send me a postcard or e-mail letting me know how -you used it. Send me a copy if you can or let me know where I can -find your work. - -You may use this font for graphical or printed work, but you may not -sell it or include it in a collection of fonts (on CD or otherwise) -being sold. You can redistribute this font as long as you charge -nothing to receive it. If you redistribute it include this text file -with it as is (without modifications). - -If you use this font for commercial purposes please credit me in -at least some little way. - -About the font: - -Unlike most LED/LCD style fonts mine could be recreated with an -actual LED. I created this font working from memories of the good -old Speak and Spell display. Since I don't have an actual Speak -and Spell to work from I had to just do as well as I could in its -spirit. Be warned that some characters look just like others. The -( and the <, for instance. Also C and [. Most of these will be -pretty clear in context. To see all the sections of the LED "lit -up" at once use character 127 (hold down alt and type 0127 on the -numeric keypad). This font is, of course, monospaced. - diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp index 28db0ba291..fa5c81a2f0 100644 --- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp +++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp @@ -83,7 +83,7 @@ private: }; tst_QFontDatabase::tst_QFontDatabase() - : m_testFont(QFINDTESTDATA("LED_REAL.TTF")) + : m_testFont(QFINDTESTDATA("FreeMono.ttf")) { } From 97ed8f3c0ff300cd8d4b3c75b91f89e6ee355e10 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sat, 22 Feb 2014 14:48:02 +0100 Subject: [PATCH 085/124] Fix a getProcAddress in QOpenGLDebugLogger under Win32 + Desktop GL + ATI We can't resolve a "basic entry point" such as glGetPointerv on Windows' Desktop GL. Apparently NVIDIA drivers let us do that, but ATI ones don't. Change-Id: I8e8a54b5dcd3fe87f2bd677d1d0cf08b3e8c11c4 Reviewed-by: Thomas Steen Reviewed-by: James Turner Reviewed-by: Laszlo Agocs Reviewed-by: Sean Harmer --- src/gui/opengl/qopengldebug.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/gui/opengl/qopengldebug.cpp b/src/gui/opengl/qopengldebug.cpp index 90d062f4dd..2355d0a8a7 100644 --- a/src/gui/opengl/qopengldebug.cpp +++ b/src/gui/opengl/qopengldebug.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "qopengldebug.h" @@ -1364,7 +1365,20 @@ bool QOpenGLDebugLogger::initialize() GET_DEBUG_PROC_ADDRESS(glGetDebugMessageLog); GET_DEBUG_PROC_ADDRESS(glPushDebugGroup); GET_DEBUG_PROC_ADDRESS(glPopDebugGroup); + + // Windows' Desktop GL doesn't allow resolution of "basic GL entry points" + // through wglGetProcAddress +#if defined(Q_OS_WIN) && !defined(QT_OPENGL_ES_2) + { + HMODULE handle = static_cast(QOpenGLFunctions::platformGLHandle()); + if (!handle) + handle = GetModuleHandleA("opengl32.dll"); + d->glGetPointerv = reinterpret_cast(GetProcAddress(handle, QByteArrayLiteral("glGetPointerv"))); + } +#else GET_DEBUG_PROC_ADDRESS(glGetPointerv) +#endif + #undef GET_DEBUG_PROC_ADDRESS glGetIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, &d->maxMessageLength); From 45e17d0cc74d3444e23c18f73d6ac155659cec55 Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Sun, 23 Feb 2014 12:36:53 -0300 Subject: [PATCH 086/124] QNX: Prevent desktop windows from becoming root window If a QDesktopWidget is created before any other window, its underlying QPlatformWindow will be granted the root window role. Windows created afterwards will become children of the root window, preventing the app from being rendered, since the Qt::Desktop windows never get posted and therefore flushed. This patch prevents a Qt::Desktop window (related to QDesktopWidget) from becoming the root window. This does not affect QDesktopWidget functionality. Change-Id: I02c9946a3979b2227afbd2e5d485ba80efa1b997 Reviewed-by: Fabian Bumberger --- src/plugins/platforms/qnx/qqnxwindow.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index e57025cbc6..f2b57aec9a 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -88,8 +88,10 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW QQnxScreen *platformScreen = static_cast(window->screen()->handle()); - if (window->type() == Qt::CoverWindow) { + if (window->type() == Qt::CoverWindow || window->type() == Qt::Desktop) { // Cover windows have to be top level to be accessible to window delegate (i.e. navigator) + // Desktop windows also need to be toplevel because they are not + // supposed to be part of the window hierarchy tree m_isTopLevel = true; } else if (parent() || (window->type() & Qt::Dialog) == Qt::Dialog) { // If we have a parent we are a child window. Sometimes we have to be a child even if we @@ -104,7 +106,7 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW if (m_isTopLevel) { Q_SCREEN_CRITICALERROR(screen_create_window(&m_window, m_screenContext), "Could not create top level window"); // Creates an application window - if (window->type() != Qt::CoverWindow) { + if (window->type() != Qt::CoverWindow && window->type() != Qt::Desktop) { if (needRootWindow) platformScreen->setRootWindow(this); } From a7d093e740b1e20874b5ebeb37b5c5d76ae19e42 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 24 Feb 2014 11:18:33 +0200 Subject: [PATCH 087/124] Upgrade ANGLE to 1.3.5bb7ec572d0a This brings Qt's copy of ANGLE up to ANGLE master, which contains a number of bugfixes as well as restructuring for the upcoming ES 3.0 support. This version brings considerable stability improvements to the D3D11 renderer. The static translator project files have been merged to align with the ANGLE source tree. Two new patches have been applied to fix errors in upstream ANGLE: - 0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch The event trace header in ANGLE's third_party directory has an unused template which causes a compilation error on MinGW. Disable this part of the code. - 0012-ANGLE-fix-semantic-index-lookup.patch The sorted semantic index table was returning a direct mapping to the new indices, instead of the old indices. This caused a mismatch in the GL type lookup for the translated attribute. All other patches have been rebased, removed if no longer needed, and renamed to clear up the application order: - 0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch No changes. - 0001-Fix-compilation-with-MinGW-mingw-tdm64-gcc-4.8.1.patch No changes. Renamed to 0002. - 0001-Fix-compilation-with-MinGW-gcc-64-bit.patch No changes. Renamed to 0003. - 0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch Modified patch to adapt to new DLL loading structure. Renamed to 0004. - 0005-Fix-build-when-SSE2-is-not-available.patch No changes. - 0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch No changes. Renamed to 0006. - 0006-Make-DX9-DX11-mutually-exclusive.patch Made the patch less invasive by allowing D3D9 code to run unless explicitly disabled (e.g. on WinRT, where it doesn't compile). This makes the patch smaller and allows Desktop Windows to compile both D3D9 and D3D11 codepaths. Renamed to 0007. - 0015-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch No changes. Renamed to 0008. - 0012-ANGLE-Support-WinRT.patch Made D3D11_level9 initialization only possible if D3D9 is disabled. This makes sure Desktop PCs use the old D3D9 codepath instead of the less-tested D3D11_level9 codepath. Renamed to 0009. - 0013-Enable-D3D11-for-feature-level-9-cards.patch Conveniently smaller patch due to buffer implementation improvements upstream. Renamed to 0010. - 0014-ANGLE-D3D11-Alwayls-execute-QueryInterface.patch This was a fix for patch 0009, so was integrated there. Removed. - 0016-ANGLE-D3D11-Fix-build-on-desktop-Windows.patch This was a fix for patch 0009, so it was integrated there. Removed. - 0001-ANGLE-Fix-compilation-with-MSVC2013.patch Fixed upstream. Removed. - 0007-ANGLE-Fix-typedefs-for-Win64.patch Fixed upstream. Removed. - 0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch The issue has been fixed in Qt itself. Removed. - 0008-DX11-Prevent-assert-when-view-is-minimized-or-.patch The cause of the problem was the same as patch 0004, but for the D3D11 codepath. Removed. Change-Id: Id69484ab3a3e013050741c462fb1b06dfb0fd112 Reviewed-by: Friedemann Kleint Reviewed-by: Kai Koehne Reviewed-by: Oliver Wolff --- src/3rdparty/angle/AUTHORS | 2 + src/3rdparty/angle/LICENSE.preprocessor | 45 - .../angle/include/GLSLANG/ShaderLang.h | 33 +- src/3rdparty/angle/include/KHR/khrplatform.h | 8 +- src/3rdparty/angle/src/commit.h | 2 + src/3rdparty/angle/src/common/angleutils.h | 14 + src/3rdparty/angle/src/common/debug.cpp | 44 +- src/3rdparty/angle/src/common/debug.h | 32 +- .../angle/src/common/event_tracer.cpp | 2 +- src/3rdparty/angle/src/common/event_tracer.h | 12 +- src/3rdparty/angle/src/common/system.h | 26 - src/3rdparty/angle/src/common/version.h | 18 +- .../angle/src/compiler/CodeGenHLSL.cpp | 33 - .../angle/src/compiler/DetectRecursion.cpp | 125 -- .../angle/src/compiler/DetectRecursion.h | 60 - .../src/compiler/InitializeGLPosition.cpp | 61 - .../angle/src/compiler/InitializeGLPosition.h | 33 - .../angle/src/compiler/IntermTraverse.cpp | 293 ----- .../compiler/preprocessor/DiagnosticsBase.cpp | 84 +- .../compiler/preprocessor/DiagnosticsBase.h | 86 +- .../compiler/preprocessor/DirectiveParser.cpp | 78 +- .../compiler/preprocessor/ExpressionParser.y | 18 +- .../compiler/preprocessor/MacroExpander.cpp | 6 +- .../compiler/preprocessor/Preprocessor.cpp | 4 +- .../src/compiler/preprocessor/Tokenizer.l | 4 +- .../src/compiler/{ => translator}/BaseTypes.h | 1 + .../BuiltInFunctionEmulator.cpp | 4 +- .../BuiltInFunctionEmulator.h | 4 +- .../CodeGen.cpp} | 12 +- .../src/compiler/{ => translator}/Common.h | 17 +- .../compiler/{ => translator}/Compiler.cpp | 216 +++- .../compiler/{ => translator}/ConstantUnion.h | 0 .../{ => translator}/DetectCallDepth.cpp | 4 +- .../{ => translator}/DetectCallDepth.h | 4 +- .../{ => translator}/DetectDiscontinuity.cpp | 4 +- .../{ => translator}/DetectDiscontinuity.h | 2 +- .../compiler/{ => translator}/Diagnostics.cpp | 10 +- .../compiler/{ => translator}/Diagnostics.h | 0 .../{ => translator}/DirectiveHandler.cpp | 26 +- .../{ => translator}/DirectiveHandler.h | 4 +- .../{ => translator}/ExtensionBehavior.h | 0 .../{ => translator}/ForLoopUnroll.cpp | 2 +- .../compiler/{ => translator}/ForLoopUnroll.h | 6 +- .../src/compiler/{ => translator}/HashNames.h | 2 +- .../compiler/{ => translator}/InfoSink.cpp | 2 +- .../src/compiler/{ => translator}/InfoSink.h | 3 +- .../compiler/{ => translator}/Initialize.cpp | 6 +- .../compiler/{ => translator}/Initialize.h | 6 +- .../{ => translator}/InitializeDll.cpp | 8 +- .../compiler/{ => translator}/InitializeDll.h | 0 .../{ => translator}/InitializeGlobals.h | 0 .../InitializeParseContext.cpp | 4 +- .../{ => translator}/InitializeParseContext.h | 0 .../translator/InitializeVariables.cpp | 116 ++ .../compiler/translator/InitializeVariables.h | 50 + .../compiler/translator/IntermTraverse.cpp | 259 ++++ .../{ => translator}/Intermediate.cpp | 76 +- .../src/compiler/{ => translator}/MMap.h | 0 .../{ => translator}/MapLongVariableNames.cpp | 9 +- .../{ => translator}/MapLongVariableNames.h | 5 +- .../src/compiler/translator/NodeSearch.h | 80 ++ .../compiler/{ => translator}/OutputESSL.cpp | 2 +- .../compiler/{ => translator}/OutputESSL.h | 2 +- .../compiler/{ => translator}/OutputGLSL.cpp | 2 +- .../compiler/{ => translator}/OutputGLSL.h | 2 +- .../{ => translator}/OutputGLSLBase.cpp | 12 +- .../{ => translator}/OutputGLSLBase.h | 6 +- .../compiler/{ => translator}/OutputHLSL.cpp | 90 +- .../compiler/{ => translator}/OutputHLSL.h | 7 +- .../ParseContext.cpp} | 10 +- .../ParseContext.h} | 10 +- .../compiler/{ => translator}/PoolAlloc.cpp | 6 +- .../src/compiler/{ => translator}/PoolAlloc.h | 0 .../src/compiler/{ => translator}/Pragma.h | 0 .../{ => translator}/QualifierAlive.cpp | 2 +- .../{ => translator}/QualifierAlive.h | 0 .../compiler/{ => translator}/RemoveTree.cpp | 4 +- .../compiler/{ => translator}/RemoveTree.h | 0 .../{ => translator}/RenameFunction.h | 2 +- .../compiler/translator/RewriteElseBlocks.cpp | 98 ++ .../compiler/translator/RewriteElseBlocks.h | 39 + .../{ => translator}/SearchSymbol.cpp | 6 +- .../compiler/{ => translator}/SearchSymbol.h | 4 +- .../src/compiler/{ => translator}/ShHandle.h | 22 +- .../compiler/{ => translator}/ShaderLang.cpp | 11 +- .../compiler/{ => translator}/SymbolTable.cpp | 2 +- .../compiler/{ => translator}/SymbolTable.h | 4 +- .../{ => translator}/TranslatorESSL.cpp | 4 +- .../{ => translator}/TranslatorESSL.h | 2 +- .../{ => translator}/TranslatorGLSL.cpp | 6 +- .../{ => translator}/TranslatorGLSL.h | 2 +- .../{ => translator}/TranslatorHLSL.cpp | 6 +- .../{ => translator}/TranslatorHLSL.h | 4 +- .../src/compiler/{ => translator}/Types.h | 26 +- .../{ => translator}/UnfoldShortCircuit.cpp | 20 +- .../{ => translator}/UnfoldShortCircuit.h | 4 +- .../translator/UnfoldShortCircuitAST.cpp | 81 ++ .../translator/UnfoldShortCircuitAST.h | 51 + .../src/compiler/{ => translator}/Uniform.cpp | 2 +- .../src/compiler/{ => translator}/Uniform.h | 0 .../{ => translator}/ValidateLimitations.cpp | 10 +- .../{ => translator}/ValidateLimitations.h | 2 +- .../{ => translator}/VariableInfo.cpp | 6 +- .../compiler/{ => translator}/VariableInfo.h | 3 +- .../{ => translator}/VariablePacker.cpp | 4 +- .../{ => translator}/VariablePacker.h | 2 +- .../compiler/{ => translator}/VersionGLSL.cpp | 2 +- .../compiler/{ => translator}/VersionGLSL.h | 2 +- .../compilerdebug.cpp} | 10 +- .../{debug.h => translator/compilerdebug.h} | 0 .../depgraph/DependencyGraph.cpp | 4 +- .../depgraph/DependencyGraph.h | 2 +- .../depgraph/DependencyGraphBuilder.cpp | 4 +- .../depgraph/DependencyGraphBuilder.h | 2 +- .../depgraph/DependencyGraphOutput.cpp | 2 +- .../depgraph/DependencyGraphOutput.h | 4 +- .../depgraph/DependencyGraphTraverse.cpp | 2 +- .../src/compiler/{ => translator}/glslang.h | 0 .../src/compiler/{ => translator}/glslang.l | 6 +- .../src/compiler/{ => translator}/glslang.y | 54 +- .../compiler/{ => translator}/intermOut.cpp | 6 +- .../compiler/{ => translator}/intermediate.h | 80 +- .../{ => translator}/localintermediate.h | 6 +- .../src/compiler/{ => translator}/osinclude.h | 20 +- .../{ => translator}/ossource_posix.cpp | 2 +- .../{ => translator}/ossource_win.cpp | 2 +- .../{ => translator}/ossource_winrt.cpp | 2 +- .../compiler/{ => translator}/parseConst.cpp | 2 +- .../timing/RestrictFragmentShaderTiming.cpp | 8 +- .../timing/RestrictFragmentShaderTiming.h | 4 +- .../timing/RestrictVertexShaderTiming.cpp | 2 +- .../timing/RestrictVertexShaderTiming.h | 4 +- .../src/compiler/{ => translator}/util.cpp | 2 +- .../src/compiler/{ => translator}/util.h | 0 src/3rdparty/angle/src/libEGL/Display.cpp | 11 +- src/3rdparty/angle/src/libEGL/Display.h | 5 +- src/3rdparty/angle/src/libEGL/Surface.cpp | 41 +- src/3rdparty/angle/src/libEGL/Surface.h | 3 +- src/3rdparty/angle/src/libEGL/libEGL.cpp | 12 +- src/3rdparty/angle/src/libEGL/libEGL.rc | 11 +- src/3rdparty/angle/src/libEGL/main.cpp | 135 ++- src/3rdparty/angle/src/libGLESv2/Buffer.cpp | 8 +- src/3rdparty/angle/src/libGLESv2/Buffer.h | 4 +- src/3rdparty/angle/src/libGLESv2/Context.cpp | 30 +- src/3rdparty/angle/src/libGLESv2/Context.h | 9 +- .../angle/src/libGLESv2/Framebuffer.h | 2 +- .../angle/src/libGLESv2/ProgramBinary.cpp | 37 +- .../angle/src/libGLESv2/Renderbuffer.cpp | 15 + .../angle/src/libGLESv2/Renderbuffer.h | 5 + src/3rdparty/angle/src/libGLESv2/Shader.cpp | 2 + src/3rdparty/angle/src/libGLESv2/Shader.h | 3 +- src/3rdparty/angle/src/libGLESv2/Texture.cpp | 8 +- .../angle/src/libGLESv2/libGLESv2.cpp | 10 +- src/3rdparty/angle/src/libGLESv2/libGLESv2.rc | 11 +- src/3rdparty/angle/src/libGLESv2/main.cpp | 112 +- src/3rdparty/angle/src/libGLESv2/main.h | 3 +- src/3rdparty/angle/src/libGLESv2/mathutil.h | 1 - .../angle/src/libGLESv2/precompiled.h | 59 +- .../src/libGLESv2/renderer/BufferStorage.h | 2 +- .../libGLESv2/renderer/BufferStorage11.cpp | 361 ------ .../src/libGLESv2/renderer/BufferStorage11.h | 56 - .../angle/src/libGLESv2/renderer/Renderer.cpp | 85 +- .../angle/src/libGLESv2/renderer/Renderer.h | 34 +- .../angle/src/libGLESv2/renderer/SwapChain.h | 7 +- .../libGLESv2/renderer/VertexDataManager.cpp | 4 + .../renderer/d3d11/BufferStorage11.cpp | 366 ++++++ .../renderer/d3d11/BufferStorage11.h | 92 ++ .../renderer/{ => d3d11}/Fence11.cpp | 4 +- .../libGLESv2/renderer/{ => d3d11}/Fence11.h | 0 .../renderer/{ => d3d11}/Image11.cpp | 48 +- .../libGLESv2/renderer/{ => d3d11}/Image11.h | 0 .../renderer/{ => d3d11}/IndexBuffer11.cpp | 8 +- .../renderer/{ => d3d11}/IndexBuffer11.h | 0 .../renderer/{ => d3d11}/InputLayoutCache.cpp | 14 +- .../renderer/{ => d3d11}/InputLayoutCache.h | 0 .../renderer/{ => d3d11}/Query11.cpp | 4 +- .../libGLESv2/renderer/{ => d3d11}/Query11.h | 0 .../renderer/{ => d3d11}/RenderStateCache.cpp | 60 +- .../renderer/{ => d3d11}/RenderStateCache.h | 22 +- .../renderer/{ => d3d11}/RenderTarget11.cpp | 6 +- .../renderer/{ => d3d11}/RenderTarget11.h | 0 .../renderer/{ => d3d11}/Renderer11.cpp | 406 ++++--- .../renderer/{ => d3d11}/Renderer11.h | 20 +- .../{ => d3d11}/ShaderExecutable11.cpp | 2 +- .../renderer/{ => d3d11}/ShaderExecutable11.h | 0 .../renderer/{ => d3d11}/SwapChain11.cpp | 215 +--- .../renderer/{ => d3d11}/SwapChain11.h | 0 .../renderer/{ => d3d11}/TextureStorage11.cpp | 18 +- .../renderer/{ => d3d11}/TextureStorage11.h | 0 .../renderer/{ => d3d11}/VertexBuffer11.cpp | 4 +- .../renderer/{ => d3d11}/VertexBuffer11.h | 0 .../renderer/{ => d3d11}/renderer11_utils.cpp | 2 +- .../renderer/{ => d3d11}/renderer11_utils.h | 0 .../renderer/{ => d3d11}/shaders/Clear11.hlsl | 0 .../{ => d3d11}/shaders/Passthrough11.hlsl | 0 .../libGLESv2/renderer/{ => d3d9}/Blit.cpp | 20 +- .../src/libGLESv2/renderer/{ => d3d9}/Blit.h | 0 .../renderer/{ => d3d9}/BufferStorage9.cpp | 4 +- .../renderer/{ => d3d9}/BufferStorage9.h | 2 +- .../libGLESv2/renderer/{ => d3d9}/Fence9.cpp | 6 +- .../libGLESv2/renderer/{ => d3d9}/Fence9.h | 0 .../libGLESv2/renderer/{ => d3d9}/Image9.cpp | 12 +- .../libGLESv2/renderer/{ => d3d9}/Image9.h | 0 .../renderer/{ => d3d9}/IndexBuffer9.cpp | 4 +- .../renderer/{ => d3d9}/IndexBuffer9.h | 0 .../libGLESv2/renderer/{ => d3d9}/Query9.cpp | 6 +- .../libGLESv2/renderer/{ => d3d9}/Query9.h | 0 .../renderer/{ => d3d9}/RenderTarget9.cpp | 6 +- .../renderer/{ => d3d9}/RenderTarget9.h | 0 .../renderer/{ => d3d9}/Renderer9.cpp | 207 ++-- .../libGLESv2/renderer/{ => d3d9}/Renderer9.h | 14 +- .../renderer/{ => d3d9}/ShaderExecutable9.cpp | 2 +- .../renderer/{ => d3d9}/ShaderExecutable9.h | 0 .../renderer/{ => d3d9}/SwapChain9.cpp | 44 +- .../renderer/{ => d3d9}/SwapChain9.h | 0 .../renderer/{ => d3d9}/TextureStorage9.cpp | 10 +- .../renderer/{ => d3d9}/TextureStorage9.h | 0 .../renderer/{ => d3d9}/VertexBuffer9.cpp | 8 +- .../renderer/{ => d3d9}/VertexBuffer9.h | 0 .../{ => d3d9}/VertexDeclarationCache.cpp | 4 +- .../{ => d3d9}/VertexDeclarationCache.h | 0 .../renderer/{ => d3d9}/renderer9_utils.cpp | 2 +- .../renderer/{ => d3d9}/renderer9_utils.h | 0 .../renderer/{ => d3d9}/shaders/Blit.ps | 0 .../renderer/{ => d3d9}/shaders/Blit.vs | 0 .../renderer/{ => d3d9}/vertexconversion.h | 0 .../angle/src/libGLESv2/utilities.cpp | 63 +- .../third_party/compiler/ArrayBoundsClamper.h | 4 +- .../src/third_party/trace_event/trace_event.h | 4 +- ...-ANGLE-Fix-compilation-with-MSVC2013.patch | 28 - ...pilation-for-MSVC-2008-and-std-tuple.patch | 15 +- ...-to-link-ANGLE-statically-for-single.patch | 200 ---- ...of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch} | 10 +- ...x-compilation-with-MinGW-gcc-64-bit.patch} | 10 +- ...-after-minimizing-OpenGL-window-with.patch | 45 - ...-to-link-ANGLE-statically-for-single.patch | 68 ++ ...Fix-build-when-SSE2-is-not-available.patch | 33 +- ...f-libGLESv2-with-older-MinGW-w64-he.patch} | 17 +- ...006-Make-DX9-DX11-mutually-exclusive.patch | 149 --- .../0007-ANGLE-Fix-typedefs-for-Win64.patch | 38 - ...007-Make-DX9-DX11-mutually-exclusive.patch | 141 +++ ...nt-assert-when-view-is-minimized-or-.patch | 58 - ...-load-D3D-compiler-from-a-list-of-k.patch} | 50 +- ...T.patch => 0009-ANGLE-Support-WinRT.patch} | 1047 +++++++++-------- ...able-D3D11-for-feature-level-9-cards.patch | 426 +++++++ ...ation-error-on-MinGW-caused-by-trace.patch | 37 + ...0012-ANGLE-fix-semantic-index-lookup.patch | 48 + ...able-D3D11-for-feature-level-9-cards.patch | 990 ---------------- ...-D3D11-Always-execute-QueryInterface.patch | 51 - ...E-D3D11-Fix-build-on-desktop-Windows.patch | 28 - src/angle/src/compiler/compiler.pro | 2 +- .../compiler/preprocessor/preprocessor.pro | 1 + src/angle/src/compiler/translator.pro | 163 +++ src/angle/src/compiler/translator_common.pro | 133 --- src/angle/src/compiler/translator_hlsl.pro | 30 - src/angle/src/config.pri | 14 +- src/angle/src/libEGL/libEGL.pro | 6 +- src/angle/src/libGLESv2/libGLESv2.pro | 157 +-- 258 files changed, 4769 insertions(+), 4902 deletions(-) delete mode 100644 src/3rdparty/angle/LICENSE.preprocessor create mode 100644 src/3rdparty/angle/src/commit.h delete mode 100644 src/3rdparty/angle/src/common/system.h delete mode 100644 src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp delete mode 100644 src/3rdparty/angle/src/compiler/DetectRecursion.cpp delete mode 100644 src/3rdparty/angle/src/compiler/DetectRecursion.h delete mode 100644 src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp delete mode 100644 src/3rdparty/angle/src/compiler/InitializeGLPosition.h delete mode 100644 src/3rdparty/angle/src/compiler/IntermTraverse.cpp rename src/3rdparty/angle/src/compiler/{ => translator}/BaseTypes.h (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/BuiltInFunctionEmulator.cpp (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/BuiltInFunctionEmulator.h (97%) rename src/3rdparty/angle/src/compiler/{CodeGenGLSL.cpp => translator/CodeGen.cpp} (74%) rename src/3rdparty/angle/src/compiler/{ => translator}/Common.h (85%) rename src/3rdparty/angle/src/compiler/{ => translator}/Compiler.cpp (70%) rename src/3rdparty/angle/src/compiler/{ => translator}/ConstantUnion.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/DetectCallDepth.cpp (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/DetectCallDepth.h (95%) rename src/3rdparty/angle/src/compiler/{ => translator}/DetectDiscontinuity.cpp (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/DetectDiscontinuity.h (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/Diagnostics.cpp (89%) rename src/3rdparty/angle/src/compiler/{ => translator}/Diagnostics.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/DirectiveHandler.cpp (84%) rename src/3rdparty/angle/src/compiler/{ => translator}/DirectiveHandler.h (93%) rename src/3rdparty/angle/src/compiler/{ => translator}/ExtensionBehavior.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/ForLoopUnroll.cpp (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/ForLoopUnroll.h (90%) rename src/3rdparty/angle/src/compiler/{ => translator}/HashNames.h (90%) rename src/3rdparty/angle/src/compiler/{ => translator}/InfoSink.cpp (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/InfoSink.h (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/Initialize.cpp (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/Initialize.h (84%) rename src/3rdparty/angle/src/compiler/{ => translator}/InitializeDll.cpp (74%) rename src/3rdparty/angle/src/compiler/{ => translator}/InitializeDll.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/InitializeGlobals.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/InitializeParseContext.cpp (91%) rename src/3rdparty/angle/src/compiler/{ => translator}/InitializeParseContext.h (100%) create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/InitializeVariables.h create mode 100644 src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp rename src/3rdparty/angle/src/compiler/{ => translator}/Intermediate.cpp (95%) rename src/3rdparty/angle/src/compiler/{ => translator}/MMap.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/MapLongVariableNames.cpp (93%) rename src/3rdparty/angle/src/compiler/{ => translator}/MapLongVariableNames.h (92%) create mode 100644 src/3rdparty/angle/src/compiler/translator/NodeSearch.h rename src/3rdparty/angle/src/compiler/{ => translator}/OutputESSL.cpp (94%) rename src/3rdparty/angle/src/compiler/{ => translator}/OutputESSL.h (93%) rename src/3rdparty/angle/src/compiler/{ => translator}/OutputGLSL.cpp (95%) rename src/3rdparty/angle/src/compiler/{ => translator}/OutputGLSL.h (93%) rename src/3rdparty/angle/src/compiler/{ => translator}/OutputGLSLBase.cpp (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/OutputGLSLBase.h (95%) rename src/3rdparty/angle/src/compiler/{ => translator}/OutputHLSL.cpp (97%) rename src/3rdparty/angle/src/compiler/{ => translator}/OutputHLSL.h (96%) rename src/3rdparty/angle/src/compiler/{ParseHelper.cpp => translator/ParseContext.cpp} (99%) rename src/3rdparty/angle/src/compiler/{ParseHelper.h => translator/ParseContext.h} (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/PoolAlloc.cpp (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/PoolAlloc.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/Pragma.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/QualifierAlive.cpp (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/QualifierAlive.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/RemoveTree.cpp (93%) rename src/3rdparty/angle/src/compiler/{ => translator}/RemoveTree.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/RenameFunction.h (95%) create mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h rename src/3rdparty/angle/src/compiler/{ => translator}/SearchSymbol.cpp (83%) rename src/3rdparty/angle/src/compiler/{ => translator}/SearchSymbol.h (87%) rename src/3rdparty/angle/src/compiler/{ => translator}/ShHandle.h (86%) rename src/3rdparty/angle/src/compiler/{ => translator}/ShaderLang.cpp (97%) rename src/3rdparty/angle/src/compiler/{ => translator}/SymbolTable.cpp (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/SymbolTable.h (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/TranslatorESSL.cpp (93%) rename src/3rdparty/angle/src/compiler/{ => translator}/TranslatorESSL.h (92%) rename src/3rdparty/angle/src/compiler/{ => translator}/TranslatorGLSL.cpp (90%) rename src/3rdparty/angle/src/compiler/{ => translator}/TranslatorGLSL.h (91%) rename src/3rdparty/angle/src/compiler/{ => translator}/TranslatorHLSL.cpp (80%) rename src/3rdparty/angle/src/compiler/{ => translator}/TranslatorHLSL.h (89%) rename src/3rdparty/angle/src/compiler/{ => translator}/Types.h (93%) rename src/3rdparty/angle/src/compiler/{ => translator}/UnfoldShortCircuit.cpp (88%) rename src/3rdparty/angle/src/compiler/{ => translator}/UnfoldShortCircuit.h (90%) create mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h rename src/3rdparty/angle/src/compiler/{ => translator}/Uniform.cpp (91%) rename src/3rdparty/angle/src/compiler/{ => translator}/Uniform.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/ValidateLimitations.cpp (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/ValidateLimitations.h (97%) rename src/3rdparty/angle/src/compiler/{ => translator}/VariableInfo.cpp (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/VariableInfo.h (95%) rename src/3rdparty/angle/src/compiler/{ => translator}/VariablePacker.cpp (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/VariablePacker.h (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/VersionGLSL.cpp (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/VersionGLSL.h (97%) rename src/3rdparty/angle/src/compiler/{debug.cpp => translator/compilerdebug.cpp} (83%) rename src/3rdparty/angle/src/compiler/{debug.h => translator/compilerdebug.h} (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/depgraph/DependencyGraph.cpp (95%) rename src/3rdparty/angle/src/compiler/{ => translator}/depgraph/DependencyGraph.h (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/depgraph/DependencyGraphBuilder.cpp (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/depgraph/DependencyGraphBuilder.h (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/depgraph/DependencyGraphOutput.cpp (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/depgraph/DependencyGraphOutput.h (90%) rename src/3rdparty/angle/src/compiler/{ => translator}/depgraph/DependencyGraphTraverse.cpp (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/glslang.h (100%) rename src/3rdparty/angle/src/compiler/{ => translator}/glslang.l (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/glslang.y (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/intermOut.cpp (98%) rename src/3rdparty/angle/src/compiler/{ => translator}/intermediate.h (84%) rename src/3rdparty/angle/src/compiler/{ => translator}/localintermediate.h (95%) rename src/3rdparty/angle/src/compiler/{ => translator}/osinclude.h (87%) rename src/3rdparty/angle/src/compiler/{ => translator}/ossource_posix.cpp (97%) rename src/3rdparty/angle/src/compiler/{ => translator}/ossource_win.cpp (96%) rename src/3rdparty/angle/src/compiler/{ => translator}/ossource_winrt.cpp (97%) rename src/3rdparty/angle/src/compiler/{ => translator}/parseConst.cpp (99%) rename src/3rdparty/angle/src/compiler/{ => translator}/timing/RestrictFragmentShaderTiming.cpp (95%) rename src/3rdparty/angle/src/compiler/{ => translator}/timing/RestrictFragmentShaderTiming.h (92%) rename src/3rdparty/angle/src/compiler/{ => translator}/timing/RestrictVertexShaderTiming.cpp (87%) rename src/3rdparty/angle/src/compiler/{ => translator}/timing/RestrictVertexShaderTiming.h (90%) rename src/3rdparty/angle/src/compiler/{ => translator}/util.cpp (94%) rename src/3rdparty/angle/src/compiler/{ => translator}/util.h (100%) delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/Fence11.cpp (96%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/Fence11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/Image11.cpp (89%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/Image11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/IndexBuffer11.cpp (95%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/IndexBuffer11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/InputLayoutCache.cpp (94%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/InputLayoutCache.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/Query11.cpp (96%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/Query11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/RenderStateCache.cpp (88%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/RenderStateCache.h (83%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/RenderTarget11.cpp (98%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/RenderTarget11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/Renderer11.cpp (94%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/Renderer11.h (95%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/ShaderExecutable11.cpp (98%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/ShaderExecutable11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/SwapChain11.cpp (86%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/SwapChain11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/TextureStorage11.cpp (97%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/TextureStorage11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/VertexBuffer11.cpp (99%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/VertexBuffer11.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/renderer11_utils.cpp (99%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/renderer11_utils.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/shaders/Clear11.hlsl (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d11}/shaders/Passthrough11.hlsl (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Blit.cpp (96%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Blit.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/BufferStorage9.cpp (94%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/BufferStorage9.h (95%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Fence9.cpp (95%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Fence9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Image9.cpp (98%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Image9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/IndexBuffer9.cpp (97%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/IndexBuffer9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Query9.cpp (94%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Query9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/RenderTarget9.cpp (95%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/RenderTarget9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Renderer9.cpp (96%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/Renderer9.h (96%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/ShaderExecutable9.cpp (96%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/ShaderExecutable9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/SwapChain9.cpp (95%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/SwapChain9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/TextureStorage9.cpp (97%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/TextureStorage9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/VertexBuffer9.cpp (99%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/VertexBuffer9.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/VertexDeclarationCache.cpp (98%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/VertexDeclarationCache.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/renderer9_utils.cpp (99%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/renderer9_utils.h (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/shaders/Blit.ps (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/shaders/Blit.vs (100%) rename src/3rdparty/angle/src/libGLESv2/renderer/{ => d3d9}/vertexconversion.h (100%) delete mode 100644 src/angle/patches/0001-ANGLE-Fix-compilation-with-MSVC2013.patch delete mode 100644 src/angle/patches/0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch rename src/angle/patches/{0001-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch => 0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch} (83%) rename src/angle/patches/{0001-Fix-compilation-with-MinGW-gcc-64-bit.patch => 0003-Fix-compilation-with-MinGW-gcc-64-bit.patch} (83%) delete mode 100644 src/angle/patches/0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch create mode 100644 src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch rename src/angle/patches/{0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch => 0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch} (84%) delete mode 100644 src/angle/patches/0006-Make-DX9-DX11-mutually-exclusive.patch delete mode 100644 src/angle/patches/0007-ANGLE-Fix-typedefs-for-Win64.patch create mode 100644 src/angle/patches/0007-Make-DX9-DX11-mutually-exclusive.patch delete mode 100644 src/angle/patches/0008-ANGLE-DX11-Prevent-assert-when-view-is-minimized-or-.patch rename src/angle/patches/{0015-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch => 0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch} (63%) rename src/angle/patches/{0012-ANGLE-Support-WinRT.patch => 0009-ANGLE-Support-WinRT.patch} (55%) create mode 100644 src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch create mode 100644 src/angle/patches/0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch create mode 100644 src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch delete mode 100644 src/angle/patches/0013-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch delete mode 100644 src/angle/patches/0014-ANGLE-D3D11-Always-execute-QueryInterface.patch delete mode 100644 src/angle/patches/0016-ANGLE-D3D11-Fix-build-on-desktop-Windows.patch create mode 100644 src/angle/src/compiler/translator.pro delete mode 100644 src/angle/src/compiler/translator_common.pro delete mode 100644 src/angle/src/compiler/translator_hlsl.pro diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS index a2ce91575a..0bdb65ee9a 100644 --- a/src/3rdparty/angle/AUTHORS +++ b/src/3rdparty/angle/AUTHORS @@ -13,6 +13,8 @@ TransGaming Inc. Adobe Systems Inc. Autodesk, Inc. +BlackBerry Limited +Cable Television Laboratories, Inc. Cloud Party, Inc. Intel Corporation Mozilla Corporation diff --git a/src/3rdparty/angle/LICENSE.preprocessor b/src/3rdparty/angle/LICENSE.preprocessor deleted file mode 100644 index 0ec2123b61..0000000000 --- a/src/3rdparty/angle/LICENSE.preprocessor +++ /dev/null @@ -1,45 +0,0 @@ -Files in src/compiler/preprocessor are provided under the following license: - -**************************************************************************** -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**************************************************************************** diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index 28bf516f7f..9912939b95 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -6,20 +6,20 @@ #ifndef _COMPILER_INTERFACE_INCLUDED_ #define _COMPILER_INTERFACE_INCLUDED_ -#if defined(COMPONENT_BUILD) +#if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC) #if defined(_WIN32) || defined(_WIN64) -#if defined(COMPILER_IMPLEMENTATION) +#if defined(ANGLE_TRANSLATOR_IMPLEMENTATION) #define COMPILER_EXPORT __declspec(dllexport) #else #define COMPILER_EXPORT __declspec(dllimport) -#endif // defined(COMPILER_IMPLEMENTATION) +#endif // defined(ANGLE_TRANSLATOR_IMPLEMENTATION) -#else // defined(WIN32) +#else // defined(_WIN32) || defined(_WIN64) #define COMPILER_EXPORT __attribute__((visibility("default"))) #endif -#else // defined(COMPONENT_BUILD) +#else // defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC) #define COMPILER_EXPORT #endif @@ -146,14 +146,14 @@ typedef enum { // This is needed only as a workaround for certain OpenGL driver bugs. SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100, - // This is an experimental flag to enforce restrictions that aim to prevent + // This is an experimental flag to enforce restrictions that aim to prevent // timing attacks. // It generates compilation errors for shaders that could expose sensitive // texture information via the timing channel. // To use this flag, you must compile the shader under the WebGL spec // (using the SH_WEBGL_SPEC flag). SH_TIMING_RESTRICTIONS = 0x0200, - + // This flag prints the dependency graph that is used to enforce timing // restrictions on fragment shaders. // This flag only has an effect if all of the following are true: @@ -184,11 +184,24 @@ typedef enum { // This flag limits the depth of the call stack. SH_LIMIT_CALL_STACK_DEPTH = 0x4000, - // This flag initializes gl_Position to vec4(0.0, 0.0, 0.0, 1.0) at - // the beginning of the vertex shader, and has no effect in the + // This flag initializes gl_Position to vec4(0,0,0,0) at the + // beginning of the vertex shader's main(), and has no effect in the // fragment shader. It is intended as a workaround for drivers which // incorrectly fail to link programs if gl_Position is not written. SH_INIT_GL_POSITION = 0x8000, + + // This flag replaces + // "a && b" with "a ? b : false", + // "a || b" with "a ? true : b". + // This is to work around a MacOSX driver bug that |b| is executed + // independent of |a|'s value. + SH_UNFOLD_SHORT_CIRCUIT = 0x10000, + + // This flag initializes varyings without static use in vertex shader + // at the beginning of main(), and has no effects in the fragment shader. + // It is intended as a workaround for drivers which incorrectly optimize + // out such varyings and cause a link failure. + SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000, } ShCompileOptions; // Defines alternate strategies for implementing array index clamping. @@ -267,7 +280,7 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); // // ShHandle held by but opaque to the driver. It is allocated, -// managed, and de-allocated by the compiler. It's contents +// managed, and de-allocated by the compiler. It's contents // are defined by and used by the compiler. // // If handle creation fails, 0 will be returned. diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h index 001e925f46..1ac2d3f324 100644 --- a/src/3rdparty/angle/include/KHR/khrplatform.h +++ b/src/3rdparty/angle/include/KHR/khrplatform.h @@ -26,7 +26,7 @@ /* Khronos platform-specific types and definitions. * - * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $ + * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $ * * Adopters may modify this file to suit their platform. Adopters are * encouraged to submit platform specific modifications to the Khronos @@ -221,6 +221,12 @@ typedef signed char khronos_int8_t; typedef unsigned char khronos_uint8_t; typedef signed short int khronos_int16_t; typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ #ifdef _WIN64 typedef signed long long int khronos_intptr_t; typedef unsigned long long int khronos_uintptr_t; diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h new file mode 100644 index 0000000000..f4a36a3cfe --- /dev/null +++ b/src/3rdparty/angle/src/commit.h @@ -0,0 +1,2 @@ +#define ANGLE_COMMIT_HASH "5bb7ec572d0a" +#define ANGLE_COMMIT_HASH_SIZE 12 diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index 9761567fb2..7723f0fb72 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -42,6 +42,20 @@ void SafeRelease(T& resource) } } +template +void SafeDelete(T*& resource) +{ + delete resource; + resource = NULL; +} + +template +void SafeDeleteArray(T*& resource) +{ + delete[] resource; + resource = NULL; +} + #if defined(_MSC_VER) #define snprintf _snprintf #endif diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index 9b932567b0..05d3dc62ad 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -7,21 +7,23 @@ // debug.cpp: Debugging utilities. #include "common/debug.h" -#include "common/system.h" -#ifndef ANGLE_ENABLE_D3D11 +#include + +#if defined(ANGLE_ENABLE_PERF) #include -#else -typedef DWORD D3DCOLOR; #endif namespace gl { - +#if defined(ANGLE_ENABLE_PERF) typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR); +#else +typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*); +#endif static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg) { -#if !defined(ANGLE_DISABLE_PERF) +#if defined(ANGLE_ENABLE_PERF) if (perfActive()) { char message[32768]; @@ -41,15 +43,15 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c perfFunc(0, wideMessage); } -#endif +#endif // ANGLE_ENABLE_PERF -#if !defined(ANGLE_DISABLE_TRACE) +#if defined(ANGLE_ENABLE_TRACE) #if defined(NDEBUG) if (traceFileDebugOnly) { return; } -#endif +#endif // NDEBUG FILE* file = fopen(TRACE_OUTPUT_FILE, "a"); if (file) @@ -57,50 +59,50 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c vfprintf(file, format, vararg); fclose(file); } -#endif +#endif // ANGLE_ENABLE_TRACE } void trace(bool traceFileDebugOnly, const char *format, ...) { va_list vararg; va_start(vararg, format); -#if defined(ANGLE_DISABLE_PERF) - output(traceFileDebugOnly, NULL, format, vararg); -#else +#if defined(ANGLE_ENABLE_PERF) output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg); +#else + output(traceFileDebugOnly, NULL, format, vararg); #endif va_end(vararg); } bool perfActive() { -#if defined(ANGLE_DISABLE_PERF) - return false; -#else +#if defined(ANGLE_ENABLE_PERF) static bool active = D3DPERF_GetStatus() != 0; return active; +#else + return false; #endif } ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) { -#if !defined(ANGLE_DISABLE_PERF) -#if defined(ANGLE_DISABLE_TRACE) +#if defined(ANGLE_ENABLE_PERF) +#if !defined(ANGLE_ENABLE_TRACE) if (!perfActive()) { return; } -#endif +#endif // !ANGLE_ENABLE_TRACE va_list vararg; va_start(vararg, format); output(true, reinterpret_cast(D3DPERF_BeginEvent), format, vararg); va_end(vararg); -#endif +#endif // ANGLE_ENABLE_PERF } ScopedPerfEventHelper::~ScopedPerfEventHelper() { -#if !defined(ANGLE_DISABLE_PERF) +#if defined(ANGLE_ENABLE_PERF) if (perfActive()) { D3DPERF_EndEvent(); diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index 23ee26d23b..793843895c 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -39,33 +39,35 @@ namespace gl } // A macro to output a trace of a function call and its arguments to the debugging log -#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) -#define TRACE(message, ...) (void(0)) -#else +#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) #define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define TRACE(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. -#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) -#define FIXME(message, ...) (void(0)) -#else +#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) #define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define FIXME(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, in case of error. -#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) -#define ERR(message, ...) (void(0)) -#else +#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) #define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define ERR(message, ...) (void(0)) #endif // A macro to log a performance event around a scope. -#if defined(ANGLE_DISABLE_TRACE) && defined(ANGLE_DISABLE_PERF) -#define EVENT(message, ...) (void(0)) -#elif defined(_MSC_VER) +#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(_MSC_VER) #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__); #else #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__); +#endif // _MSC_VER +#else +#define EVENT(message, ...) (void(0)) #endif // A macro asserting a condition and outputting failures to the debug log @@ -99,8 +101,10 @@ namespace gl #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__) #endif -// A macro that determines whether an object has a given runtime type. -#if !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) +// A macro that determines whether an object has a given runtime type. MSVC uses _CPPRTTI. +// GCC uses __GXX_RTTI, but the macro was introduced in version 4.3, so we assume that all older +// versions support RTTI. +#if !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || defined(__GXX_RTTI)) #define HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast(obj) != NULL) #else #define HAS_DYNAMIC_TYPE(type, obj) true diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp index 96cbb01061..142373d13f 100644 --- a/src/3rdparty/angle/src/common/event_tracer.cpp +++ b/src/3rdparty/angle/src/common/event_tracer.cpp @@ -14,7 +14,7 @@ AddTraceEventFunc g_addTraceEvent; extern "C" { -void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, +void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, AddTraceEventFunc addTraceEvent) { gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag; diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h index ae397e7db9..14b7b298fd 100644 --- a/src/3rdparty/angle/src/common/event_tracer.h +++ b/src/3rdparty/angle/src/common/event_tracer.h @@ -5,6 +5,14 @@ #ifndef COMMON_EVENT_TRACER_H_ #define COMMON_EVENT_TRACER_H_ +#if !defined(TRACE_ENTRY) +#if defined(_WIN32) +#define TRACE_ENTRY __stdcall +#else +#define TRACE_ENTRY +#endif // // _WIN32 +#endif //TRACE_ENTRY + extern "C" { typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name); @@ -14,8 +22,8 @@ typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroup unsigned char flags); // extern "C" so that it has a reasonable name for GetProcAddress. -void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag, - AddTraceEventFunc add_trace_event_func); +void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag, + AddTraceEventFunc add_trace_event_func); } diff --git a/src/3rdparty/angle/src/common/system.h b/src/3rdparty/angle/src/common/system.h deleted file mode 100644 index 5eb140bccd..0000000000 --- a/src/3rdparty/angle/src/common/system.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// system.h: Includes Windows system headers and undefines macros that conflict. - -#ifndef COMMON_SYSTEM_H -#define COMMON_SYSTEM_H - -#if !defined(WIN32_LEAN_AND_MEAN) -#define WIN32_LEAN_AND_MEAN -#endif - -#include - -#if defined(min) -#undef min -#endif - -#if defined(max) -#undef max -#endif - -#endif // COMMON_SYSTEM_H diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h index 7a4942ad88..f6ae19f541 100644 --- a/src/3rdparty/angle/src/common/version.h +++ b/src/3rdparty/angle/src/common/version.h @@ -1,12 +1,12 @@ -#define MAJOR_VERSION 1 -#define MINOR_VERSION 2 -#define BUILD_VERSION 0 -#define BUILD_REVISION 2446 +#include "commit.h" -#define STRINGIFY(x) #x -#define MACRO_STRINGIFY(x) STRINGIFY(x) +#define ANGLE_MAJOR_VERSION 1 +#define ANGLE_MINOR_VERSION 3 -#define REVISION_STRING MACRO_STRINGIFY(BUILD_REVISION) -#define VERSION_STRING MACRO_STRINGIFY(MAJOR_VERSION) "." MACRO_STRINGIFY(MINOR_VERSION) "." MACRO_STRINGIFY(BUILD_VERSION) "." MACRO_STRINGIFY(BUILD_REVISION) +#define ANGLE_STRINGIFY(x) #x +#define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x) -#define VERSION_DWORD ((MAJOR_VERSION << 24) | (MINOR_VERSION << 16) | BUILD_REVISION) +#define ANGLE_VERSION_STRING \ + ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \ + ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \ + ANGLE_COMMIT_HASH diff --git a/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp b/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp deleted file mode 100644 index 637ccc5e37..0000000000 --- a/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/TranslatorHLSL.h" - -// -// This function must be provided to create the actual -// compile object used by higher level code. It returns -// a subclass of TCompiler. -// -TCompiler* ConstructCompiler( - ShShaderType type, ShShaderSpec spec, ShShaderOutput output) -{ - switch (output) - { - case SH_HLSL9_OUTPUT: - case SH_HLSL11_OUTPUT: - return new TranslatorHLSL(type, spec, output); - default: - return NULL; - } -} - -// -// Delete the compiler made by ConstructCompiler -// -void DeleteCompiler(TCompiler* compiler) -{ - delete compiler; -} diff --git a/src/3rdparty/angle/src/compiler/DetectRecursion.cpp b/src/3rdparty/angle/src/compiler/DetectRecursion.cpp deleted file mode 100644 index c09780dd92..0000000000 --- a/src/3rdparty/angle/src/compiler/DetectRecursion.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/DetectRecursion.h" - -DetectRecursion::FunctionNode::FunctionNode(const TString& fname) - : name(fname), - visit(PreVisit) -{ -} - -const TString& DetectRecursion::FunctionNode::getName() const -{ - return name; -} - -void DetectRecursion::FunctionNode::addCallee( - DetectRecursion::FunctionNode* callee) -{ - for (size_t i = 0; i < callees.size(); ++i) { - if (callees[i] == callee) - return; - } - callees.push_back(callee); -} - -bool DetectRecursion::FunctionNode::detectRecursion() -{ - ASSERT(visit == PreVisit); - visit = InVisit; - for (size_t i = 0; i < callees.size(); ++i) { - switch (callees[i]->visit) { - case InVisit: - // cycle detected, i.e., recursion detected. - return true; - case PostVisit: - break; - case PreVisit: { - bool recursion = callees[i]->detectRecursion(); - if (recursion) - return true; - break; - } - default: - UNREACHABLE(); - break; - } - } - visit = PostVisit; - return false; -} - -DetectRecursion::DetectRecursion() - : currentFunction(NULL) -{ -} - -DetectRecursion::~DetectRecursion() -{ - for (size_t i = 0; i < functions.size(); ++i) - delete functions[i]; -} - -bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node) -{ - switch (node->getOp()) - { - case EOpPrototype: - // Function declaration. - // Don't add FunctionNode here because node->getName() is the - // unmangled function name. - break; - case EOpFunction: { - // Function definition. - if (visit == PreVisit) { - currentFunction = findFunctionByName(node->getName()); - if (currentFunction == NULL) { - currentFunction = new FunctionNode(node->getName()); - functions.push_back(currentFunction); - } - } - break; - } - case EOpFunctionCall: { - // Function call. - if (visit == PreVisit) { - ASSERT(currentFunction != NULL); - FunctionNode* func = findFunctionByName(node->getName()); - if (func == NULL) { - func = new FunctionNode(node->getName()); - functions.push_back(func); - } - currentFunction->addCallee(func); - } - break; - } - default: - break; - } - return true; -} - -DetectRecursion::ErrorCode DetectRecursion::detectRecursion() -{ - FunctionNode* main = findFunctionByName("main("); - if (main == NULL) - return kErrorMissingMain; - if (main->detectRecursion()) - return kErrorRecursion; - return kErrorNone; -} - -DetectRecursion::FunctionNode* DetectRecursion::findFunctionByName( - const TString& name) -{ - for (size_t i = 0; i < functions.size(); ++i) { - if (functions[i]->getName() == name) - return functions[i]; - } - return NULL; -} - diff --git a/src/3rdparty/angle/src/compiler/DetectRecursion.h b/src/3rdparty/angle/src/compiler/DetectRecursion.h deleted file mode 100644 index bbac79dc9c..0000000000 --- a/src/3rdparty/angle/src/compiler/DetectRecursion.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_DETECT_RECURSION_H_ -#define COMPILER_DETECT_RECURSION_H_ - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/intermediate.h" -#include "compiler/VariableInfo.h" - -// Traverses intermediate tree to detect function recursion. -class DetectRecursion : public TIntermTraverser { -public: - enum ErrorCode { - kErrorMissingMain, - kErrorRecursion, - kErrorNone - }; - - DetectRecursion(); - ~DetectRecursion(); - - virtual bool visitAggregate(Visit, TIntermAggregate*); - - ErrorCode detectRecursion(); - -private: - class FunctionNode { - public: - FunctionNode(const TString& fname); - - const TString& getName() const; - - // If a function is already in the callee list, this becomes a no-op. - void addCallee(FunctionNode* callee); - - // Return true if recursive function calls are detected. - bool detectRecursion(); - - private: - // mangled function name is unique. - TString name; - - // functions that are directly called by this function. - TVector callees; - - Visit visit; - }; - - FunctionNode* findFunctionByName(const TString& name); - - TVector functions; - FunctionNode* currentFunction; -}; - -#endif // COMPILER_DETECT_RECURSION_H_ diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp b/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp deleted file mode 100644 index e0193e39d2..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/InitializeGLPosition.h" -#include "compiler/debug.h" - -bool InitializeGLPosition::visitAggregate(Visit visit, TIntermAggregate* node) -{ - bool visitChildren = !mCodeInserted; - switch (node->getOp()) - { - case EOpSequence: break; - case EOpFunction: - { - // Function definition. - ASSERT(visit == PreVisit); - if (node->getName() == "main(") - { - TIntermSequence &sequence = node->getSequence(); - ASSERT((sequence.size() == 1) || (sequence.size() == 2)); - TIntermAggregate *body = NULL; - if (sequence.size() == 1) - { - body = new TIntermAggregate(EOpSequence); - sequence.push_back(body); - } - else - { - body = sequence[1]->getAsAggregate(); - } - ASSERT(body); - insertCode(body->getSequence()); - mCodeInserted = true; - } - break; - } - default: visitChildren = false; break; - } - return visitChildren; -} - -void InitializeGLPosition::insertCode(TIntermSequence& sequence) -{ - TIntermBinary *binary = new TIntermBinary(EOpAssign); - sequence.insert(sequence.begin(), binary); - - TIntermSymbol *left = new TIntermSymbol( - 0, "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4)); - binary->setLeft(left); - - ConstantUnion *u = new ConstantUnion[4]; - for (int ii = 0; ii < 3; ++ii) - u[ii].setFConst(0.0f); - u[3].setFConst(1.0f); - TIntermConstantUnion *right = new TIntermConstantUnion( - u, TType(EbtFloat, EbpUndefined, EvqConst, 4)); - binary->setRight(right); -} diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.h b/src/3rdparty/angle/src/compiler/InitializeGLPosition.h deleted file mode 100644 index 1b11075a13..0000000000 --- a/src/3rdparty/angle/src/compiler/InitializeGLPosition.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_INITIALIZE_GL_POSITION_H_ -#define COMPILER_INITIALIZE_GL_POSITION_H_ - -#include "compiler/intermediate.h" - -class InitializeGLPosition : public TIntermTraverser -{ -public: - InitializeGLPosition() : mCodeInserted(false) { } - -protected: - virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; } - virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; } - virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; } - virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; } - virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; } - - virtual bool visitAggregate(Visit visit, TIntermAggregate* node); - -private: - // Insert AST node in the beginning of main() for "gl_Position = vec4(0.0, 0.0, 0.0, 1.0);". - void insertCode(TIntermSequence& sequence); - - bool mCodeInserted; -}; - -#endif // COMPILER_INITIALIZE_GL_POSITION_H_ diff --git a/src/3rdparty/angle/src/compiler/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/IntermTraverse.cpp deleted file mode 100644 index a13877f18f..0000000000 --- a/src/3rdparty/angle/src/compiler/IntermTraverse.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/intermediate.h" - -// -// Traverse the intermediate representation tree, and -// call a node type specific function for each node. -// Done recursively through the member function Traverse(). -// Node types can be skipped if their function to call is 0, -// but their subtree will still be traversed. -// Nodes with children can have their whole subtree skipped -// if preVisit is turned on and the type specific function -// returns false. -// -// preVisit, postVisit, and rightToLeft control what order -// nodes are visited in. -// - -// -// Traversal functions for terminals are straighforward.... -// -void TIntermSymbol::traverse(TIntermTraverser* it) -{ - it->visitSymbol(this); -} - -void TIntermConstantUnion::traverse(TIntermTraverser* it) -{ - it->visitConstantUnion(this); -} - -// -// Traverse a binary node. -// -void TIntermBinary::traverse(TIntermTraverser* it) -{ - bool visit = true; - - // - // visit the node before children if pre-visiting. - // - if(it->preVisit) - { - visit = it->visitBinary(PreVisit, this); - } - - // - // Visit the children, in the right order. - // - if(visit) - { - it->incrementDepth(); - - if(it->rightToLeft) - { - if(right) - { - right->traverse(it); - } - - if(it->inVisit) - { - visit = it->visitBinary(InVisit, this); - } - - if(visit && left) - { - left->traverse(it); - } - } - else - { - if(left) - { - left->traverse(it); - } - - if(it->inVisit) - { - visit = it->visitBinary(InVisit, this); - } - - if(visit && right) - { - right->traverse(it); - } - } - - it->decrementDepth(); - } - - // - // Visit the node after the children, if requested and the traversal - // hasn't been cancelled yet. - // - if(visit && it->postVisit) - { - it->visitBinary(PostVisit, this); - } -} - -// -// Traverse a unary node. Same comments in binary node apply here. -// -void TIntermUnary::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitUnary(PreVisit, this); - - if (visit) { - it->incrementDepth(); - operand->traverse(it); - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitUnary(PostVisit, this); -} - -// -// Traverse an aggregate node. Same comments in binary node apply here. -// -void TIntermAggregate::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if(it->preVisit) - { - visit = it->visitAggregate(PreVisit, this); - } - - if(visit) - { - it->incrementDepth(); - - if(it->rightToLeft) - { - for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) - { - (*sit)->traverse(it); - - if(visit && it->inVisit) - { - if(*sit != sequence.front()) - { - visit = it->visitAggregate(InVisit, this); - } - } - } - } - else - { - for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) - { - (*sit)->traverse(it); - - if(visit && it->inVisit) - { - if(*sit != sequence.back()) - { - visit = it->visitAggregate(InVisit, this); - } - } - } - } - - it->decrementDepth(); - } - - if(visit && it->postVisit) - { - it->visitAggregate(PostVisit, this); - } -} - -// -// Traverse a selection node. Same comments in binary node apply here. -// -void TIntermSelection::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitSelection(PreVisit, this); - - if (visit) { - it->incrementDepth(); - if (it->rightToLeft) { - if (falseBlock) - falseBlock->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - condition->traverse(it); - } else { - condition->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - if (falseBlock) - falseBlock->traverse(it); - } - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitSelection(PostVisit, this); -} - -// -// Traverse a loop node. Same comments in binary node apply here. -// -void TIntermLoop::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if(it->preVisit) - { - visit = it->visitLoop(PreVisit, this); - } - - if(visit) - { - it->incrementDepth(); - - if(it->rightToLeft) - { - if(expr) - { - expr->traverse(it); - } - - if(body) - { - body->traverse(it); - } - - if(cond) - { - cond->traverse(it); - } - } - else - { - if(cond) - { - cond->traverse(it); - } - - if(body) - { - body->traverse(it); - } - - if(expr) - { - expr->traverse(it); - } - } - - it->decrementDepth(); - } - - if(visit && it->postVisit) - { - it->visitLoop(PostVisit, this); - } -} - -// -// Traverse a branch node. Same comments in binary node apply here. -// -void TIntermBranch::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitBranch(PreVisit, this); - - if (visit && expression) { - it->incrementDepth(); - expression->traverse(it); - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitBranch(PostVisit, this); -} - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp index 3e22e1f1c5..a7ce862bcb 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp @@ -25,14 +25,14 @@ void Diagnostics::report(ID id, Diagnostics::Severity Diagnostics::severity(ID id) { - if ((id > ERROR_BEGIN) && (id < ERROR_END)) - return ERROR; + if ((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END)) + return PP_ERROR; - if ((id > WARNING_BEGIN) && (id < WARNING_END)) - return WARNING; + if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END)) + return PP_WARNING; assert(false); - return ERROR; + return PP_ERROR; } std::string Diagnostics::message(ID id) @@ -40,82 +40,82 @@ std::string Diagnostics::message(ID id) switch (id) { // Errors begin. - case INTERNAL_ERROR: + case PP_INTERNAL_ERROR: return "internal error"; - case OUT_OF_MEMORY: + case PP_OUT_OF_MEMORY: return "out of memory"; - case INVALID_CHARACTER: + case PP_INVALID_CHARACTER: return "invalid character"; - case INVALID_NUMBER: + case PP_INVALID_NUMBER: return "invalid number"; - case INTEGER_OVERFLOW: + case PP_INTEGER_OVERFLOW: return "integer overflow"; - case FLOAT_OVERFLOW: + case PP_FLOAT_OVERFLOW: return "float overflow"; - case TOKEN_TOO_LONG: + case PP_TOKEN_TOO_LONG: return "token too long"; - case INVALID_EXPRESSION: + case PP_INVALID_EXPRESSION: return "invalid expression"; - case DIVISION_BY_ZERO: + case PP_DIVISION_BY_ZERO: return "division by zero"; - case EOF_IN_COMMENT: + case PP_EOF_IN_COMMENT: return "unexpected end of file found in comment"; - case UNEXPECTED_TOKEN: + case PP_UNEXPECTED_TOKEN: return "unexpected token"; - case DIRECTIVE_INVALID_NAME: + case PP_DIRECTIVE_INVALID_NAME: return "invalid directive name"; - case MACRO_NAME_RESERVED: + case PP_MACRO_NAME_RESERVED: return "macro name is reserved"; - case MACRO_REDEFINED: + case PP_MACRO_REDEFINED: return "macro redefined"; - case MACRO_PREDEFINED_REDEFINED: + case PP_MACRO_PREDEFINED_REDEFINED: return "predefined macro redefined"; - case MACRO_PREDEFINED_UNDEFINED: + case PP_MACRO_PREDEFINED_UNDEFINED: return "predefined macro undefined"; - case MACRO_UNTERMINATED_INVOCATION: + case PP_MACRO_UNTERMINATED_INVOCATION: return "unterminated macro invocation"; - case MACRO_TOO_FEW_ARGS: + case PP_MACRO_TOO_FEW_ARGS: return "Not enough arguments for macro"; - case MACRO_TOO_MANY_ARGS: + case PP_MACRO_TOO_MANY_ARGS: return "Too many arguments for macro"; - case CONDITIONAL_ENDIF_WITHOUT_IF: + case PP_CONDITIONAL_ENDIF_WITHOUT_IF: return "unexpected #endif found without a matching #if"; - case CONDITIONAL_ELSE_WITHOUT_IF: + case PP_CONDITIONAL_ELSE_WITHOUT_IF: return "unexpected #else found without a matching #if"; - case CONDITIONAL_ELSE_AFTER_ELSE: + case PP_CONDITIONAL_ELSE_AFTER_ELSE: return "unexpected #else found after another #else"; - case CONDITIONAL_ELIF_WITHOUT_IF: + case PP_CONDITIONAL_ELIF_WITHOUT_IF: return "unexpected #elif found without a matching #if"; - case CONDITIONAL_ELIF_AFTER_ELSE: + case PP_CONDITIONAL_ELIF_AFTER_ELSE: return "unexpected #elif found after #else"; - case CONDITIONAL_UNTERMINATED: + case PP_CONDITIONAL_UNTERMINATED: return "unexpected end of file found in conditional block"; - case INVALID_EXTENSION_NAME: + case PP_INVALID_EXTENSION_NAME: return "invalid extension name"; - case INVALID_EXTENSION_BEHAVIOR: + case PP_INVALID_EXTENSION_BEHAVIOR: return "invalid extension behavior"; - case INVALID_EXTENSION_DIRECTIVE: + case PP_INVALID_EXTENSION_DIRECTIVE: return "invalid extension directive"; - case INVALID_VERSION_NUMBER: + case PP_INVALID_VERSION_NUMBER: return "invalid version number"; - case INVALID_VERSION_DIRECTIVE: + case PP_INVALID_VERSION_DIRECTIVE: return "invalid version directive"; - case VERSION_NOT_FIRST_STATEMENT: + case PP_VERSION_NOT_FIRST_STATEMENT: return "#version directive must occur before anything else, " "except for comments and white space"; - case INVALID_LINE_NUMBER: + case PP_INVALID_LINE_NUMBER: return "invalid line number"; - case INVALID_FILE_NUMBER: + case PP_INVALID_FILE_NUMBER: return "invalid file number"; - case INVALID_LINE_DIRECTIVE: + case PP_INVALID_LINE_DIRECTIVE: return "invalid line directive"; // Errors end. // Warnings begin. - case EOF_IN_DIRECTIVE: + case PP_EOF_IN_DIRECTIVE: return "unexpected end of file found in directive"; - case CONDITIONAL_UNEXPECTED_TOKEN: + case PP_CONDITIONAL_UNEXPECTED_TOKEN: return "unexpected token after conditional expression"; - case UNRECOGNIZED_PRAGMA: + case PP_UNRECOGNIZED_PRAGMA: return "unrecognized pragma"; // Warnings end. default: diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h index 07bc411846..2c8c539137 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h @@ -21,53 +21,53 @@ class Diagnostics public: enum Severity { - ERROR, - WARNING + PP_ERROR, + PP_WARNING }; enum ID { - ERROR_BEGIN, - INTERNAL_ERROR, - OUT_OF_MEMORY, - INVALID_CHARACTER, - INVALID_NUMBER, - INTEGER_OVERFLOW, - FLOAT_OVERFLOW, - TOKEN_TOO_LONG, - INVALID_EXPRESSION, - DIVISION_BY_ZERO, - EOF_IN_COMMENT, - UNEXPECTED_TOKEN, - DIRECTIVE_INVALID_NAME, - MACRO_NAME_RESERVED, - MACRO_REDEFINED, - MACRO_PREDEFINED_REDEFINED, - MACRO_PREDEFINED_UNDEFINED, - MACRO_UNTERMINATED_INVOCATION, - MACRO_TOO_FEW_ARGS, - MACRO_TOO_MANY_ARGS, - CONDITIONAL_ENDIF_WITHOUT_IF, - CONDITIONAL_ELSE_WITHOUT_IF, - CONDITIONAL_ELSE_AFTER_ELSE, - CONDITIONAL_ELIF_WITHOUT_IF, - CONDITIONAL_ELIF_AFTER_ELSE, - CONDITIONAL_UNTERMINATED, - INVALID_EXTENSION_NAME, - INVALID_EXTENSION_BEHAVIOR, - INVALID_EXTENSION_DIRECTIVE, - INVALID_VERSION_NUMBER, - INVALID_VERSION_DIRECTIVE, - VERSION_NOT_FIRST_STATEMENT, - INVALID_LINE_NUMBER, - INVALID_FILE_NUMBER, - INVALID_LINE_DIRECTIVE, - ERROR_END, + PP_ERROR_BEGIN, + PP_INTERNAL_ERROR, + PP_OUT_OF_MEMORY, + PP_INVALID_CHARACTER, + PP_INVALID_NUMBER, + PP_INTEGER_OVERFLOW, + PP_FLOAT_OVERFLOW, + PP_TOKEN_TOO_LONG, + PP_INVALID_EXPRESSION, + PP_DIVISION_BY_ZERO, + PP_EOF_IN_COMMENT, + PP_UNEXPECTED_TOKEN, + PP_DIRECTIVE_INVALID_NAME, + PP_MACRO_NAME_RESERVED, + PP_MACRO_REDEFINED, + PP_MACRO_PREDEFINED_REDEFINED, + PP_MACRO_PREDEFINED_UNDEFINED, + PP_MACRO_UNTERMINATED_INVOCATION, + PP_MACRO_TOO_FEW_ARGS, + PP_MACRO_TOO_MANY_ARGS, + PP_CONDITIONAL_ENDIF_WITHOUT_IF, + PP_CONDITIONAL_ELSE_WITHOUT_IF, + PP_CONDITIONAL_ELSE_AFTER_ELSE, + PP_CONDITIONAL_ELIF_WITHOUT_IF, + PP_CONDITIONAL_ELIF_AFTER_ELSE, + PP_CONDITIONAL_UNTERMINATED, + PP_INVALID_EXTENSION_NAME, + PP_INVALID_EXTENSION_BEHAVIOR, + PP_INVALID_EXTENSION_DIRECTIVE, + PP_INVALID_VERSION_NUMBER, + PP_INVALID_VERSION_DIRECTIVE, + PP_VERSION_NOT_FIRST_STATEMENT, + PP_INVALID_LINE_NUMBER, + PP_INVALID_FILE_NUMBER, + PP_INVALID_LINE_DIRECTIVE, + PP_ERROR_END, - WARNING_BEGIN, - EOF_IN_DIRECTIVE, - CONDITIONAL_UNEXPECTED_TOKEN, - UNRECOGNIZED_PRAGMA, - WARNING_END + PP_WARNING_BEGIN, + PP_EOF_IN_DIRECTIVE, + PP_CONDITIONAL_UNEXPECTED_TOKEN, + PP_UNRECOGNIZED_PRAGMA, + PP_WARNING_END }; virtual ~Diagnostics(); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp index 94dfdf513d..ebec79804d 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp @@ -172,7 +172,7 @@ class DefinedParser : public Lexer if (token->type != Token::IDENTIFIER) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mLexer, token); return; @@ -185,7 +185,7 @@ class DefinedParser : public Lexer mLexer->lex(token); if (token->type != ')') { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mLexer, token); return; @@ -233,7 +233,7 @@ void DirectiveParser::lex(Token* token) if (!mConditionalStack.empty()) { const ConditionalBlock& block = mConditionalStack.back(); - mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED, block.location, block.type); } break; @@ -268,7 +268,7 @@ void DirectiveParser::parseDirective(Token* token) switch(directive) { case DIRECTIVE_NONE: - mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME, + mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME, token->location, token->text); skipUntilEOD(mTokenizer, token); break; @@ -319,7 +319,7 @@ void DirectiveParser::parseDirective(Token* token) skipUntilEOD(mTokenizer, token); if (token->type == Token::LAST) { - mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE, + mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE, token->location, token->text); } } @@ -331,19 +331,19 @@ void DirectiveParser::parseDefine(Token* token) mTokenizer->lex(token); if (token->type != Token::IDENTIFIER) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); return; } if (isMacroPredefined(token->text, *mMacroSet)) { - mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED, + mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED, token->location, token->text); return; } if (isMacroNameReserved(token->text)) { - mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED, + mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED, token->location, token->text); return; } @@ -368,7 +368,7 @@ void DirectiveParser::parseDefine(Token* token) if (token->type != ')') { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); return; @@ -396,7 +396,7 @@ void DirectiveParser::parseDefine(Token* token) MacroSet::const_iterator iter = mMacroSet->find(macro.name); if (iter != mMacroSet->end() && !macro.equals(iter->second)) { - mDiagnostics->report(Diagnostics::MACRO_REDEFINED, + mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED, token->location, macro.name); return; @@ -411,7 +411,7 @@ void DirectiveParser::parseUndef(Token* token) mTokenizer->lex(token); if (token->type != Token::IDENTIFIER) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); return; } @@ -421,7 +421,7 @@ void DirectiveParser::parseUndef(Token* token) { if (iter->second.predefined) { - mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED, + mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED, token->location, token->text); } else @@ -457,7 +457,7 @@ void DirectiveParser::parseElse(Token* token) if (mConditionalStack.empty()) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -472,7 +472,7 @@ void DirectiveParser::parseElse(Token* token) } if (block.foundElseGroup) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -486,7 +486,7 @@ void DirectiveParser::parseElse(Token* token) mTokenizer->lex(token); if (!isEOD(token)) { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); } @@ -498,7 +498,7 @@ void DirectiveParser::parseElif(Token* token) if (mConditionalStack.empty()) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -513,7 +513,7 @@ void DirectiveParser::parseElif(Token* token) } if (block.foundElseGroup) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -538,7 +538,7 @@ void DirectiveParser::parseEndif(Token* token) if (mConditionalStack.empty()) { - mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -550,7 +550,7 @@ void DirectiveParser::parseEndif(Token* token) mTokenizer->lex(token); if (!isEOD(token)) { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); } @@ -618,7 +618,7 @@ void DirectiveParser::parsePragma(Token* token) (state == RIGHT_PAREN + 1)); // With value. if (!valid) { - mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA, + mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA, token->location, name); } else if (state > PRAGMA_NAME) // Do not notify for empty pragma. @@ -650,7 +650,7 @@ void DirectiveParser::parseExtension(Token* token) case EXT_NAME: if (valid && (token->type != Token::IDENTIFIER)) { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME, + mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME, token->location, token->text); valid = false; } @@ -659,7 +659,7 @@ void DirectiveParser::parseExtension(Token* token) case COLON: if (valid && (token->type != ':')) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); valid = false; } @@ -667,7 +667,7 @@ void DirectiveParser::parseExtension(Token* token) case EXT_BEHAVIOR: if (valid && (token->type != Token::IDENTIFIER)) { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR, + mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR, token->location, token->text); valid = false; } @@ -676,7 +676,7 @@ void DirectiveParser::parseExtension(Token* token) default: if (valid) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); valid = false; } @@ -686,7 +686,7 @@ void DirectiveParser::parseExtension(Token* token) } if (valid && (state != EXT_BEHAVIOR + 1)) { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE, + mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE, token->location, token->text); valid = false; } @@ -700,7 +700,7 @@ void DirectiveParser::parseVersion(Token* token) if (mPastFirstStatement) { - mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT, + mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT, token->location, token->text); skipUntilEOD(mTokenizer, token); return; @@ -723,13 +723,13 @@ void DirectiveParser::parseVersion(Token* token) case VERSION_NUMBER: if (valid && (token->type != Token::CONST_INT)) { - mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER, + mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER, token->location, token->text); valid = false; } if (valid && !token->iValue(&version)) { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); valid = false; } @@ -737,7 +737,7 @@ void DirectiveParser::parseVersion(Token* token) default: if (valid) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); valid = false; } @@ -747,7 +747,7 @@ void DirectiveParser::parseVersion(Token* token) } if (valid && (state != VERSION_NUMBER + 1)) { - mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, + mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location, token->text); valid = false; } @@ -778,13 +778,13 @@ void DirectiveParser::parseLine(Token* token) case LINE_NUMBER: if (valid && (token->type != Token::CONST_INT)) { - mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER, + mDiagnostics->report(Diagnostics::PP_INVALID_LINE_NUMBER, token->location, token->text); valid = false; } if (valid && !token->iValue(&line)) { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); valid = false; } @@ -792,13 +792,13 @@ void DirectiveParser::parseLine(Token* token) case FILE_NUMBER: if (valid && (token->type != Token::CONST_INT)) { - mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER, + mDiagnostics->report(Diagnostics::PP_INVALID_FILE_NUMBER, token->location, token->text); valid = false; } if (valid && !token->iValue(&file)) { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); valid = false; } @@ -806,7 +806,7 @@ void DirectiveParser::parseLine(Token* token) default: if (valid) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); valid = false; } @@ -817,7 +817,7 @@ void DirectiveParser::parseLine(Token* token) if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1)) { - mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE, + mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE, token->location, token->text); valid = false; } @@ -893,7 +893,7 @@ int DirectiveParser::parseExpressionIf(Token* token) // Warn if there are tokens after #if expression. if (!isEOD(token)) { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); } @@ -909,7 +909,7 @@ int DirectiveParser::parseExpressionIfdef(Token* token) mTokenizer->lex(token); if (token->type != Token::IDENTIFIER) { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); return 0; @@ -922,7 +922,7 @@ int DirectiveParser::parseExpressionIfdef(Token* token) mTokenizer->lex(token); if (!isEOD(token)) { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location, token->text); skipUntilEOD(mTokenizer, token); } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y index b6d3143e60..9fa0f0bf80 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y @@ -33,6 +33,12 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser. #include "ExpressionParser.h" +#if defined(_MSC_VER) +#include +#else +#include +#endif + #include #include @@ -146,7 +152,7 @@ expression std::ostringstream stream; stream << $1 << " % " << $3; std::string text = stream.str(); - context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, + context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, context->token->location, text.c_str()); YYABORT; @@ -159,7 +165,7 @@ expression std::ostringstream stream; stream << $1 << " / " << $3; std::string text = stream.str(); - context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, + context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO, context->token->location, text.c_str()); YYABORT; @@ -201,7 +207,7 @@ int yylex(YYSTYPE* lvalp, Context* context) unsigned int val = 0; if (!token->uValue(&val)) { - context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW, + context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW, token->location, token->text); } *lvalp = static_cast(val); @@ -242,7 +248,7 @@ int yylex(YYSTYPE* lvalp, Context* context) void yyerror(Context* context, const char* reason) { - context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION, + context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION, context->token->location, reason); } @@ -270,12 +276,12 @@ bool ExpressionParser::parse(Token* token, int* result) break; case 2: - mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, ""); + mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, ""); break; default: assert(false); - mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, ""); + mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, ""); break; } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp index 1116c516ff..b789260af9 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp @@ -254,7 +254,7 @@ bool MacroExpander::collectMacroArgs(const Macro& macro, if (token.type == Token::LAST) { - mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION, + mDiagnostics->report(Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION, identifier.location, identifier.text); // Do not lose EOF token. ungetToken(token); @@ -302,8 +302,8 @@ bool MacroExpander::collectMacroArgs(const Macro& macro, if (args->size() != params.size()) { Diagnostics::ID id = args->size() < macro.parameters.size() ? - Diagnostics::MACRO_TOO_FEW_ARGS : - Diagnostics::MACRO_TOO_MANY_ARGS; + Diagnostics::PP_MACRO_TOO_FEW_ARGS : + Diagnostics::PP_MACRO_TOO_MANY_ARGS; mDiagnostics->report(id, identifier.location, identifier.text); return false; } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp index b615c85dce..580ffba459 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp @@ -101,11 +101,11 @@ void Preprocessor::lex(Token* token) assert(false); break; case Token::PP_NUMBER: - mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, + mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER, token->location, token->text); break; case Token::PP_OTHER: - mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER, + mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER, token->location, token->text); break; default: diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l index 01f0177b6c..f1380b26b7 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l @@ -256,7 +256,7 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") if (YY_START == COMMENT) { - yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT, + yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT, pp::SourceLocation(yyfileno, yylineno), ""); } @@ -304,7 +304,7 @@ void Tokenizer::lex(Token* token) token->type = yylex(&token->text, &token->location, mHandle); if (token->text.size() > mMaxTokenLength) { - mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG, + mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG, token->location, token->text); token->text.erase(mMaxTokenLength); } diff --git a/src/3rdparty/angle/src/compiler/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h similarity index 98% rename from src/3rdparty/angle/src/compiler/BaseTypes.h rename to src/3rdparty/angle/src/compiler/translator/BaseTypes.h index 1631f4f779..7bdaf14983 100644 --- a/src/3rdparty/angle/src/compiler/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h @@ -82,6 +82,7 @@ enum TQualifier { EvqTemporary, // For temporaries (within a function), read/write EvqGlobal, // For globals read/write + EvqInternal, // For internal use, not visible to the user EvqConst, // User defined constants and non-output parameters in functions EvqAttribute, // Readonly EvqVaryingIn, // readonly, fragment shaders only diff --git a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp similarity index 99% rename from src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp rename to src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp index 1c4b25f13f..92b71c6bdb 100644 --- a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.cpp +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -4,9 +4,9 @@ // found in the LICENSE file. // -#include "compiler/BuiltInFunctionEmulator.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/SymbolTable.h" +#include "compiler/translator/SymbolTable.h" namespace { diff --git a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h similarity index 97% rename from src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h rename to src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h index 0d904f41d0..cfb71a803a 100644 --- a/src/3rdparty/angle/src/compiler/BuiltInFunctionEmulator.h +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -9,8 +9,8 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/InfoSink.h" -#include "compiler/intermediate.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/intermediate.h" // // This class decides which built-in functions need to be replaced with the diff --git a/src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp similarity index 74% rename from src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp rename to src/3rdparty/angle/src/compiler/translator/CodeGen.cpp index 226bf8f0fc..8f5d129104 100644 --- a/src/3rdparty/angle/src/compiler/CodeGenGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp @@ -4,8 +4,9 @@ // found in the LICENSE file. // -#include "compiler/TranslatorGLSL.h" -#include "compiler/TranslatorESSL.h" +#include "compiler/translator/TranslatorESSL.h" +#include "compiler/translator/TranslatorGLSL.h" +#include "compiler/translator/TranslatorHLSL.h" // // This function must be provided to create the actual @@ -16,10 +17,13 @@ TCompiler* ConstructCompiler( ShShaderType type, ShShaderSpec spec, ShShaderOutput output) { switch (output) { - case SH_GLSL_OUTPUT: - return new TranslatorGLSL(type, spec); case SH_ESSL_OUTPUT: return new TranslatorESSL(type, spec); + case SH_GLSL_OUTPUT: + return new TranslatorGLSL(type, spec); + case SH_HLSL9_OUTPUT: + case SH_HLSL11_OUTPUT: + return new TranslatorHLSL(type, spec, output); default: return NULL; } diff --git a/src/3rdparty/angle/src/compiler/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h similarity index 85% rename from src/3rdparty/angle/src/compiler/Common.h rename to src/3rdparty/angle/src/compiler/translator/Common.h index 46f9440fff..1e4503e340 100644 --- a/src/3rdparty/angle/src/compiler/Common.h +++ b/src/3rdparty/angle/src/compiler/translator/Common.h @@ -11,8 +11,12 @@ #include #include #include +#include +#include -#include "compiler/PoolAlloc.h" +#include "compiler/translator/PoolAlloc.h" +#include "compiler/translator/compilerdebug.h" +#include "common/angleutils.h" struct TSourceLoc { int first_file; @@ -74,4 +78,15 @@ public: TMap(const tAllocator& a) : std::map(std::map::key_compare(), a) {} }; +// Integer to TString conversion +template +inline TString str(T i) +{ + ASSERT(std::numeric_limits::is_integer); + char buffer[((8 * sizeof(T)) / 3) + 3]; + const char *formatStr = std::numeric_limits::is_signed ? "%d" : "%u"; + snprintf(buffer, sizeof(buffer), formatStr, i); + return buffer; +} + #endif // _COMMON_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp similarity index 70% rename from src/3rdparty/angle/src/compiler/Compiler.cpp rename to src/3rdparty/angle/src/compiler/translator/Compiler.cpp index ee64057ac4..eb7465e35c 100644 --- a/src/3rdparty/angle/src/compiler/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -4,22 +4,23 @@ // found in the LICENSE file. // -#include "compiler/BuiltInFunctionEmulator.h" -#include "compiler/DetectCallDepth.h" -#include "compiler/ForLoopUnroll.h" -#include "compiler/Initialize.h" -#include "compiler/InitializeGLPosition.h" -#include "compiler/InitializeParseContext.h" -#include "compiler/MapLongVariableNames.h" -#include "compiler/ParseHelper.h" -#include "compiler/RenameFunction.h" -#include "compiler/ShHandle.h" -#include "compiler/ValidateLimitations.h" -#include "compiler/VariablePacker.h" -#include "compiler/depgraph/DependencyGraph.h" -#include "compiler/depgraph/DependencyGraphOutput.h" -#include "compiler/timing/RestrictFragmentShaderTiming.h" -#include "compiler/timing/RestrictVertexShaderTiming.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/DetectCallDepth.h" +#include "compiler/translator/ForLoopUnroll.h" +#include "compiler/translator/Initialize.h" +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/InitializeVariables.h" +#include "compiler/translator/MapLongVariableNames.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/RenameFunction.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/UnfoldShortCircuitAST.h" +#include "compiler/translator/ValidateLimitations.h" +#include "compiler/translator/VariablePacker.h" +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/depgraph/DependencyGraphOutput.h" +#include "compiler/translator/timing/RestrictFragmentShaderTiming.h" +#include "compiler/translator/timing/RestrictVertexShaderTiming.h" #include "third_party/compiler/ArrayBoundsClamper.h" bool isWebGLBasedSpec(ShShaderSpec spec) @@ -28,43 +29,51 @@ bool isWebGLBasedSpec(ShShaderSpec spec) } namespace { -class TScopedPoolAllocator { -public: - TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) { +class TScopedPoolAllocator +{ + public: + TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) + { mAllocator->push(); SetGlobalPoolAllocator(mAllocator); } - ~TScopedPoolAllocator() { + ~TScopedPoolAllocator() + { SetGlobalPoolAllocator(NULL); mAllocator->pop(); } -private: + private: TPoolAllocator* mAllocator; }; -class TScopedSymbolTableLevel { -public: - TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) { +class TScopedSymbolTableLevel +{ + public: + TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) + { ASSERT(mTable->atBuiltInLevel()); mTable->push(); } - ~TScopedSymbolTableLevel() { + ~TScopedSymbolTableLevel() + { while (!mTable->atBuiltInLevel()) mTable->pop(); } -private: + private: TSymbolTable* mTable; }; } // namespace -TShHandleBase::TShHandleBase() { +TShHandleBase::TShHandleBase() +{ allocator.push(); SetGlobalPoolAllocator(&allocator); } -TShHandleBase::~TShHandleBase() { +TShHandleBase::~TShHandleBase() +{ SetGlobalPoolAllocator(NULL); allocator.popAll(); } @@ -150,7 +159,8 @@ bool TCompiler::compile(const char* const shaderStrings[], bool success = (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) && (parseContext.treeRoot != NULL); - if (success) { + if (success) + { TIntermNode* root = parseContext.treeRoot; success = intermediate.postProcess(root); @@ -189,20 +199,31 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL) mapLongVariableNames(root); - if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) { - InitializeGLPosition initGLPosition; - root->traverse(&initGLPosition); + if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) + initializeGLPosition(root); + + if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)) + { + UnfoldShortCircuitAST unfoldShortCircuit; + root->traverse(&unfoldShortCircuit); + unfoldShortCircuit.updateTree(); } - if (success && (compileOptions & SH_VARIABLES)) { + if (success && (compileOptions & SH_VARIABLES)) + { collectVariables(root); - if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) { + if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) + { success = enforcePackingRestrictions(); - if (!success) { + if (!success) + { infoSink.info.prefix(EPrefixError); infoSink.info << "too many uniforms"; } } + if (success && shaderType == SH_VERTEX_SHADER && + (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE)) + initializeVaryingsWithoutStaticUse(root); } if (success && (compileOptions & SH_INTERMEDIATE_TREE)) @@ -251,12 +272,14 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) symbolTable.setDefaultPrecision(integer, EbpHigh); symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); break; - default: assert(false && "Language not supported"); + default: + assert(false && "Language not supported"); } // We set defaults for all the sampler types, even those that are // only available if an extension exists. for (int samplerType = EbtGuardSamplerBegin + 1; - samplerType < EbtGuardSamplerEnd; ++samplerType) { + samplerType < EbtGuardSamplerEnd; ++samplerType) + { sampler.type = static_cast(samplerType); symbolTable.setDefaultPrecision(sampler, EbpLow); } @@ -288,24 +311,25 @@ bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool lim { DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); root->traverse(&detect); - switch (detect.detectCallDepth()) { - case DetectCallDepth::kErrorNone: - return true; - case DetectCallDepth::kErrorMissingMain: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Missing main()"; - return false; - case DetectCallDepth::kErrorRecursion: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function recursion detected"; - return false; - case DetectCallDepth::kErrorMaxDepthExceeded: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function call stack too deep"; - return false; - default: - UNREACHABLE(); - return false; + switch (detect.detectCallDepth()) + { + case DetectCallDepth::kErrorNone: + return true; + case DetectCallDepth::kErrorMissingMain: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Missing main()"; + return false; + case DetectCallDepth::kErrorRecursion: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function recursion detected"; + return false; + case DetectCallDepth::kErrorMaxDepthExceeded: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function call stack too deep"; + return false; + default: + UNREACHABLE(); + return false; } } @@ -315,7 +339,8 @@ void TCompiler::rewriteCSSShader(TIntermNode* root) root->traverse(&renamer); } -bool TCompiler::validateLimitations(TIntermNode* root) { +bool TCompiler::validateLimitations(TIntermNode* root) +{ ValidateLimitations validate(shaderType, infoSink.info); root->traverse(&validate); return validate.numErrors() == 0; @@ -323,26 +348,30 @@ bool TCompiler::validateLimitations(TIntermNode* root) { bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) { - if (shaderSpec != SH_WEBGL_SPEC) { + if (shaderSpec != SH_WEBGL_SPEC) + { infoSink.info << "Timing restrictions must be enforced under the WebGL spec."; return false; } - if (shaderType == SH_FRAGMENT_SHADER) { + if (shaderType == SH_FRAGMENT_SHADER) + { TDependencyGraph graph(root); // Output any errors first. bool success = enforceFragmentShaderTimingRestrictions(graph); // Then, output the dependency graph. - if (outputGraph) { + if (outputGraph) + { TDependencyGraphOutput output(infoSink.info); output.outputAllSpanningTrees(graph); } return success; } - else { + else + { return enforceVertexShaderTimingRestrictions(root); } } @@ -362,7 +391,8 @@ bool TCompiler::limitExpressionComplexity(TIntermNode* root) samplerSymbol->traverse(&graphTraverser); } - if (traverser.getMaxDepth() > maxExpressionComplexity) { + if (traverser.getMaxDepth() > maxExpressionComplexity) + { infoSink.info << "Expression too complex."; return false; } @@ -395,6 +425,70 @@ bool TCompiler::enforcePackingRestrictions() return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms); } +void TCompiler::initializeGLPosition(TIntermNode* root) +{ + InitializeVariables::InitVariableInfoList variables; + InitializeVariables::InitVariableInfo var( + "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4)); + variables.push_back(var); + InitializeVariables initializer(variables); + root->traverse(&initializer); +} + +void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root) +{ + InitializeVariables::InitVariableInfoList variables; + for (size_t ii = 0; ii < varyings.size(); ++ii) + { + const TVariableInfo& varying = varyings[ii]; + if (varying.staticUse) + continue; + unsigned char size = 0; + bool matrix = false; + switch (varying.type) + { + case SH_FLOAT: + size = 1; + break; + case SH_FLOAT_VEC2: + size = 2; + break; + case SH_FLOAT_VEC3: + size = 3; + break; + case SH_FLOAT_VEC4: + size = 4; + break; + case SH_FLOAT_MAT2: + size = 2; + matrix = true; + break; + case SH_FLOAT_MAT3: + size = 3; + matrix = true; + break; + case SH_FLOAT_MAT4: + size = 4; + matrix = true; + break; + default: + ASSERT(false); + } + TType type(EbtFloat, EbpUndefined, EvqVaryingOut, size, matrix, varying.isArray); + TString name = varying.name.c_str(); + if (varying.isArray) + { + type.setArraySize(varying.size); + name = name.substr(0, name.find_first_of('[')); + } + + InitializeVariables::InitVariableInfo var(name, type); + variables.push_back(var); + } + InitializeVariables initializer(variables); + root->traverse(&initializer); +} + void TCompiler::mapLongVariableNames(TIntermNode* root) { ASSERT(longNameMap); diff --git a/src/3rdparty/angle/src/compiler/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h similarity index 100% rename from src/3rdparty/angle/src/compiler/ConstantUnion.h rename to src/3rdparty/angle/src/compiler/translator/ConstantUnion.h diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp similarity index 98% rename from src/3rdparty/angle/src/compiler/DetectCallDepth.cpp rename to src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp index 60df52c715..bfc1d5852f 100644 --- a/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#include "compiler/DetectCallDepth.h" -#include "compiler/InfoSink.h" +#include "compiler/translator/DetectCallDepth.h" +#include "compiler/translator/InfoSink.h" DetectCallDepth::FunctionNode::FunctionNode(const TString& fname) : name(fname), diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h similarity index 95% rename from src/3rdparty/angle/src/compiler/DetectCallDepth.h rename to src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h index 89e85f88f6..5e7f23d15f 100644 --- a/src/3rdparty/angle/src/compiler/DetectCallDepth.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h @@ -10,8 +10,8 @@ #include "GLSLANG/ShaderLang.h" #include -#include "compiler/intermediate.h" -#include "compiler/VariableInfo.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/VariableInfo.h" class TInfoSink; diff --git a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp similarity index 96% rename from src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp rename to src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp index 7c3b68a0b3..334eb0bfa8 100644 --- a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp @@ -8,9 +8,9 @@ // gradients of functions with discontinuities. // -#include "compiler/DetectDiscontinuity.h" +#include "compiler/translator/DetectDiscontinuity.h" -#include "compiler/ParseHelper.h" +#include "compiler/translator/ParseContext.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h similarity index 96% rename from src/3rdparty/angle/src/compiler/DetectDiscontinuity.h rename to src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h index e5520bd5b0..1dd8be9233 100644 --- a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -11,7 +11,7 @@ #ifndef COMPILER_DETECTDISCONTINUITY_H_ #define COMPILER_DETECTDISCONTINUITY_H_ -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp similarity index 89% rename from src/3rdparty/angle/src/compiler/Diagnostics.cpp rename to src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp index 8a38c41a65..99506c0849 100644 --- a/src/3rdparty/angle/src/compiler/Diagnostics.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#include "compiler/Diagnostics.h" +#include "compiler/translator/Diagnostics.h" -#include "compiler/debug.h" -#include "compiler/InfoSink.h" +#include "compiler/translator/compilerdebug.h" +#include "compiler/translator/InfoSink.h" #include "compiler/preprocessor/SourceLocation.h" TDiagnostics::TDiagnostics(TInfoSink& infoSink) : @@ -30,11 +30,11 @@ void TDiagnostics::writeInfo(Severity severity, TPrefixType prefix = EPrefixNone; switch (severity) { - case ERROR: + case PP_ERROR: ++mNumErrors; prefix = EPrefixError; break; - case WARNING: + case PP_WARNING: ++mNumWarnings; prefix = EPrefixWarning; break; diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h similarity index 100% rename from src/3rdparty/angle/src/compiler/Diagnostics.h rename to src/3rdparty/angle/src/compiler/translator/Diagnostics.h diff --git a/src/3rdparty/angle/src/compiler/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp similarity index 84% rename from src/3rdparty/angle/src/compiler/DirectiveHandler.cpp rename to src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp index d1f6ab3af5..662c8ae624 100644 --- a/src/3rdparty/angle/src/compiler/DirectiveHandler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp @@ -4,12 +4,12 @@ // found in the LICENSE file. // -#include "compiler/DirectiveHandler.h" +#include "compiler/translator/DirectiveHandler.h" #include -#include "compiler/debug.h" -#include "compiler/Diagnostics.h" +#include "compiler/translator/compilerdebug.h" +#include "compiler/translator/Diagnostics.h" static TBehavior getBehavior(const std::string& str) { @@ -39,7 +39,7 @@ TDirectiveHandler::~TDirectiveHandler() void TDirectiveHandler::handleError(const pp::SourceLocation& loc, const std::string& msg) { - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, msg, "", ""); + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", ""); } void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, @@ -73,12 +73,12 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, } else { - mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name); + mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); return; } if (invalidValue) - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, "invalid pragma value", value, "'on' or 'off' expected"); } @@ -92,7 +92,7 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, TBehavior behaviorVal = getBehavior(behavior); if (behaviorVal == EBhUndefined) { - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, "behavior", name, "invalid"); return; } @@ -101,13 +101,13 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, { if (behaviorVal == EBhRequire) { - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, "extension", name, "cannot have 'require' behavior"); } else if (behaviorVal == EBhEnable) { - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, "extension", name, "cannot have 'enable' behavior"); } @@ -127,15 +127,15 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, return; } - pp::Diagnostics::Severity severity = pp::Diagnostics::ERROR; + pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR; switch (behaviorVal) { case EBhRequire: - severity = pp::Diagnostics::ERROR; + severity = pp::Diagnostics::PP_ERROR; break; case EBhEnable: case EBhWarn: case EBhDisable: - severity = pp::Diagnostics::WARNING; + severity = pp::Diagnostics::PP_WARNING; break; default: UNREACHABLE(); @@ -155,7 +155,7 @@ void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc, std::stringstream stream; stream << version; std::string str = stream.str(); - mDiagnostics.writeInfo(pp::Diagnostics::ERROR, loc, + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, "version number", str, "not supported"); } } diff --git a/src/3rdparty/angle/src/compiler/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h similarity index 93% rename from src/3rdparty/angle/src/compiler/DirectiveHandler.h rename to src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h index 95ca59d6fe..eb5f055494 100644 --- a/src/3rdparty/angle/src/compiler/DirectiveHandler.h +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h @@ -7,8 +7,8 @@ #ifndef COMPILER_DIRECTIVE_HANDLER_H_ #define COMPILER_DIRECTIVE_HANDLER_H_ -#include "compiler/ExtensionBehavior.h" -#include "compiler/Pragma.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/Pragma.h" #include "compiler/preprocessor/DirectiveHandlerBase.h" class TDiagnostics; diff --git a/src/3rdparty/angle/src/compiler/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h similarity index 100% rename from src/3rdparty/angle/src/compiler/ExtensionBehavior.h rename to src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h diff --git a/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp similarity index 99% rename from src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp rename to src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp index 27a13eabab..89e6f1a62b 100644 --- a/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/ForLoopUnroll.h" +#include "compiler/translator/ForLoopUnroll.h" namespace { diff --git a/src/3rdparty/angle/src/compiler/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h similarity index 90% rename from src/3rdparty/angle/src/compiler/ForLoopUnroll.h rename to src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h index e800e25b1f..afd70d1fd2 100644 --- a/src/3rdparty/angle/src/compiler/ForLoopUnroll.h +++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h @@ -4,7 +4,10 @@ // found in the LICENSE file. // -#include "compiler/intermediate.h" +#ifndef COMPILER_FORLOOPUNROLL_H_ +#define COMPILER_FORLOOPUNROLL_H_ + +#include "compiler/translator/intermediate.h" struct TLoopIndexInfo { int id; @@ -46,3 +49,4 @@ private: TVector mLoopIndexStack; }; +#endif diff --git a/src/3rdparty/angle/src/compiler/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h similarity index 90% rename from src/3rdparty/angle/src/compiler/HashNames.h rename to src/3rdparty/angle/src/compiler/translator/HashNames.h index d2141e2d85..751265b759 100644 --- a/src/3rdparty/angle/src/compiler/HashNames.h +++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h @@ -9,7 +9,7 @@ #include -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" #include "GLSLANG/ShaderLang.h" #define HASHED_NAME_PREFIX "webgl_" diff --git a/src/3rdparty/angle/src/compiler/InfoSink.cpp b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp similarity index 96% rename from src/3rdparty/angle/src/compiler/InfoSink.cpp rename to src/3rdparty/angle/src/compiler/translator/InfoSink.cpp index d20a6c0175..cd59658ff7 100644 --- a/src/3rdparty/angle/src/compiler/InfoSink.cpp +++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/InfoSink.h" +#include "compiler/translator/InfoSink.h" void TInfoSinkBase::prefix(TPrefixType p) { switch(p) { diff --git a/src/3rdparty/angle/src/compiler/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h similarity index 98% rename from src/3rdparty/angle/src/compiler/InfoSink.h rename to src/3rdparty/angle/src/compiler/translator/InfoSink.h index 6888838142..698a8b454b 100644 --- a/src/3rdparty/angle/src/compiler/InfoSink.h +++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.h @@ -8,7 +8,8 @@ #define _INFOSINK_INCLUDED_ #include -#include "compiler/Common.h" +#include +#include "compiler/translator/Common.h" // Returns the fractional part of the given floating-point number. inline float fractionalPart(float f) { diff --git a/src/3rdparty/angle/src/compiler/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp similarity index 99% rename from src/3rdparty/angle/src/compiler/Initialize.cpp rename to src/3rdparty/angle/src/compiler/translator/Initialize.cpp index 236383d874..db728b2129 100644 --- a/src/3rdparty/angle/src/compiler/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp @@ -10,9 +10,9 @@ // built-in functions and operators. // -#include "compiler/Initialize.h" +#include "compiler/translator/Initialize.h" -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { @@ -363,7 +363,7 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI symbolTable.insertBuiltIn(float2, "dFdx", float2); symbolTable.insertBuiltIn(float3, "dFdx", float3); symbolTable.insertBuiltIn(float4, "dFdx", float4); - + symbolTable.insertBuiltIn(float1, "dFdy", float1); symbolTable.insertBuiltIn(float2, "dFdy", float2); symbolTable.insertBuiltIn(float3, "dFdy", float3); diff --git a/src/3rdparty/angle/src/compiler/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h similarity index 84% rename from src/3rdparty/angle/src/compiler/Initialize.h rename to src/3rdparty/angle/src/compiler/translator/Initialize.h index 4aa13466ac..b5642869aa 100644 --- a/src/3rdparty/angle/src/compiler/Initialize.h +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.h @@ -7,9 +7,9 @@ #ifndef _INITIALIZE_INCLUDED_ #define _INITIALIZE_INCLUDED_ -#include "compiler/Common.h" -#include "compiler/ShHandle.h" -#include "compiler/SymbolTable.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/SymbolTable.h" void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp similarity index 74% rename from src/3rdparty/angle/src/compiler/InitializeDll.cpp rename to src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp index 6c7f27fced..43f81784d0 100644 --- a/src/3rdparty/angle/src/compiler/InitializeDll.cpp +++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp @@ -4,11 +4,11 @@ // found in the LICENSE file. // -#include "compiler/InitializeDll.h" +#include "compiler/translator/InitializeDll.h" -#include "compiler/InitializeGlobals.h" -#include "compiler/InitializeParseContext.h" -#include "compiler/osinclude.h" +#include "compiler/translator/InitializeGlobals.h" +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/osinclude.h" bool InitProcess() { diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h similarity index 100% rename from src/3rdparty/angle/src/compiler/InitializeDll.h rename to src/3rdparty/angle/src/compiler/translator/InitializeDll.h diff --git a/src/3rdparty/angle/src/compiler/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h similarity index 100% rename from src/3rdparty/angle/src/compiler/InitializeGlobals.h rename to src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp similarity index 91% rename from src/3rdparty/angle/src/compiler/InitializeParseContext.cpp rename to src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp index dfab027330..b4defae569 100644 --- a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp @@ -4,9 +4,9 @@ // found in the LICENSE file. // -#include "compiler/InitializeParseContext.h" +#include "compiler/translator/InitializeParseContext.h" -#include "compiler/osinclude.h" +#include "compiler/translator/osinclude.h" OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h similarity index 100% rename from src/3rdparty/angle/src/compiler/InitializeParseContext.h rename to src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp new file mode 100644 index 0000000000..115c561c77 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp @@ -0,0 +1,116 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/InitializeVariables.h" +#include "compiler/translator/compilerdebug.h" + +namespace +{ + +TIntermConstantUnion* constructFloatConstUnionNode(const TType& type) +{ + TType myType = type; + unsigned char size = myType.getNominalSize(); + if (myType.isMatrix()) + size *= size; + ConstantUnion *u = new ConstantUnion[size]; + for (int ii = 0; ii < size; ++ii) + u[ii].setFConst(0.0f); + + myType.clearArrayness(); + myType.setQualifier(EvqConst); + TIntermConstantUnion *node = new TIntermConstantUnion(u, myType); + return node; +} + +TIntermConstantUnion* constructIndexNode(int index) +{ + ConstantUnion *u = new ConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpUndefined, EvqConst, 1); + TIntermConstantUnion *node = new TIntermConstantUnion(u, type); + return node; +} + +} // namespace anonymous + +bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node) +{ + bool visitChildren = !mCodeInserted; + switch (node->getOp()) + { + case EOpSequence: + break; + case EOpFunction: + { + // Function definition. + ASSERT(visit == PreVisit); + if (node->getName() == "main(") + { + TIntermSequence &sequence = node->getSequence(); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermAggregate *body = NULL; + if (sequence.size() == 1) + { + body = new TIntermAggregate(EOpSequence); + sequence.push_back(body); + } + else + { + body = sequence[1]->getAsAggregate(); + } + ASSERT(body); + insertInitCode(body->getSequence()); + mCodeInserted = true; + } + break; + } + default: + visitChildren = false; + break; + } + return visitChildren; +} + +void InitializeVariables::insertInitCode(TIntermSequence& sequence) +{ + for (size_t ii = 0; ii < mVariables.size(); ++ii) + { + const InitVariableInfo& varInfo = mVariables[ii]; + + if (varInfo.type.isArray()) + { + for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index) + { + TIntermBinary *assign = new TIntermBinary(EOpAssign); + sequence.insert(sequence.begin(), assign); + + TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); + TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); + indexDirect->setLeft(symbol); + TIntermConstantUnion *indexNode = constructIndexNode(index); + indexDirect->setRight(indexNode); + + assign->setLeft(indexDirect); + + TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); + assign->setRight(zeroConst); + } + } + else + { + TIntermBinary *assign = new TIntermBinary(EOpAssign); + sequence.insert(sequence.begin(), assign); + TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); + assign->setLeft(symbol); + TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); + assign->setRight(zeroConst); + } + + } +} + diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h new file mode 100644 index 0000000000..1cd6d7e1b5 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_INITIALIZE_VARIABLES_H_ +#define COMPILER_INITIALIZE_VARIABLES_H_ + +#include "compiler/translator/intermediate.h" + +class InitializeVariables : public TIntermTraverser +{ + public: + struct InitVariableInfo + { + TString name; + TType type; + + InitVariableInfo(const TString& _name, const TType& _type) + : name(_name), + type(_type) + { + } + }; + typedef TVector InitVariableInfoList; + + InitializeVariables(const InitVariableInfoList& vars) + : mCodeInserted(false), + mVariables(vars) + { + } + + protected: + virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; } + virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; } + virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; } + virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; } + virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; } + + virtual bool visitAggregate(Visit visit, TIntermAggregate* node); + + private: + void insertInitCode(TIntermSequence& sequence); + + InitVariableInfoList mVariables; + bool mCodeInserted; +}; + +#endif // COMPILER_INITIALIZE_VARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp new file mode 100644 index 0000000000..554b83409a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp @@ -0,0 +1,259 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/intermediate.h" + +// +// Traverse the intermediate representation tree, and +// call a node type specific function for each node. +// Done recursively through the member function Traverse(). +// Node types can be skipped if their function to call is 0, +// but their subtree will still be traversed. +// Nodes with children can have their whole subtree skipped +// if preVisit is turned on and the type specific function +// returns false. +// +// preVisit, postVisit, and rightToLeft control what order +// nodes are visited in. +// + +// +// Traversal functions for terminals are straighforward.... +// +void TIntermSymbol::traverse(TIntermTraverser *it) +{ + it->visitSymbol(this); +} + +void TIntermConstantUnion::traverse(TIntermTraverser *it) +{ + it->visitConstantUnion(this); +} + +// +// Traverse a binary node. +// +void TIntermBinary::traverse(TIntermTraverser *it) +{ + bool visit = true; + + // + // visit the node before children if pre-visiting. + // + if (it->preVisit) + visit = it->visitBinary(PreVisit, this); + + // + // Visit the children, in the right order. + // + if (visit) + { + it->incrementDepth(this); + + if (it->rightToLeft) + { + if (right) + right->traverse(it); + + if (it->inVisit) + visit = it->visitBinary(InVisit, this); + + if (visit && left) + left->traverse(it); + } + else + { + if (left) + left->traverse(it); + + if (it->inVisit) + visit = it->visitBinary(InVisit, this); + + if (visit && right) + right->traverse(it); + } + + it->decrementDepth(); + } + + // + // Visit the node after the children, if requested and the traversal + // hasn't been cancelled yet. + // + if (visit && it->postVisit) + it->visitBinary(PostVisit, this); +} + +// +// Traverse a unary node. Same comments in binary node apply here. +// +void TIntermUnary::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitUnary(PreVisit, this); + + if (visit) { + it->incrementDepth(this); + operand->traverse(it); + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitUnary(PostVisit, this); +} + +// +// Traverse an aggregate node. Same comments in binary node apply here. +// +void TIntermAggregate::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitAggregate(PreVisit, this); + + if (visit) + { + it->incrementDepth(this); + + if (it->rightToLeft) + { + for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) + { + (*sit)->traverse(it); + + if (visit && it->inVisit) + { + if (*sit != sequence.front()) + visit = it->visitAggregate(InVisit, this); + } + } + } + else + { + for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + { + (*sit)->traverse(it); + + if (visit && it->inVisit) + { + if (*sit != sequence.back()) + visit = it->visitAggregate(InVisit, this); + } + } + } + + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitAggregate(PostVisit, this); +} + +// +// Traverse a selection node. Same comments in binary node apply here. +// +void TIntermSelection::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitSelection(PreVisit, this); + + if (visit) { + it->incrementDepth(this); + if (it->rightToLeft) { + if (falseBlock) + falseBlock->traverse(it); + if (trueBlock) + trueBlock->traverse(it); + condition->traverse(it); + } else { + condition->traverse(it); + if (trueBlock) + trueBlock->traverse(it); + if (falseBlock) + falseBlock->traverse(it); + } + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitSelection(PostVisit, this); +} + +// +// Traverse a loop node. Same comments in binary node apply here. +// +void TIntermLoop::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitLoop(PreVisit, this); + + if (visit) + { + it->incrementDepth(this); + + if (it->rightToLeft) + { + if (expr) + expr->traverse(it); + + if (body) + body->traverse(it); + + if (cond) + cond->traverse(it); + + if (init) + init->traverse(it); + } + else + { + if (init) + init->traverse(it); + + if (cond) + cond->traverse(it); + + if (body) + body->traverse(it); + + if (expr) + expr->traverse(it); + } + + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitLoop(PostVisit, this); +} + +// +// Traverse a branch node. Same comments in binary node apply here. +// +void TIntermBranch::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitBranch(PreVisit, this); + + if (visit && expression) { + it->incrementDepth(this); + expression->traverse(it); + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitBranch(PostVisit, this); +} + diff --git a/src/3rdparty/angle/src/compiler/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp similarity index 95% rename from src/3rdparty/angle/src/compiler/Intermediate.cpp rename to src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index 3b6622185d..777cab5458 100644 --- a/src/3rdparty/angle/src/compiler/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -12,18 +12,20 @@ #include #include -#include "compiler/HashNames.h" -#include "compiler/localintermediate.h" -#include "compiler/QualifierAlive.h" -#include "compiler/RemoveTree.h" +#include "compiler/translator/HashNames.h" +#include "compiler/translator/localintermediate.h" +#include "compiler/translator/QualifierAlive.h" +#include "compiler/translator/RemoveTree.h" bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); -static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){ +static TPrecision GetHigherPrecision(TPrecision left, TPrecision right) +{ return left > right ? left : right; } -const char* getOperatorString(TOperator op) { +const char* getOperatorString(TOperator op) +{ switch (op) { case EOpInitialize: return "="; case EOpAssign: return "="; @@ -742,12 +744,67 @@ void TIntermediate::remove(TIntermNode* root) // //////////////////////////////////////////////////////////////// +#define REPLACE_IF_IS(node, type, original, replacement) \ + if (node == original) { \ + node = static_cast(replacement); \ + return true; \ + } + +bool TIntermLoop::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(init, TIntermNode, original, replacement); + REPLACE_IF_IS(cond, TIntermTyped, original, replacement); + REPLACE_IF_IS(expr, TIntermTyped, original, replacement); + REPLACE_IF_IS(body, TIntermNode, original, replacement); + return false; +} + +bool TIntermBranch::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(expression, TIntermTyped, original, replacement); + return false; +} + +bool TIntermBinary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(left, TIntermTyped, original, replacement); + REPLACE_IF_IS(right, TIntermTyped, original, replacement); + return false; +} + +bool TIntermUnary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(operand, TIntermTyped, original, replacement); + return false; +} + +bool TIntermAggregate::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement); + } + return false; +} + +bool TIntermSelection::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(condition, TIntermTyped, original, replacement); + REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement); + REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement); + return false; +} + // // Say whether or not an operation node changes the value of a variable. // -// Returns true if state is modified. -// -bool TIntermOperator::modifiesState() const +bool TIntermOperator::isAssignment() const { switch (op) { case EOpPostIncrement: @@ -796,6 +853,7 @@ bool TIntermOperator::isConstructor() const return false; } } + // // Make sure the type of a unary operator is appropriate for its // combination of operation and operand type. diff --git a/src/3rdparty/angle/src/compiler/MMap.h b/src/3rdparty/angle/src/compiler/translator/MMap.h similarity index 100% rename from src/3rdparty/angle/src/compiler/MMap.h rename to src/3rdparty/angle/src/compiler/translator/MMap.h diff --git a/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp similarity index 93% rename from src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp rename to src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp index a41d20f4e8..ef629c26b1 100644 --- a/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp +++ b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/MapLongVariableNames.h" +#include "compiler/translator/MapLongVariableNames.h" namespace { @@ -102,13 +102,6 @@ void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol) } } -bool MapLongVariableNames::visitLoop(Visit, TIntermLoop* node) -{ - if (node->getInit()) - node->getInit()->traverse(this); - return true; -} - TString MapLongVariableNames::mapGlobalLongName(const TString& name) { ASSERT(mGlobalMap); diff --git a/src/3rdparty/angle/src/compiler/MapLongVariableNames.h b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h similarity index 92% rename from src/3rdparty/angle/src/compiler/MapLongVariableNames.h rename to src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h index d6352acb4b..3b085a3687 100644 --- a/src/3rdparty/angle/src/compiler/MapLongVariableNames.h +++ b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h @@ -9,8 +9,8 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" -#include "compiler/VariableInfo.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/VariableInfo.h" // This size does not include '\0' in the end. #define MAX_SHORTENED_IDENTIFIER_SIZE 32 @@ -48,7 +48,6 @@ public: MapLongVariableNames(LongNameMap* globalMap); virtual void visitSymbol(TIntermSymbol*); - virtual bool visitLoop(Visit, TIntermLoop*); private: TString mapGlobalLongName(const TString& name); diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h new file mode 100644 index 0000000000..b58c7ec689 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h @@ -0,0 +1,80 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// NodeSearch.h: Utilities for searching translator node graphs +// + +#ifndef TRANSLATOR_NODESEARCH_H_ +#define TRANSLATOR_NODESEARCH_H_ + +#include "compiler/translator/intermediate.h" + +namespace sh +{ + +template +class NodeSearchTraverser : public TIntermTraverser +{ + public: + NodeSearchTraverser() + : mFound(false) + {} + + bool found() const { return mFound; } + + static bool search(TIntermNode *node) + { + Parent searchTraverser; + node->traverse(&searchTraverser); + return searchTraverser.found(); + } + + protected: + bool mFound; +}; + +class FindDiscard : public NodeSearchTraverser +{ + public: + virtual bool visitBranch(Visit visit, TIntermBranch *node) + { + switch (node->getFlowOp()) + { + case EOpKill: + mFound = true; + break; + + default: break; + } + + return !mFound; + } +}; + +class FindSideEffectRewriting : public NodeSearchTraverser +{ + public: + virtual bool visitBinary(Visit visit, TIntermBinary *node) + { + switch (node->getOp()) + { + case EOpLogicalOr: + case EOpLogicalAnd: + if (node->getRight()->hasSideEffects()) + { + mFound = true; + } + break; + + default: break; + } + + return !mFound; + } +}; + +} + +#endif // TRANSLATOR_NODESEARCH_H_ diff --git a/src/3rdparty/angle/src/compiler/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp similarity index 94% rename from src/3rdparty/angle/src/compiler/OutputESSL.cpp rename to src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp index c2048f1cec..8367412462 100644 --- a/src/3rdparty/angle/src/compiler/OutputESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/OutputESSL.h" +#include "compiler/translator/OutputESSL.h" TOutputESSL::TOutputESSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, diff --git a/src/3rdparty/angle/src/compiler/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h similarity index 93% rename from src/3rdparty/angle/src/compiler/OutputESSL.h rename to src/3rdparty/angle/src/compiler/translator/OutputESSL.h index 05db96e497..2f02979a05 100644 --- a/src/3rdparty/angle/src/compiler/OutputESSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h @@ -7,7 +7,7 @@ #ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_ #define CROSSCOMPILERGLSL_OUTPUTESSL_H_ -#include "compiler/OutputGLSLBase.h" +#include "compiler/translator/OutputGLSLBase.h" class TOutputESSL : public TOutputGLSLBase { diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp similarity index 95% rename from src/3rdparty/angle/src/compiler/OutputGLSL.cpp rename to src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp index 10a451c0d7..5589560682 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/OutputGLSL.h" +#include "compiler/translator/OutputGLSL.h" TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h similarity index 93% rename from src/3rdparty/angle/src/compiler/OutputGLSL.h rename to src/3rdparty/angle/src/compiler/translator/OutputGLSL.h index fa68ac8103..e1f114d347 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h @@ -7,7 +7,7 @@ #ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_ #define CROSSCOMPILERGLSL_OUTPUTGLSL_H_ -#include "compiler/OutputGLSLBase.h" +#include "compiler/translator/OutputGLSLBase.h" class TOutputGLSL : public TOutputGLSLBase { diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp similarity index 99% rename from src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp rename to src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index d677c75633..f2f0a3d6be 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#include "compiler/OutputGLSLBase.h" -#include "compiler/debug.h" +#include "compiler/translator/OutputGLSLBase.h" +#include "compiler/translator/compilerdebug.h" #include @@ -435,7 +435,7 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) node->getCondition()->traverse(this); out << ")\n"; - incrementDepth(); + incrementDepth(node); visitCodeBlock(node->getTrueBlock()); if (node->getFalseBlock()) @@ -460,7 +460,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) // Scope the sequences except when at the global scope. if (depth > 0) out << "{\n"; - incrementDepth(); + incrementDepth(node); const TIntermSequence& sequence = node->getSequence(); for (TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter) @@ -498,7 +498,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) writeVariableType(node->getType()); out << " " << hashFunctionName(node->getName()); - incrementDepth(); + incrementDepth(node); // Function definition node contains one or two children nodes // representing function parameters and function body. The latter // is not present in case of empty function bodies. @@ -638,7 +638,7 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) { TInfoSinkBase& out = objSink(); - incrementDepth(); + incrementDepth(node); // Loop header. TLoopType loopType = node->getType(); if (loopType == ELoopFor) // for loop diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h similarity index 95% rename from src/3rdparty/angle/src/compiler/OutputGLSLBase.h rename to src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h index df4ad68c2c..76bec4de61 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h @@ -9,9 +9,9 @@ #include -#include "compiler/ForLoopUnroll.h" -#include "compiler/intermediate.h" -#include "compiler/ParseHelper.h" +#include "compiler/translator/ForLoopUnroll.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/ParseContext.h" class TOutputGLSLBase : public TIntermTraverser { diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp similarity index 97% rename from src/3rdparty/angle/src/compiler/OutputHLSL.cpp rename to src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index 79a373ebab..af996df719 100644 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -4,14 +4,16 @@ // found in the LICENSE file. // -#include "compiler/OutputHLSL.h" +#include "compiler/translator/OutputHLSL.h" #include "common/angleutils.h" -#include "compiler/debug.h" -#include "compiler/DetectDiscontinuity.h" -#include "compiler/InfoSink.h" -#include "compiler/SearchSymbol.h" -#include "compiler/UnfoldShortCircuit.h" +#include "compiler/translator/compilerdebug.h" +#include "compiler/translator/DetectDiscontinuity.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/SearchSymbol.h" +#include "compiler/translator/UnfoldShortCircuit.h" +#include "compiler/translator/NodeSearch.h" +#include "compiler/translator/RewriteElseBlocks.h" #include #include @@ -19,13 +21,6 @@ namespace sh { -// Integer to TString conversion -TString str(int i) -{ - char buffer[20]; - snprintf(buffer, sizeof(buffer), "%d", i); - return buffer; -} OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) @@ -72,6 +67,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mUsesAtan2_2 = false; mUsesAtan2_3 = false; mUsesAtan2_4 = false; + mUsesDiscardRewriting = false; mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; @@ -113,6 +109,13 @@ void OutputHLSL::output() { mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); + // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which + // use a vertex attribute as a condition, and some related computation in the else block. + if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == SH_VERTEX_SHADER) + { + RewriteElseBlocks(mContext.treeRoot); + } + mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header header(); @@ -196,6 +199,11 @@ void OutputHLSL::header() attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; } + if (mUsesDiscardRewriting) + { + out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n"; + } + if (shaderType == SH_FRAGMENT_SHADER) { TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); @@ -761,12 +769,12 @@ void OutputHLSL::header() } else if (mOutputType == SH_HLSL11_OUTPUT) { - out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float lod)\n" + out << "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float3 uvw, float lod)\n" "{\n" " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n" "}\n" "\n" - "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" + "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float4 uvw, float lod)\n" "{\n" " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n" "}\n" @@ -1092,6 +1100,10 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mReferencedVaryings[name] = node; out << decorate(name); } + else if (qualifier == EvqInternal) + { + out << name; + } else { out << decorate(name); @@ -1299,15 +1311,31 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break; case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break; case EOpLogicalOr: - out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); - return false; + if (node->getRight()->hasSideEffects()) + { + out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); + return false; + } + else + { + outputTriplet(visit, "(", " || ", ")"); + return true; + } case EOpLogicalXor: mUsesXor = true; outputTriplet(visit, "xor(", ", ", ")"); break; case EOpLogicalAnd: - out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); - return false; + if (node->getRight()->hasSideEffects()) + { + out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex(); + return false; + } + else + { + outputTriplet(visit, "(", " && ", ")"); + return true; + } default: UNREACHABLE(); } @@ -1491,7 +1519,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { symbol->traverse(this); out << arrayString(symbol->getType()); - out << " = " + initializer(variable->getType()); + out << " = " + initializer(symbol->getType()); } else { @@ -1944,7 +1972,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) { mUnfoldShortCircuit->traverse(node->getCondition()); - out << "if("; + out << "if ("; node->getCondition()->traverse(this); @@ -1953,9 +1981,14 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) outputLineDirective(node->getLine().first_line); out << "{\n"; + bool discard = false; + if (node->getTrueBlock()) { traverseStatements(node->getTrueBlock()); + + // Detect true discard + discard = (discard || FindDiscard::search(node->getTrueBlock())); } outputLineDirective(node->getLine().first_line); @@ -1973,6 +2006,15 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) outputLineDirective(node->getFalseBlock()->getLine().first_line); out << ";\n}\n"; + + // Detect false discard + discard = (discard || FindDiscard::search(node->getFalseBlock())); + } + + // ANGLE issue 486: Detect problematic conditional discard + if (discard && FindSideEffectRewriting::search(node)) + { + mUsesDiscardRewriting = true; } } @@ -2070,7 +2112,9 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) switch (node->getFlowOp()) { - case EOpKill: outputTriplet(visit, "discard;\n", "", ""); break; + case EOpKill: + outputTriplet(visit, "discard;\n", "", ""); + break; case EOpBreak: if (visit == PreVisit) { @@ -2293,7 +2337,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (!firstLoopFragment) { - out << "if(!Break"; + out << "if (!Break"; index->traverse(this); out << ") {\n"; } diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h similarity index 96% rename from src/3rdparty/angle/src/compiler/OutputHLSL.h rename to src/3rdparty/angle/src/compiler/translator/OutputHLSL.h index cde4120718..3afd8e9ada 100644 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -14,9 +14,9 @@ #define GL_APICALL #include -#include "compiler/intermediate.h" -#include "compiler/ParseHelper.h" -#include "compiler/Uniform.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/Uniform.h" namespace sh { @@ -125,6 +125,7 @@ class OutputHLSL : public TIntermTraverser bool mUsesAtan2_2; bool mUsesAtan2_3; bool mUsesAtan2_4; + bool mUsesDiscardRewriting; int mNumRenderTargets; diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp similarity index 99% rename from src/3rdparty/angle/src/compiler/ParseHelper.cpp rename to src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index 1f8538e6a4..1a1e0d140c 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -4,12 +4,12 @@ // found in the LICENSE file. // -#include "compiler/ParseHelper.h" +#include "compiler/translator/ParseContext.h" #include #include -#include "compiler/glslang.h" +#include "compiler/translator/glslang.h" #include "compiler/preprocessor/SourceLocation.h" /////////////////////////////////////////////////////////////////////// @@ -182,7 +182,7 @@ void TParseContext::error(const TSourceLoc& loc, pp::SourceLocation srcLoc; srcLoc.file = loc.first_file; srcLoc.line = loc.first_line; - diagnostics.writeInfo(pp::Diagnostics::ERROR, + diagnostics.writeInfo(pp::Diagnostics::PP_ERROR, srcLoc, reason, token, extraInfo); } @@ -193,7 +193,7 @@ void TParseContext::warning(const TSourceLoc& loc, pp::SourceLocation srcLoc; srcLoc.file = loc.first_file; srcLoc.line = loc.first_line; - diagnostics.writeInfo(pp::Diagnostics::WARNING, + diagnostics.writeInfo(pp::Diagnostics::PP_WARNING, srcLoc, reason, token, extraInfo); } @@ -535,7 +535,7 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* n return true; } - if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) { + if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) { error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); return true; } diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h similarity index 96% rename from src/3rdparty/angle/src/compiler/ParseHelper.h rename to src/3rdparty/angle/src/compiler/translator/ParseContext.h index c2b3c3f7ec..b324e575d3 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -6,12 +6,12 @@ #ifndef _PARSER_HELPER_INCLUDED_ #define _PARSER_HELPER_INCLUDED_ -#include "compiler/Diagnostics.h" -#include "compiler/DirectiveHandler.h" -#include "compiler/localintermediate.h" +#include "compiler/translator/Diagnostics.h" +#include "compiler/translator/DirectiveHandler.h" +#include "compiler/translator/localintermediate.h" #include "compiler/preprocessor/Preprocessor.h" -#include "compiler/ShHandle.h" -#include "compiler/SymbolTable.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/SymbolTable.h" struct TMatrixFields { bool wholeRow; diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp similarity index 98% rename from src/3rdparty/angle/src/compiler/PoolAlloc.cpp rename to src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp index eb993567b3..abe70262f2 100644 --- a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp +++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/PoolAlloc.h" +#include "compiler/translator/PoolAlloc.h" #ifndef _MSC_VER #include @@ -12,8 +12,8 @@ #include #include "common/angleutils.h" -#include "compiler/InitializeGlobals.h" -#include "compiler/osinclude.h" +#include "compiler/translator/InitializeGlobals.h" +#include "compiler/translator/osinclude.h" OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h similarity index 100% rename from src/3rdparty/angle/src/compiler/PoolAlloc.h rename to src/3rdparty/angle/src/compiler/translator/PoolAlloc.h diff --git a/src/3rdparty/angle/src/compiler/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h similarity index 100% rename from src/3rdparty/angle/src/compiler/Pragma.h rename to src/3rdparty/angle/src/compiler/translator/Pragma.h diff --git a/src/3rdparty/angle/src/compiler/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp similarity index 96% rename from src/3rdparty/angle/src/compiler/QualifierAlive.cpp rename to src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp index 92a6874eb7..1ba087e176 100644 --- a/src/3rdparty/angle/src/compiler/QualifierAlive.cpp +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" class TAliveTraverser : public TIntermTraverser { public: diff --git a/src/3rdparty/angle/src/compiler/QualifierAlive.h b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h similarity index 100% rename from src/3rdparty/angle/src/compiler/QualifierAlive.h rename to src/3rdparty/angle/src/compiler/translator/QualifierAlive.h diff --git a/src/3rdparty/angle/src/compiler/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp similarity index 93% rename from src/3rdparty/angle/src/compiler/RemoveTree.cpp rename to src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp index a4b8c1e63e..92e5dbbfe1 100644 --- a/src/3rdparty/angle/src/compiler/RemoveTree.cpp +++ b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#include "compiler/intermediate.h" -#include "compiler/RemoveTree.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/RemoveTree.h" // // Code to recursively delete the intermediate tree. diff --git a/src/3rdparty/angle/src/compiler/RemoveTree.h b/src/3rdparty/angle/src/compiler/translator/RemoveTree.h similarity index 100% rename from src/3rdparty/angle/src/compiler/RemoveTree.h rename to src/3rdparty/angle/src/compiler/translator/RemoveTree.h diff --git a/src/3rdparty/angle/src/compiler/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h similarity index 95% rename from src/3rdparty/angle/src/compiler/RenameFunction.h rename to src/3rdparty/angle/src/compiler/translator/RenameFunction.h index 3908bfddb8..1f7fb16c45 100644 --- a/src/3rdparty/angle/src/compiler/RenameFunction.h +++ b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h @@ -7,7 +7,7 @@ #ifndef COMPILER_RENAME_FUNCTION #define COMPILER_RENAME_FUNCTION -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" // // Renames a function, including its declaration and any calls to it. diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp new file mode 100644 index 0000000000..48e87cd57a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp @@ -0,0 +1,98 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteElseBlocks.cpp: Implementation for tree transform to change +// all if-else blocks to if-if blocks. +// + +#include "compiler/translator/RewriteElseBlocks.h" +#include "compiler/translator/NodeSearch.h" +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type) +{ + TType variableType(type, EbpHigh, EvqInternal); + return new TIntermSymbol(-1, name, variableType); +} + +TIntermBinary *MakeNewBinary(TOperator op, TIntermTyped *left, TIntermTyped *right, const TType &resultType) +{ + TIntermBinary *binary = new TIntermBinary(op); + binary->setLeft(left); + binary->setRight(right); + binary->setType(resultType); + return binary; +} + +TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand) +{ + TIntermUnary *unary = new TIntermUnary(op, operand->getType()); + unary->setOperand(operand); + return unary; +} + +bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node) +{ + switch (node->getOp()) + { + case EOpSequence: + { + for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++) + { + TIntermNode *statement = node->getSequence()[statementIndex]; + TIntermSelection *selection = statement->getAsSelectionNode(); + if (selection && selection->getFalseBlock() != NULL) + { + node->getSequence()[statementIndex] = rewriteSelection(selection); + delete selection; + } + } + } + break; + + default: break; + } + + return true; +} + +TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection) +{ + ASSERT(selection->getFalseBlock() != NULL); + + TString temporaryName = "cond_" + str(mTemporaryIndex++); + TIntermTyped *typedCondition = selection->getCondition()->getAsTyped(); + TType resultType(EbtBool, EbpUndefined); + TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool); + TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool); + TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool); + TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA, + typedCondition, resultType); + TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB); + TIntermSelection *falseBlock = new TIntermSelection(negatedCondition, + selection->getFalseBlock(), NULL); + TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC, + selection->getTrueBlock(), falseBlock); + + TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration); + declaration->getSequence().push_back(storeCondition); + + TIntermAggregate *block = new TIntermAggregate(EOpSequence); + block->getSequence().push_back(declaration); + block->getSequence().push_back(newIfElse); + + return block; +} + +void RewriteElseBlocks(TIntermNode *node) +{ + ElseBlockRewriter rewriter; + node->traverse(&rewriter); +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h new file mode 100644 index 0000000000..10221335ce --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// RewriteElseBlocks.h: Prototype for tree transform to change +// all if-else blocks to if-if blocks. +// + +#ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_ +#define COMPILER_REWRITE_ELSE_BLOCKS_H_ + +#include "compiler/translator/intermediate.h" + +namespace sh +{ + +class ElseBlockRewriter : public TIntermTraverser +{ + public: + ElseBlockRewriter() + : TIntermTraverser(false, false, true, false) + , mTemporaryIndex(0) + {} + + protected: + bool visitAggregate(Visit visit, TIntermAggregate *aggregate); + + private: + int mTemporaryIndex; + + TIntermNode *rewriteSelection(TIntermSelection *selection); +}; + +void RewriteElseBlocks(TIntermNode *node); + +} + +#endif // COMPILER_REWRITE_ELSE_BLOCKS_H_ diff --git a/src/3rdparty/angle/src/compiler/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp similarity index 83% rename from src/3rdparty/angle/src/compiler/SearchSymbol.cpp rename to src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp index 9368f1a4fa..f78c84e370 100644 --- a/src/3rdparty/angle/src/compiler/SearchSymbol.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp @@ -6,10 +6,10 @@ // SearchSymbol is an AST traverser to detect the use of a given symbol name // -#include "compiler/SearchSymbol.h" +#include "compiler/translator/SearchSymbol.h" -#include "compiler/InfoSink.h" -#include "compiler/OutputHLSL.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/OutputHLSL.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h similarity index 87% rename from src/3rdparty/angle/src/compiler/SearchSymbol.h rename to src/3rdparty/angle/src/compiler/translator/SearchSymbol.h index 6bc0b90feb..8ddd3cb1ac 100644 --- a/src/3rdparty/angle/src/compiler/SearchSymbol.h +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h @@ -9,8 +9,8 @@ #ifndef COMPILER_SEARCHSYMBOL_H_ #define COMPILER_SEARCHSYMBOL_H_ -#include "compiler/intermediate.h" -#include "compiler/ParseHelper.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/ParseContext.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/ShHandle.h b/src/3rdparty/angle/src/compiler/translator/ShHandle.h similarity index 86% rename from src/3rdparty/angle/src/compiler/ShHandle.h rename to src/3rdparty/angle/src/compiler/translator/ShHandle.h index 873580a99c..54ae27852d 100644 --- a/src/3rdparty/angle/src/compiler/ShHandle.h +++ b/src/3rdparty/angle/src/compiler/translator/ShHandle.h @@ -16,12 +16,12 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/BuiltInFunctionEmulator.h" -#include "compiler/ExtensionBehavior.h" -#include "compiler/HashNames.h" -#include "compiler/InfoSink.h" -#include "compiler/SymbolTable.h" -#include "compiler/VariableInfo.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/HashNames.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/VariableInfo.h" #include "third_party/compiler/ArrayBoundsClamper.h" class LongNameMap; @@ -100,6 +100,16 @@ protected: // Returns true if, after applying the packing rules in the GLSL 1.017 spec // Appendix A, section 7, the shader does not use too many uniforms. bool enforcePackingRestrictions(); + // Insert statements to initialize varyings without static use in the beginning + // of main(). It is to work around a Mac driver where such varyings in a vertex + // shader may be optimized out incorrectly at compile time, causing a link failure. + // This function should only be applied to vertex shaders. + void initializeVaryingsWithoutStaticUse(TIntermNode* root); + // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). + // It is to work around a Linux driver bug where missing this causes compile failure + // while spec says it is allowed. + // This function should only be applied to vertex shaders. + void initializeGLPosition(TIntermNode* root); // Returns true if the shader passes the restrictions that aim to prevent timing attacks. bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph); // Returns true if the shader does not use samplers. diff --git a/src/3rdparty/angle/src/compiler/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp similarity index 97% rename from src/3rdparty/angle/src/compiler/ShaderLang.cpp rename to src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 42cd5cc5c1..608237860c 100644 --- a/src/3rdparty/angle/src/compiler/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -11,11 +11,11 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/InitializeDll.h" +#include "compiler/translator/InitializeDll.h" #include "compiler/preprocessor/length_limits.h" -#include "compiler/ShHandle.h" -#include "compiler/TranslatorHLSL.h" -#include "compiler/VariablePacker.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/TranslatorHLSL.h" +#include "compiler/translator/VariablePacker.h" // // This is the platform independent interface between an OGL driver @@ -91,6 +91,9 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->HashFunction = NULL; resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC; + + resources->MaxExpressionComplexity = 256; + resources->MaxCallStackDepth = 256; } // diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp similarity index 99% rename from src/3rdparty/angle/src/compiler/SymbolTable.cpp rename to src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp index a7ce21680f..d04fe5d355 100644 --- a/src/3rdparty/angle/src/compiler/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp @@ -13,7 +13,7 @@ #pragma warning(disable: 4718) #endif -#include "compiler/SymbolTable.h" +#include "compiler/translator/SymbolTable.h" #include #include diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h similarity index 99% rename from src/3rdparty/angle/src/compiler/SymbolTable.h rename to src/3rdparty/angle/src/compiler/translator/SymbolTable.h index bebad4b92e..6c7211f2a9 100644 --- a/src/3rdparty/angle/src/compiler/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -33,8 +33,8 @@ #include #include "common/angleutils.h" -#include "compiler/InfoSink.h" -#include "compiler/intermediate.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/intermediate.h" // // Symbol base class. (Can build functions or variables out of these...) diff --git a/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp similarity index 93% rename from src/3rdparty/angle/src/compiler/TranslatorESSL.cpp rename to src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp index 2900f8a8ed..9262f7af8c 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp @@ -4,9 +4,9 @@ // found in the LICENSE file. // -#include "compiler/TranslatorESSL.h" +#include "compiler/translator/TranslatorESSL.h" -#include "compiler/OutputESSL.h" +#include "compiler/translator/OutputESSL.h" TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec) : TCompiler(type, spec) { diff --git a/src/3rdparty/angle/src/compiler/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h similarity index 92% rename from src/3rdparty/angle/src/compiler/TranslatorESSL.h rename to src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h index a1196bd001..e18f3c25ec 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorESSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATORESSL_H_ #define COMPILER_TRANSLATORESSL_H_ -#include "compiler/ShHandle.h" +#include "compiler/translator/ShHandle.h" class TranslatorESSL : public TCompiler { public: diff --git a/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp similarity index 90% rename from src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp rename to src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp index 7ca4341dcd..6688d7f362 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#include "compiler/TranslatorGLSL.h" +#include "compiler/translator/TranslatorGLSL.h" -#include "compiler/OutputGLSL.h" -#include "compiler/VersionGLSL.h" +#include "compiler/translator/OutputGLSL.h" +#include "compiler/translator/VersionGLSL.h" static void writeVersion(ShShaderType type, TIntermNode* root, TInfoSinkBase& sink) { diff --git a/src/3rdparty/angle/src/compiler/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h similarity index 91% rename from src/3rdparty/angle/src/compiler/TranslatorGLSL.h rename to src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h index c2ce06d192..40bb3145e8 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATORGLSL_H_ #define COMPILER_TRANSLATORGLSL_H_ -#include "compiler/ShHandle.h" +#include "compiler/translator/ShHandle.h" class TranslatorGLSL : public TCompiler { public: diff --git a/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp similarity index 80% rename from src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp rename to src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp index 37408a07c4..3c1db011b6 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#include "compiler/TranslatorHLSL.h" +#include "compiler/translator/TranslatorHLSL.h" -#include "compiler/InitializeParseContext.h" -#include "compiler/OutputHLSL.h" +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/OutputHLSL.h" TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output) : TCompiler(type, spec), mOutputType(output) diff --git a/src/3rdparty/angle/src/compiler/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h similarity index 89% rename from src/3rdparty/angle/src/compiler/TranslatorHLSL.h rename to src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h index 9550e15e8e..6204b30cc2 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h @@ -7,8 +7,8 @@ #ifndef COMPILER_TRANSLATORHLSL_H_ #define COMPILER_TRANSLATORHLSL_H_ -#include "compiler/ShHandle.h" -#include "compiler/Uniform.h" +#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Uniform.h" class TranslatorHLSL : public TCompiler { public: diff --git a/src/3rdparty/angle/src/compiler/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h similarity index 93% rename from src/3rdparty/angle/src/compiler/Types.h rename to src/3rdparty/angle/src/compiler/translator/Types.h index 505fa8e3bf..119f4f29e5 100644 --- a/src/3rdparty/angle/src/compiler/Types.h +++ b/src/3rdparty/angle/src/compiler/translator/Types.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,9 +9,9 @@ #include "common/angleutils.h" -#include "compiler/BaseTypes.h" -#include "compiler/Common.h" -#include "compiler/debug.h" +#include "compiler/translator/BaseTypes.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/compilerdebug.h" struct TPublicType; class TType; @@ -95,7 +95,7 @@ class TType public: POOL_ALLOCATOR_NEW_DELETE(); TType() {} - TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : + TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, unsigned char s = 1, bool m = false, bool a = false) : type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0) { } @@ -116,7 +116,7 @@ public: // One-dimensional size of single instance type int getNominalSize() const { return size; } - void setNominalSize(int s) { size = s; } + void setNominalSize(unsigned char s) { size = s; } // Full size of single instance of type size_t getObjectSize() const; @@ -234,12 +234,12 @@ public: private: TString buildMangledName() const; - TBasicType type : 6; + TBasicType type; TPrecision precision; - TQualifier qualifier : 7; - int size : 8; // size of vector or matrix, not size of array - unsigned int matrix : 1; - unsigned int array : 1; + TQualifier qualifier; + unsigned char size; + bool matrix; + bool array; int arraySize; TStructure* structure; // 0 unless this is a struct @@ -261,7 +261,7 @@ struct TPublicType TBasicType type; TQualifier qualifier; TPrecision precision; - int size; // size of vector or matrix, not size of array + unsigned char size; // size of vector or matrix, not size of array bool matrix; bool array; int arraySize; @@ -281,7 +281,7 @@ struct TPublicType line = ln; } - void setAggregate(int s, bool m = false) + void setAggregate(unsigned char s, bool m = false) { size = s; matrix = m; diff --git a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp similarity index 88% rename from src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp rename to src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp index 47f0afca6a..b7826119ae 100644 --- a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp @@ -8,10 +8,10 @@ // the original expression. // -#include "compiler/UnfoldShortCircuit.h" +#include "compiler/translator/UnfoldShortCircuit.h" -#include "compiler/InfoSink.h" -#include "compiler/OutputHLSL.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/OutputHLSL.h" namespace sh { @@ -31,6 +31,14 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) { TInfoSinkBase &out = mOutputHLSL->getBodyStream(); + // If our right node doesn't have side effects, we know we don't need to unfold this + // expression: there will be no short-circuiting side effects to avoid + // (note: unfolding doesn't depend on the left node -- it will always be evaluated) + if (!node->getRight()->hasSideEffects()) + { + return true; + } + switch (node->getOp()) { case EOpLogicalOr: @@ -49,7 +57,7 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) mTemporaryIndex = i + 1; node->getLeft()->traverse(mOutputHLSL); out << ";\n"; - out << "if(!s" << i << ")\n" + out << "if (!s" << i << ")\n" "{\n"; mTemporaryIndex = i + 1; node->getRight()->traverse(this); @@ -80,7 +88,7 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) mTemporaryIndex = i + 1; node->getLeft()->traverse(mOutputHLSL); out << ";\n"; - out << "if(s" << i << ")\n" + out << "if (s" << i << ")\n" "{\n"; mTemporaryIndex = i + 1; node->getRight()->traverse(this); @@ -115,7 +123,7 @@ bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) mTemporaryIndex = i + 1; node->getCondition()->traverse(this); - out << "if("; + out << "if ("; mTemporaryIndex = i + 1; node->getCondition()->traverse(mOutputHLSL); out << ")\n" diff --git a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h similarity index 90% rename from src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h rename to src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h index cb176a5f1c..1e416bc04c 100644 --- a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h @@ -9,8 +9,8 @@ #ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ #define COMPILER_UNFOLDSHORTCIRCUIT_H_ -#include "compiler/intermediate.h" -#include "compiler/ParseHelper.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/ParseContext.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp new file mode 100644 index 0000000000..29c4397d56 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp @@ -0,0 +1,81 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/UnfoldShortCircuitAST.h" + +namespace +{ + +// "x || y" is equivalent to "x ? true : y". +TIntermSelection *UnfoldOR(TIntermTyped *x, TIntermTyped *y) +{ + const TType boolType(EbtBool, EbpUndefined); + ConstantUnion *u = new ConstantUnion; + u->setBConst(true); + TIntermConstantUnion *trueNode = new TIntermConstantUnion( + u, TType(EbtBool, EbpUndefined, EvqConst, 1)); + return new TIntermSelection(x, trueNode, y, boolType); +} + +// "x && y" is equivalent to "x ? y : false". +TIntermSelection *UnfoldAND(TIntermTyped *x, TIntermTyped *y) +{ + const TType boolType(EbtBool, EbpUndefined); + ConstantUnion *u = new ConstantUnion; + u->setBConst(false); + TIntermConstantUnion *falseNode = new TIntermConstantUnion( + u, TType(EbtBool, EbpUndefined, EvqConst, 1)); + return new TIntermSelection(x, y, falseNode, boolType); +} + +} // namespace anonymous + +bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node) +{ + TIntermSelection *replacement = NULL; + + switch (node->getOp()) + { + case EOpLogicalOr: + replacement = UnfoldOR(node->getLeft(), node->getRight()); + break; + case EOpLogicalAnd: + replacement = UnfoldAND(node->getLeft(), node->getRight()); + break; + default: + break; + } + if (replacement) + { + replacements.push_back( + NodeUpdateEntry(getParentNode(), node, replacement)); + } + return true; +} + +void UnfoldShortCircuitAST::updateTree() +{ + for (size_t ii = 0; ii < replacements.size(); ++ii) + { + const NodeUpdateEntry& entry = replacements[ii]; + ASSERT(entry.parent); + bool replaced = entry.parent->replaceChildNode( + entry.original, entry.replacement); + ASSERT(replaced); + + // In AST traversing, a parent is visited before its children. + // After we replace a node, if an immediate child is to + // be replaced, we need to make sure we don't update the replaced + // node; instead, we update the replacement node. + for (size_t jj = ii + 1; jj < replacements.size(); ++jj) + { + NodeUpdateEntry& entry2 = replacements[jj]; + if (entry2.parent == entry.original) + entry2.parent = entry.replacement; + } + } +} + diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h new file mode 100644 index 0000000000..24c14a60e3 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -0,0 +1,51 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UnfoldShortCircuitAST is an AST traverser to replace short-circuiting +// operations with ternary operations. +// + +#ifndef COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ +#define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ + +#include "common/angleutils.h" +#include "compiler/translator/intermediate.h" + +// This traverser identifies all the short circuit binary nodes that need to +// be replaced, and creates the corresponding replacement nodes. However, +// the actual replacements happen after the traverse through updateTree(). + +class UnfoldShortCircuitAST : public TIntermTraverser +{ + public: + UnfoldShortCircuitAST() { } + + virtual bool visitBinary(Visit visit, TIntermBinary *); + + void updateTree(); + + private: + struct NodeUpdateEntry + { + NodeUpdateEntry(TIntermNode *_parent, + TIntermNode *_original, + TIntermNode *_replacement) + : parent(_parent), + original(_original), + replacement(_replacement) {} + + TIntermNode *parent; + TIntermNode *original; + TIntermNode *replacement; + }; + + // During traversing, save all the replacements that need to happen; + // then replace them by calling updateNodes(). + std::vector replacements; + + DISALLOW_COPY_AND_ASSIGN(UnfoldShortCircuitAST); +}; + +#endif // COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ diff --git a/src/3rdparty/angle/src/compiler/Uniform.cpp b/src/3rdparty/angle/src/compiler/translator/Uniform.cpp similarity index 91% rename from src/3rdparty/angle/src/compiler/Uniform.cpp rename to src/3rdparty/angle/src/compiler/translator/Uniform.cpp index f367db2be8..922e13f071 100644 --- a/src/3rdparty/angle/src/compiler/Uniform.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Uniform.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/Uniform.h" +#include "compiler/translator/Uniform.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/Uniform.h b/src/3rdparty/angle/src/compiler/translator/Uniform.h similarity index 100% rename from src/3rdparty/angle/src/compiler/Uniform.h rename to src/3rdparty/angle/src/compiler/translator/Uniform.h diff --git a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp similarity index 98% rename from src/3rdparty/angle/src/compiler/ValidateLimitations.cpp rename to src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp index 736ceeaefc..3c2cc41cda 100644 --- a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#include "compiler/ValidateLimitations.h" -#include "compiler/InfoSink.h" -#include "compiler/InitializeParseContext.h" -#include "compiler/ParseHelper.h" +#include "compiler/translator/ValidateLimitations.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/ParseContext.h" namespace { bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) { @@ -457,7 +457,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) bool ValidateLimitations::validateOperation(TIntermOperator* node, TIntermNode* operand) { // Check if loop index is modified in the loop body. - if (!withinLoopBody() || !node->modifiesState()) + if (!withinLoopBody() || !node->isAssignment()) return true; const TIntermSymbol* symbol = operand->getAsSymbolNode(); diff --git a/src/3rdparty/angle/src/compiler/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h similarity index 97% rename from src/3rdparty/angle/src/compiler/ValidateLimitations.h rename to src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h index a835cb3c22..8839dd8b8a 100644 --- a/src/3rdparty/angle/src/compiler/ValidateLimitations.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h @@ -5,7 +5,7 @@ // #include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp similarity index 98% rename from src/3rdparty/angle/src/compiler/VariableInfo.cpp rename to src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index f3f7b1ef35..ef888aff11 100644 --- a/src/3rdparty/angle/src/compiler/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/VariableInfo.h" +#include "compiler/translator/VariableInfo.h" namespace { @@ -116,10 +116,12 @@ void getBuiltInVariableInfo(const TType& type, varInfo.name = (name + "[0]").c_str(); varInfo.mappedName = (mappedName + "[0]").c_str(); varInfo.size = type.getArraySize(); + varInfo.isArray = true; } else { varInfo.name = name.c_str(); varInfo.mappedName = mappedName.c_str(); varInfo.size = 1; + varInfo.isArray = false; } varInfo.precision = type.getPrecision(); varInfo.type = getVariableDataType(type); @@ -167,6 +169,7 @@ TVariableInfo* findVariable(const TType& type, TVariableInfo::TVariableInfo() : type(SH_NONE), size(0), + isArray(false), precision(EbpUndefined), staticUse(false) { @@ -175,6 +178,7 @@ TVariableInfo::TVariableInfo() TVariableInfo::TVariableInfo(ShDataType type, int size) : type(type), size(size), + isArray(false), precision(EbpUndefined), staticUse(false) { diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h similarity index 95% rename from src/3rdparty/angle/src/compiler/VariableInfo.h rename to src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 3c7f2a5f84..37216cd142 100644 --- a/src/3rdparty/angle/src/compiler/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -8,7 +8,7 @@ #define COMPILER_VARIABLE_INFO_H_ #include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" // Provides information about a variable. // It is currently being used to store info about active attribs and uniforms. @@ -20,6 +20,7 @@ struct TVariableInfo { TPersistString mappedName; ShDataType type; int size; + bool isArray; TPrecision precision; bool staticUse; }; diff --git a/src/3rdparty/angle/src/compiler/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp similarity index 98% rename from src/3rdparty/angle/src/compiler/VariablePacker.cpp rename to src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp index 8957287763..5634d86337 100644 --- a/src/3rdparty/angle/src/compiler/VariablePacker.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp @@ -3,10 +3,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#include "compiler/VariablePacker.h" +#include "compiler/translator/VariablePacker.h" #include -#include "compiler/ShHandle.h" +#include "compiler/translator/ShHandle.h" namespace { int GetSortOrder(ShDataType type) diff --git a/src/3rdparty/angle/src/compiler/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h similarity index 96% rename from src/3rdparty/angle/src/compiler/VariablePacker.h rename to src/3rdparty/angle/src/compiler/translator/VariablePacker.h index 8987066cc3..fd6090827c 100644 --- a/src/3rdparty/angle/src/compiler/VariablePacker.h +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h @@ -8,7 +8,7 @@ #define _VARIABLEPACKER_INCLUDED_ #include -#include "compiler/ShHandle.h" +#include "compiler/translator/ShHandle.h" class VariablePacker { public: diff --git a/src/3rdparty/angle/src/compiler/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp similarity index 98% rename from src/3rdparty/angle/src/compiler/VersionGLSL.cpp rename to src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index 7a82bb4dc1..dd11f99eb8 100644 --- a/src/3rdparty/angle/src/compiler/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/VersionGLSL.h" +#include "compiler/translator/VersionGLSL.h" static const int GLSL_VERSION_110 = 110; static const int GLSL_VERSION_120 = 120; diff --git a/src/3rdparty/angle/src/compiler/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h similarity index 97% rename from src/3rdparty/angle/src/compiler/VersionGLSL.h rename to src/3rdparty/angle/src/compiler/translator/VersionGLSL.h index 1c1cb1ab97..d310066171 100644 --- a/src/3rdparty/angle/src/compiler/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -8,7 +8,7 @@ #define COMPILER_VERSIONGLSL_H_ #include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" // Traverses the intermediate tree to return the minimum GLSL version // required to legally access all built-in features used in the shader. diff --git a/src/3rdparty/angle/src/compiler/debug.cpp b/src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp similarity index 83% rename from src/3rdparty/angle/src/compiler/debug.cpp rename to src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp index 53778bd3eb..10cbe43b8d 100644 --- a/src/3rdparty/angle/src/compiler/debug.cpp +++ b/src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp @@ -6,17 +6,17 @@ // debug.cpp: Debugging utilities. -#include "compiler/debug.h" +#include "compiler/translator/compilerdebug.h" #include #include -#include "compiler/InitializeParseContext.h" -#include "compiler/ParseHelper.h" - -static const int kTraceBufferLen = 1024; +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/ParseContext.h" #ifdef TRACE_ENABLED +static const int kTraceBufferLen = 1024; + extern "C" { void Trace(const char *format, ...) { if (!format) return; diff --git a/src/3rdparty/angle/src/compiler/debug.h b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h similarity index 100% rename from src/3rdparty/angle/src/compiler/debug.h rename to src/3rdparty/angle/src/compiler/translator/compilerdebug.h diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp similarity index 95% rename from src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp rename to src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp index ca661d6767..19ddf5c439 100644 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.cpp +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp @@ -6,8 +6,8 @@ #pragma warning(disable: 4718) -#include "compiler/depgraph/DependencyGraph.h" -#include "compiler/depgraph/DependencyGraphBuilder.h" +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/depgraph/DependencyGraphBuilder.h" TDependencyGraph::TDependencyGraph(TIntermNode* intermNode) { diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h similarity index 99% rename from src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h rename to src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h index 5a9c35d00b..5ea1cbb837 100644 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraph.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -7,7 +7,7 @@ #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H -#include "compiler/intermediate.h" +#include "compiler/translator/intermediate.h" #include #include diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp similarity index 98% rename from src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp rename to src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp index d586cfd03c..d5f2cba5fc 100644 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.cpp +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/depgraph/DependencyGraphBuilder.h" +#include "compiler/translator/depgraph/DependencyGraphBuilder.h" void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph) { @@ -94,7 +94,7 @@ void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol) bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary) { TOperator op = intermBinary->getOp(); - if (op == EOpInitialize || intermBinary->modifiesState()) + if (op == EOpInitialize || intermBinary->isAssignment()) visitAssignment(intermBinary); else if (op == EOpLogicalAnd || op == EOpLogicalOr) visitLogicalOp(intermBinary); diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h similarity index 99% rename from src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h rename to src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h index c5f232cb21..3e928fb77e 100644 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphBuilder.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h @@ -7,7 +7,7 @@ #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H -#include "compiler/depgraph/DependencyGraph.h" +#include "compiler/translator/depgraph/DependencyGraph.h" // // Creates a dependency graph of symbols, function calls, conditions etc. by traversing a diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp similarity index 96% rename from src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp rename to src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp index 6fc489e7b6..e226333545 100644 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.cpp +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/depgraph/DependencyGraphOutput.h" +#include "compiler/translator/depgraph/DependencyGraphOutput.h" void TDependencyGraphOutput::outputIndentation() { diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h similarity index 90% rename from src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h rename to src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h index 01447da987..c3a4112278 100644 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphOutput.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h @@ -7,8 +7,8 @@ #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H -#include "compiler/depgraph/DependencyGraph.h" -#include "compiler/InfoSink.h" +#include "compiler/translator/depgraph/DependencyGraph.h" +#include "compiler/translator/InfoSink.h" class TDependencyGraphOutput : public TDependencyGraphTraverser { public: diff --git a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp similarity index 96% rename from src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp rename to src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp index b158575cec..197fde97e2 100644 --- a/src/3rdparty/angle/src/compiler/depgraph/DependencyGraphTraverse.cpp +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/depgraph/DependencyGraph.h" +#include "compiler/translator/depgraph/DependencyGraph.h" // These methods do a breadth-first traversal through the graph and mark visited nodes. diff --git a/src/3rdparty/angle/src/compiler/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h similarity index 100% rename from src/3rdparty/angle/src/compiler/glslang.h rename to src/3rdparty/angle/src/compiler/translator/glslang.h diff --git a/src/3rdparty/angle/src/compiler/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l similarity index 98% rename from src/3rdparty/angle/src/compiler/glslang.l rename to src/3rdparty/angle/src/compiler/translator/glslang.l index 60663f9a6b..ffc1aa18ac 100644 --- a/src/3rdparty/angle/src/compiler/glslang.l +++ b/src/3rdparty/angle/src/compiler/translator/glslang.l @@ -36,10 +36,10 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). } %{ -#include "compiler/glslang.h" -#include "compiler/ParseHelper.h" +#include "compiler/translator/glslang.h" +#include "compiler/translator/ParseContext.h" #include "compiler/preprocessor/Token.h" -#include "compiler/util.h" +#include "compiler/translator/util.h" #include "glslang_tab.h" /* windows only pragma */ diff --git a/src/3rdparty/angle/src/compiler/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y similarity index 99% rename from src/3rdparty/angle/src/compiler/glslang.y rename to src/3rdparty/angle/src/compiler/translator/glslang.y index c64f736f41..7614ff3447 100644 --- a/src/3rdparty/angle/src/compiler/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -34,8 +34,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #pragma warning(disable: 4701) #endif -#include "compiler/SymbolTable.h" -#include "compiler/ParseHelper.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/ParseContext.h" #include "GLSLANG/ShaderLang.h" #define YYENABLE_NLS 0 @@ -183,43 +183,55 @@ identifier variable_identifier : IDENTIFIER { // The symbol table search was done in the lexical phase - const TSymbol* symbol = $1.symbol; - const TVariable* variable; - if (symbol == 0) { + const TSymbol *symbol = $1.symbol; + const TVariable *variable = 0; + + if (!symbol) + { context->error(@1, "undeclared identifier", $1.string->c_str()); context->recover(); - TType type(EbtFloat, EbpUndefined); - TVariable* fakeVariable = new TVariable($1.string, type); - context->symbolTable.insert(*fakeVariable); - variable = fakeVariable; - } else { - // This identifier can only be a variable type symbol - if (! symbol->isVariable()) { - context->error(@1, "variable expected", $1.string->c_str()); - context->recover(); - } - + } + else if (!symbol->isVariable()) + { + context->error(@1, "variable expected", $1.string->c_str()); + context->recover(); + } + else + { variable = static_cast(symbol); if (context->symbolTable.findBuiltIn(variable->getName()) && !variable->getExtension().empty() && - context->extensionErrorCheck(@1, variable->getExtension())) { + context->extensionErrorCheck(@1, variable->getExtension())) + { context->recover(); } } - // don't delete $1.string, it's used by error recovery, and the pool - // pop will reclaim the memory + if (!variable) + { + TType type(EbtFloat, EbpUndefined); + TVariable *fakeVariable = new TVariable($1.string, type); + context->symbolTable.insert(*fakeVariable); + variable = fakeVariable; + } - if (variable->getType().getQualifier() == EvqConst ) { + if (variable->getType().getQualifier() == EvqConst) + { ConstantUnion* constArray = variable->getConstPointer(); TType t(variable->getType()); $$ = context->intermediate.addConstantUnion(constArray, t, @1); - } else + } + else + { $$ = context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), @1); + } + + // don't delete $1.string, it's used by error recovery, and the pool + // pop will reclaim the memory } ; diff --git a/src/3rdparty/angle/src/compiler/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp similarity index 98% rename from src/3rdparty/angle/src/compiler/intermOut.cpp rename to src/3rdparty/angle/src/compiler/translator/intermOut.cpp index 13aa96af6d..f2f918d77a 100644 --- a/src/3rdparty/angle/src/compiler/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/localintermediate.h" +#include "compiler/translator/localintermediate.h" // // Two purposes: @@ -44,9 +44,9 @@ TString TType::getCompleteString() const if (array) stream << "array[" << getArraySize() << "] of "; if (matrix) - stream << size << "X" << size << " matrix of "; + stream << static_cast(size) << "X" << static_cast(size) << " matrix of "; else if (size > 1) - stream << size << "-component vector of "; + stream << static_cast(size) << "-component vector of "; stream << getBasicString(); return stream.str(); diff --git a/src/3rdparty/angle/src/compiler/intermediate.h b/src/3rdparty/angle/src/compiler/translator/intermediate.h similarity index 84% rename from src/3rdparty/angle/src/compiler/intermediate.h rename to src/3rdparty/angle/src/compiler/translator/intermediate.h index 738621fe70..8f9fe23d3b 100644 --- a/src/3rdparty/angle/src/compiler/intermediate.h +++ b/src/3rdparty/angle/src/compiler/translator/intermediate.h @@ -19,9 +19,9 @@ #include "GLSLANG/ShaderLang.h" #include -#include "compiler/Common.h" -#include "compiler/Types.h" -#include "compiler/ConstantUnion.h" +#include "compiler/translator/Common.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/ConstantUnion.h" // // Operators used by the high-level (parse tree) representation. @@ -227,6 +227,11 @@ public: virtual TIntermSymbol* getAsSymbolNode() { return 0; } virtual TIntermLoop* getAsLoopNode() { return 0; } + // Replace a child node. Return true if |original| is a child + // node and it is replaced; otherwise, return false. + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) = 0; + protected: TSourceLoc line; }; @@ -247,6 +252,8 @@ public: TIntermTyped(const TType& t) : type(t) { } virtual TIntermTyped* getAsTyped() { return this; } + virtual bool hasSideEffects() const = 0; + void setType(const TType& t) { type = t; } const TType& getType() const { return type; } TType* getTypePointer() { return &type; } @@ -295,6 +302,8 @@ public: virtual TIntermLoop* getAsLoopNode() { return this; } virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); TLoopType getType() const { return type; } TIntermNode* getInit() { return init; } @@ -325,6 +334,8 @@ public: expression(e) { } virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); TOperator getFlowOp() { return flowOp; } TIntermTyped* getExpression() { return expression; } @@ -345,6 +356,8 @@ public: TIntermSymbol(int i, const TString& sym, const TType& t) : TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; } + virtual bool hasSideEffects() const { return false; } + int getId() const { return id; } const TString& getSymbol() const { return symbol; } @@ -355,6 +368,7 @@ public: virtual void traverse(TIntermTraverser*); virtual TIntermSymbol* getAsSymbolNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } protected: int id; @@ -366,14 +380,17 @@ class TIntermConstantUnion : public TIntermTyped { public: TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } + virtual bool hasSideEffects() const { return false; } + ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } - int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } - float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } - bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } + int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } + float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } + bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } virtual TIntermConstantUnion* getAsConstantUnion() { return this; } virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); @@ -389,12 +406,14 @@ public: TOperator getOp() const { return op; } void setOp(TOperator o) { op = o; } - bool modifiesState() const; + bool isAssignment() const; bool isConstructor() const; + virtual bool hasSideEffects() const { return isAssignment(); } + protected: TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} - TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} + TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {} TOperator op; }; @@ -407,6 +426,10 @@ public: virtual TIntermBinary* getAsBinaryNode() { return this; } virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); } void setLeft(TIntermTyped* n) { left = n; } void setRight(TIntermTyped* n) { right = n; } @@ -430,11 +453,15 @@ protected: // class TIntermUnary : public TIntermOperator { public: - TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {} + TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {} TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {} virtual void traverse(TIntermTraverser*); virtual TIntermUnary* getAsUnaryNode() { return this; } + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); } void setOperand(TIntermTyped* o) { operand = o; } TIntermTyped* getOperand() { return operand; } @@ -465,6 +492,11 @@ public: virtual TIntermAggregate* getAsAggregate() { return this; } virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume function calls and other aggregate operators have side-effects + virtual bool hasSideEffects() const { return true; } TIntermSequence& getSequence() { return sequence; } @@ -508,6 +540,11 @@ public: TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} virtual void traverse(TIntermTraverser*); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume selections have side-effects + virtual bool hasSideEffects() const { return true; } bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } TIntermNode* getCondition() const { return condition; } @@ -547,7 +584,7 @@ public: rightToLeft(rightToLeft), depth(0), maxDepth(0) {} - virtual ~TIntermTraverser() {}; + virtual ~TIntermTraverser() {} virtual void visitSymbol(TIntermSymbol*) {} virtual void visitConstantUnion(TIntermConstantUnion*) {} @@ -559,8 +596,24 @@ public: virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} int getMaxDepth() const {return maxDepth;} - void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); } - void decrementDepth() {depth--;} + + void incrementDepth(TIntermNode *current) + { + depth++; + maxDepth = std::max(maxDepth, depth); + path.push_back(current); + } + + void decrementDepth() + { + depth--; + path.pop_back(); + } + + TIntermNode *getParentNode() + { + return path.size() == 0 ? NULL : path.back(); + } // Return the original name if hash function pointer is NULL; // otherwise return the hashed name. @@ -574,6 +627,9 @@ public: protected: int depth; int maxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector path; }; #endif // __INTERMEDIATE_H diff --git a/src/3rdparty/angle/src/compiler/localintermediate.h b/src/3rdparty/angle/src/compiler/translator/localintermediate.h similarity index 95% rename from src/3rdparty/angle/src/compiler/localintermediate.h rename to src/3rdparty/angle/src/compiler/translator/localintermediate.h index 1214d821eb..b582e02f5d 100644 --- a/src/3rdparty/angle/src/compiler/localintermediate.h +++ b/src/3rdparty/angle/src/compiler/translator/localintermediate.h @@ -8,8 +8,8 @@ #define _LOCAL_INTERMEDIATE_INCLUDED_ #include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" -#include "compiler/SymbolTable.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/SymbolTable.h" struct TVectorFields { int offsets[4]; @@ -39,7 +39,7 @@ public: TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&); TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; - bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); + bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&); TIntermBranch* addBranch(TOperator, const TSourceLoc&); TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); diff --git a/src/3rdparty/angle/src/compiler/osinclude.h b/src/3rdparty/angle/src/compiler/translator/osinclude.h similarity index 87% rename from src/3rdparty/angle/src/compiler/osinclude.h rename to src/3rdparty/angle/src/compiler/translator/osinclude.h index 60177d5fe5..cccfa6355c 100644 --- a/src/3rdparty/angle/src/compiler/osinclude.h +++ b/src/3rdparty/angle/src/compiler/translator/osinclude.h @@ -13,9 +13,6 @@ // #if defined(_WIN32) || defined(_WIN64) -#define STRICT -#define VC_EXTRALEAN 1 -#include #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) #define ANGLE_OS_WINRT #else @@ -23,18 +20,27 @@ #endif #elif defined(__APPLE__) || defined(__linux__) || \ defined(__FreeBSD__) || defined(__OpenBSD__) || \ + defined(__NetBSD__) || defined(__DragonFly__) || \ defined(__sun) || defined(ANDROID) || \ defined(__GLIBC__) || defined(__GNU__) || \ defined(__QNX__) #define ANGLE_OS_POSIX -#include -#include -#include #else #error Unsupported platform. #endif -#include "compiler/debug.h" +#if defined(ANGLE_OS_WIN) || defined(ANGLE_OS_WINRT) +#define STRICT +#define VC_EXTRALEAN 1 +#include +#elif defined(ANGLE_OS_POSIX) +#include +#include +#include +#endif // ANGLE_OS_WIN + + +#include "compiler/translator/compilerdebug.h" // // Thread Local Storage Operations diff --git a/src/3rdparty/angle/src/compiler/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp similarity index 97% rename from src/3rdparty/angle/src/compiler/ossource_posix.cpp rename to src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp index 35510c1af5..d4bba4c70e 100644 --- a/src/3rdparty/angle/src/compiler/ossource_posix.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp @@ -7,7 +7,7 @@ // // This file contains the posix specific functions // -#include "compiler/osinclude.h" +#include "compiler/translator/osinclude.h" #if !defined(ANGLE_OS_POSIX) #error Trying to build a posix specific file in a non-posix build. diff --git a/src/3rdparty/angle/src/compiler/ossource_win.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp similarity index 96% rename from src/3rdparty/angle/src/compiler/ossource_win.cpp rename to src/3rdparty/angle/src/compiler/translator/ossource_win.cpp index 708a1ad311..abd8bc7833 100644 --- a/src/3rdparty/angle/src/compiler/ossource_win.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/osinclude.h" +#include "compiler/translator/osinclude.h" // // This file contains contains the window's specific functions // diff --git a/src/3rdparty/angle/src/compiler/ossource_winrt.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp similarity index 97% rename from src/3rdparty/angle/src/compiler/ossource_winrt.cpp rename to src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp index 84443abc02..bb061ca85d 100644 --- a/src/3rdparty/angle/src/compiler/ossource_winrt.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/osinclude.h" +#include "compiler/translator/osinclude.h" // // This file contains contains Windows Runtime specific functions // diff --git a/src/3rdparty/angle/src/compiler/parseConst.cpp b/src/3rdparty/angle/src/compiler/translator/parseConst.cpp similarity index 99% rename from src/3rdparty/angle/src/compiler/parseConst.cpp rename to src/3rdparty/angle/src/compiler/translator/parseConst.cpp index 1cc5db8d77..a59f0be9d8 100644 --- a/src/3rdparty/angle/src/compiler/parseConst.cpp +++ b/src/3rdparty/angle/src/compiler/translator/parseConst.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/ParseHelper.h" +#include "compiler/translator/ParseContext.h" // // Use this class to carry along data from node to node in diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp similarity index 95% rename from src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp rename to src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp index 538b731b8e..a9f3f49ef3 100644 --- a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.cpp +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#include "compiler/InfoSink.h" -#include "compiler/ParseHelper.h" -#include "compiler/depgraph/DependencyGraphOutput.h" -#include "compiler/timing/RestrictFragmentShaderTiming.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/ParseContext.h" +#include "compiler/translator/depgraph/DependencyGraphOutput.h" +#include "compiler/translator/timing/RestrictFragmentShaderTiming.h" RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink) : mSink(sink) diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h similarity index 92% rename from src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h rename to src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h index 899165ca28..323cb62d8a 100644 --- a/src/3rdparty/angle/src/compiler/timing/RestrictFragmentShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -9,8 +9,8 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" -#include "compiler/depgraph/DependencyGraph.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/depgraph/DependencyGraph.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp similarity index 87% rename from src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp rename to src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp index 355eb62d65..ee78c35450 100644 --- a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/timing/RestrictVertexShaderTiming.h" +#include "compiler/translator/timing/RestrictVertexShaderTiming.h" void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node) { diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h similarity index 90% rename from src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h rename to src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h index 19a05fa68b..5f0dd3197a 100644 --- a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -9,8 +9,8 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/intermediate.h" -#include "compiler/InfoSink.h" +#include "compiler/translator/intermediate.h" +#include "compiler/translator/InfoSink.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp similarity index 94% rename from src/3rdparty/angle/src/compiler/util.cpp rename to src/3rdparty/angle/src/compiler/translator/util.cpp index d6e5eeed91..077bdcc48b 100644 --- a/src/3rdparty/angle/src/compiler/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/util.h" +#include "compiler/translator/util.h" #include diff --git a/src/3rdparty/angle/src/compiler/util.h b/src/3rdparty/angle/src/compiler/translator/util.h similarity index 100% rename from src/3rdparty/angle/src/compiler/util.h rename to src/3rdparty/angle/src/compiler/translator/util.h diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index b18a876a55..e75a4b6440 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -1,3 +1,4 @@ +#include "../libGLESv2/precompiled.h" // // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -40,13 +41,13 @@ egl::Display *Display::getDisplay(EGLNativeDisplayType displayId) // FIXME: Check if displayId is a valid display device context - egl::Display *display = new egl::Display(displayId, (HDC)displayId); + egl::Display *display = new egl::Display(displayId); displays[displayId] = display; return display; } -Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext) +Display::Display(EGLNativeDisplayType displayId) { mDisplayId = displayId; mRenderer = NULL; @@ -71,7 +72,7 @@ bool Display::initialize() return true; } - mRenderer = glCreateRenderer(this, mDc, mDisplayId); + mRenderer = glCreateRenderer(this, mDisplayId); if (!mRenderer) { @@ -486,7 +487,7 @@ void Display::initExtensionString() mExtensionString += "EGL_ANGLE_query_surface_pointer "; -#if !defined(ANGLE_OS_WINRT) +#if defined(ANGLE_ENABLE_D3D9) HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); if (swiftShader) { @@ -525,7 +526,7 @@ void Display::initVendorString() if (mRenderer && mRenderer->getLUID(&adapterLuid)) { char adapterLuidString[64]; - snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08l%08l)", adapterLuid.HighPart, adapterLuid.LowPart); + snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); mVendorString += adapterLuidString; } diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h index 5d55410440..cd07bb3388 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h @@ -11,8 +11,6 @@ #ifndef LIBEGL_DISPLAY_H_ #define LIBEGL_DISPLAY_H_ -#include "common/system.h" - #include #include @@ -65,12 +63,11 @@ class Display private: DISALLOW_COPY_AND_ASSIGN(Display); - Display(EGLNativeDisplayType displayId, HDC deviceContext); + Display(EGLNativeDisplayType displayId); bool restoreLostDevice(); EGLNativeDisplayType mDisplayId; - const HDC mDc; bool mSoftwareDevice; diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index dbff159d0e..3443355c07 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -1,3 +1,4 @@ +#include "../libGLESv2/precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,6 +11,8 @@ #include +#include + #include "libEGL/Surface.h" #include "common/debug.h" @@ -20,8 +23,6 @@ #include "libEGL/main.h" #include "libEGL/Display.h" -#include - #if defined(ANGLE_OS_WINRT) #include #include @@ -118,12 +119,9 @@ bool Surface::resetSwapChain() #else ABI::Windows::Foundation::Rect windowRect; ABI::Windows::UI::Core::ICoreWindow *window; - HRESULT result = mWindow->QueryInterface(IID_PPV_ARGS(&window)); - if (FAILED(result)) - { - ASSERT(false); + HRESULT hr = mWindow->QueryInterface(IID_PPV_ARGS(&window)); + if (FAILED(hr)) return false; - } window->get_Bounds(&windowRect); width = windowRect.Width; height = windowRect.Height; @@ -156,16 +154,9 @@ bool Surface::resetSwapChain() bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) { + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); - // Prevent bad swap chain resize by calling reset if size is invalid - if (backbufferWidth < 1 || backbufferHeight < 1) - { - mWidth = backbufferWidth; - mHeight = backbufferHeight; - return mSwapChain->reset(0, 0, mSwapInterval) == EGL_SUCCESS; - } - EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); if (status == EGL_CONTEXT_LOST) @@ -347,18 +338,26 @@ bool Surface::checkForOutOfDateSwapChain() #else ABI::Windows::Foundation::Rect windowRect; ABI::Windows::UI::Core::ICoreWindow *window; - HRESULT result = mWindow->QueryInterface(IID_PPV_ARGS(&window)); - if (FAILED(result)) - { - ASSERT(false); + HRESULT hr = mWindow->QueryInterface(IID_PPV_ARGS(&window)); + if (FAILED(hr)) return false; - } window->get_Bounds(&windowRect); int clientWidth = windowRect.Width; int clientHeight = windowRect.Height; #endif bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); +#if !defined(ANGLE_OS_WINRT) + if (IsIconic(getWindowHandle())) + { + // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized + // because that's not a useful size to render to. + sizeDirty = false; + } +#endif + + bool wasDirty = (mSwapIntervalDirty || sizeDirty); + if (mSwapIntervalDirty) { resetSwapChain(clientWidth, clientHeight); @@ -368,7 +367,7 @@ bool Surface::checkForOutOfDateSwapChain() resizeSwapChain(clientWidth, clientHeight); } - if (mSwapIntervalDirty || sizeDirty) + if (wasDirty) { if (static_cast(getCurrentDrawSurface()) == this) { diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h index ae9a380858..1d2303c6eb 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ b/src/3rdparty/angle/src/libEGL/Surface.h @@ -15,7 +15,6 @@ #include #include "common/angleutils.h" -#include "windows.h" namespace gl { @@ -80,7 +79,7 @@ private: bool resetSwapChain(int backbufferWidth, int backbufferHeight); bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - const EGLNativeWindowType mWindow; // Window that the surface is created for. + const EGLNativeWindowType mWindow; // Window that the surface is created for. bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking const egl::Config *mConfig; // EGL config surface was created with EGLint mHeight; // Height of surface diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index 5bcb5d5959..b2944d5c0d 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -184,7 +184,7 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) case EGL_VENDOR: return egl::success(display->getVendorString()); case EGL_VERSION: - return egl::success("1.4 (ANGLE " VERSION_STRING ")"); + return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); } return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); @@ -821,13 +821,21 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); } - if (share_context && static_cast(share_context)->isResetNotificationEnabled() != reset_notification) + gl::Context *sharedContextPtr = (share_context != EGL_NO_CONTEXT ? static_cast(share_context) : NULL); + + if (sharedContextPtr != NULL && sharedContextPtr->isResetNotificationEnabled() != reset_notification) { return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); } egl::Display *display = static_cast(dpy); + // Can not share contexts between displays + if (sharedContextPtr != NULL && sharedContextPtr->getRenderer() != display->getRenderer()) + { + return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + } + if (!validateConfig(display, config)) { return EGL_NO_CONTEXT; diff --git a/src/3rdparty/angle/src/libEGL/libEGL.rc b/src/3rdparty/angle/src/libEGL/libEGL.rc index 5d1f32f1c9..65e0aa50c8 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.rc +++ b/src/3rdparty/angle/src/libEGL/libEGL.rc @@ -54,8 +54,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION - PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION + FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 + PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -71,13 +71,14 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library" - VALUE "FileVersion", VERSION_STRING + VALUE "FileVersion", ANGLE_VERSION_STRING VALUE "InternalName", "libEGL" VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." VALUE "OriginalFilename", "libEGL.dll" - VALUE "PrivateBuild", VERSION_STRING + VALUE "PrivateBuild", ANGLE_VERSION_STRING VALUE "ProductName", "ANGLE libEGL Dynamic Link Library" - VALUE "ProductVersion", VERSION_STRING + VALUE "ProductVersion", ANGLE_VERSION_STRING + VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE END END BLOCK "VarFileInfo" diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index 964b4b21fd..e972691a4f 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -11,15 +11,63 @@ #include "common/debug.h" -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - #if !defined(ANGLE_OS_WINRT) static DWORD currentTLS = TLS_OUT_OF_INDEXES; #else static __declspec(thread) void *currentTLS = 0; #endif -namespace egl { Current *getCurrent(); } +namespace egl +{ + +Current *AllocateCurrent() +{ +#if !defined(ANGLE_OS_WINRT) + Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); +#else + currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current)); + Current *current = (egl::Current*)currentTLS; +#endif + + if (!current) + { + ERR("Could not allocate thread local storage."); + return NULL; + } + +#if !defined(ANGLE_OS_WINRT) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + TlsSetValue(currentTLS, current); +#endif + + current->error = EGL_SUCCESS; + current->API = EGL_OPENGL_ES_API; + current->display = EGL_NO_DISPLAY; + current->drawSurface = EGL_NO_SURFACE; + current->readSurface = EGL_NO_SURFACE; + + return current; +} + +void DeallocateCurrent() +{ +#if !defined(ANGLE_OS_WINRT) + void *current = TlsGetValue(currentTLS); + + if (current) + { + LocalFree((HLOCAL)current); + } +#else + if (currentTLS) + { + HeapFree(GetProcessHeap(), 0, currentTLS); + currentTLS = 0; + } +#endif +} + +} extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { @@ -27,7 +75,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved { case DLL_PROCESS_ATTACH: { -#if !defined(ANGLE_DISABLE_TRACE) +#if defined(ANGLE_ENABLE_TRACE) FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt"); if (debug) @@ -41,7 +89,6 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved } } #endif - #if !defined(ANGLE_OS_WINRT) currentTLS = TlsAlloc(); @@ -54,51 +101,19 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved // Fall throught to initialize index case DLL_THREAD_ATTACH: { - egl::Current *current = egl::getCurrent(); - - if (current) - { -#if !defined(ANGLE_OS_WINRT) - TlsSetValue(currentTLS, current); -#endif - current->error = EGL_SUCCESS; - current->API = EGL_OPENGL_ES_API; - current->display = EGL_NO_DISPLAY; - current->drawSurface = EGL_NO_SURFACE; - current->readSurface = EGL_NO_SURFACE; - } + egl::AllocateCurrent(); } break; case DLL_THREAD_DETACH: { - egl::Current *current = egl::getCurrent(); - - if (current) - { -#if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); -#else - HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); - currentTLS = 0; -#endif - } + egl::DeallocateCurrent(); } break; case DLL_PROCESS_DETACH: { - egl::Current *current = egl::getCurrent(); - - if (current) - { + egl::DeallocateCurrent(); #if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); - } - TlsFree(currentTLS); -#else - HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); - currentTLS = 0; - } #endif } break; @@ -109,96 +124,94 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved return TRUE; } -#endif // !QT_OPENGL_ES_2_ANGLE_STATIC - namespace egl { -Current *getCurrent() + +Current *GetCurrentData() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC #if !defined(ANGLE_OS_WINRT) Current *current = (Current*)TlsGetValue(currentTLS); - if (!current) - current = (Current*)LocalAlloc(LPTR, sizeof(Current)); - return current; #else - if (!currentTLS) - currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); - return (Current*)currentTLS; + Current *current = (Current*)currentTLS; #endif #else // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; - return &curr; + static Current s_current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; + Current *current = &s_current; #endif + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. + return (current ? current : AllocateCurrent()); } void setCurrentError(EGLint error) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->error = error; } EGLint getCurrentError() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->error; } void setCurrentAPI(EGLenum API) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->API = API; } EGLenum getCurrentAPI() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->API; } void setCurrentDisplay(EGLDisplay dpy) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->display = dpy; } EGLDisplay getCurrentDisplay() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->display; } void setCurrentDrawSurface(EGLSurface surface) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->drawSurface = surface; } EGLSurface getCurrentDrawSurface() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->drawSurface; } void setCurrentReadSurface(EGLSurface surface) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->readSurface = surface; } EGLSurface getCurrentReadSurface() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->readSurface; } diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp index 40baa95760..c007d5d9e9 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp @@ -37,11 +37,11 @@ Buffer::~Buffer() delete mStaticIndexBuffer; } -void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage, GLenum target) +void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) { mBufferStorage->clear(); mIndexRangeCache.clear(); - mBufferStorage->setData(data, size, 0, target); + mBufferStorage->setData(data, size, 0); mUsage = usage; @@ -54,9 +54,9 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage, GLenum } } -void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset, GLenum target) +void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { - mBufferStorage->setData(data, size, offset, target); + mBufferStorage->setData(data, size, offset); mIndexRangeCache.invalidateRange(offset, size); if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h index 9b86b9791f..4048f4b906 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -33,8 +33,8 @@ class Buffer : public RefCountObject virtual ~Buffer(); - void bufferData(const void *data, GLsizeiptr size, GLenum usage, GLenum target); - void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset, GLenum target); + void bufferData(const void *data, GLsizeiptr size, GLenum usage); + void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); GLenum usage() const; diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index e829d508a6..e651785aed 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -1779,7 +1779,7 @@ void Context::applyState(GLenum drawMode) { mask = 0xFFFFFFFF; } - mRenderer->setBlendState(mState.blend, mState.blendColor, mask); + mRenderer->setBlendState(framebufferObject, mState.blend, mState.blendColor, mask); mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef, mState.rasterizer.frontFace == GL_CCW); @@ -1813,6 +1813,8 @@ void Context::applyTextures(SamplerType type) { ProgramBinary *programBinary = getCurrentProgramBinary(); + FramebufferTextureSerialSet boundFramebufferTextures = getBoundFramebufferTextureSerials(); + // Range of Direct3D samplers of given sampler type int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits(); int samplerRange = programBinary->getUsedSamplerRange(type); @@ -1826,7 +1828,8 @@ void Context::applyTextures(SamplerType type) TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex); Texture *texture = getSamplerTexture(textureUnit, textureType); - if (texture->isSamplerComplete()) + if (texture->isSamplerComplete() && + boundFramebufferTextures.find(texture->getTextureSerial()) == boundFramebufferTextures.end()) { SamplerState samplerState; texture->getSamplerState(&samplerState); @@ -2656,6 +2659,29 @@ const char *Context::getRendererString() const return mRendererString; } +Context::FramebufferTextureSerialSet Context::getBoundFramebufferTextureSerials() +{ + FramebufferTextureSerialSet set; + + Framebuffer *drawFramebuffer = getDrawFramebuffer(); + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) + { + Renderbuffer *renderBuffer = drawFramebuffer->getColorbuffer(i); + if (renderBuffer && renderBuffer->getTextureSerial() != 0) + { + set.insert(renderBuffer->getTextureSerial()); + } + } + + Renderbuffer *depthStencilBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + if (depthStencilBuffer && depthStencilBuffer->getTextureSerial() != 0) + { + set.insert(depthStencilBuffer->getTextureSerial()); + } + + return set; +} + void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask) diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h index 9c222be24d..3dc95e3b95 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libGLESv2/Context.h @@ -18,6 +18,7 @@ #include #include +#include #ifdef _MSC_VER #include #else @@ -37,7 +38,6 @@ class Renderer; namespace egl { -class Display; class Surface; } @@ -73,7 +73,7 @@ enum QueryType class VertexAttribute { public: - VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0) + VertexAttribute() : mType(GL_FLOAT), mSize(4), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0) { mCurrentValue[0] = 0.0f; mCurrentValue[1] = 0.0f; @@ -398,6 +398,8 @@ class Context GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask); + rx::Renderer *getRenderer() { return mRenderer; } + private: DISALLOW_COPY_AND_ASSIGN(Context); @@ -419,6 +421,9 @@ class Context void initExtensionString(); void initRendererString(); + typedef std::set FramebufferTextureSerialSet; + FramebufferTextureSerialSet getBoundFramebufferTextureSerials(); + rx::Renderer *const mRenderer; State mState; diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index b54e008dd8..50bfd4fd0f 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -12,7 +12,7 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" -#include "constants.h" +#include "Constants.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index bcd04b7157..a4d21192fa 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -34,6 +34,11 @@ std::string str(int i) return buffer; } +static rx::D3DWorkaroundType DiscardWorkaround(bool usesDiscard) +{ + return (usesDiscard ? rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER : rx::ANGLE_D3D_WORKAROUND_NONE); +} + UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index) { @@ -1622,9 +1627,19 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) return false; } - int version = 0; - stream.read(&version); - if (version != VERSION_DWORD) + int majorVersion = 0; + int minorVersion = 0; + stream.read(&majorVersion); + stream.read(&minorVersion); + if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) + { + infoLog.append("Invalid program binary version."); + return false; + } + + unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; + stream.read(commitString, ANGLE_COMMIT_HASH_SIZE); + if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) { infoLog.append("Invalid program binary version."); return false; @@ -1791,7 +1806,9 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) BinaryOutputStream stream; stream.write(GL_PROGRAM_BINARY_ANGLE); - stream.write(VERSION_DWORD); + stream.write(ANGLE_MAJOR_VERSION); + stream.write(ANGLE_MINOR_VERSION); + stream.write(ANGLE_COMMIT_HASH, ANGLE_COMMIT_HASH_SIZE); stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL); for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) @@ -1962,13 +1979,13 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin if (success) { - mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX); - mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL); + mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, DiscardWorkaround(vertexShader->mUsesDiscardRewriting)); + mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, DiscardWorkaround(fragmentShader->mUsesDiscardRewriting)); if (usesGeometryShader()) { std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader); - mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY); + mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE); } if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) @@ -2587,7 +2604,9 @@ struct AttributeSorter bool operator()(int a, int b) { - return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b]; + if (originalIndices[a] == -1) return false; + if (originalIndices[b] == -1) return true; + return (originalIndices[a] < originalIndices[b]); } const int (&originalIndices)[MAX_VERTEX_ATTRIBS]; @@ -2615,7 +2634,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { int oldIndex = mAttributesByLayout[i]; - sortedSemanticIndices[i] = mSemanticIndex[oldIndex]; + sortedSemanticIndices[i] = oldIndex; attributes[i] = oldTranslatedAttributes[oldIndex]; } } diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp index 127513741c..98d33ec6c3 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp @@ -129,6 +129,11 @@ unsigned int RenderbufferTexture2D::getSerial() const return mTexture2D->getRenderTargetSerial(mTarget); } +unsigned int RenderbufferTexture2D::getTextureSerial() const +{ + return mTexture2D->getTextureSerial(); +} + ///// RenderbufferTextureCubeMap Implementation //////// RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target) @@ -193,6 +198,11 @@ unsigned int RenderbufferTextureCubeMap::getSerial() const return mTextureCubeMap->getRenderTargetSerial(mTarget); } +unsigned int RenderbufferTextureCubeMap::getTextureSerial() const +{ + return mTextureCubeMap->getTextureSerial(); +} + ////// Renderbuffer Implementation ////// Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *instance) : RefCountObject(id) @@ -292,6 +302,11 @@ unsigned int Renderbuffer::getSerial() const return mInstance->getSerial(); } +unsigned int Renderbuffer::getTextureSerial() const +{ + return mInstance->getTextureSerial(); +} + void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { ASSERT(newStorage != NULL); diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h index eca2f3a780..d46fd44557 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h @@ -60,6 +60,7 @@ class RenderbufferInterface GLuint getStencilSize() const; virtual unsigned int getSerial() const = 0; + virtual unsigned int getTextureSerial() const = 0; private: DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface); @@ -85,6 +86,7 @@ class RenderbufferTexture2D : public RenderbufferInterface virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; + virtual unsigned int getTextureSerial() const; private: DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture2D); @@ -113,6 +115,7 @@ class RenderbufferTextureCubeMap : public RenderbufferInterface virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; + virtual unsigned int getTextureSerial() const; private: DISALLOW_COPY_AND_ASSIGN(RenderbufferTextureCubeMap); @@ -141,6 +144,7 @@ class RenderbufferStorage : public RenderbufferInterface virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; + virtual unsigned int getTextureSerial() const { return 0; } static unsigned int issueSerial(); static unsigned int issueCubeSerials(); @@ -193,6 +197,7 @@ class Renderbuffer : public RefCountObject GLsizei getSamples() const; unsigned int getSerial() const; + unsigned int getTextureSerial() const; void setStorage(RenderbufferStorage *newStorage); diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index 7dfdd0ba3a..f6a2f03dfc 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -307,6 +307,7 @@ void Shader::parseVaryings() mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL; mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL; mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL; + mUsesDiscardRewriting = strstr(mHlsl, "ANGLE_USES_DISCARD_REWRITING") != NULL; } } @@ -340,6 +341,7 @@ void Shader::uncompile() mUsesPointCoord = false; mUsesDepthRange = false; mUsesFragDepth = false; + mUsesDiscardRewriting = false; mActiveUniforms.clear(); } diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index 2afe2976c3..2015addd11 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -18,7 +18,7 @@ #include #include -#include "compiler/Uniform.h" +#include "compiler/translator/Uniform.h" #include "common/angleutils.h" namespace rx @@ -107,6 +107,7 @@ class Shader bool mUsesPointCoord; bool mUsesDepthRange; bool mUsesFragDepth; + bool mUsesDiscardRewriting; static void *mFragmentCompiler; static void *mVertexCompiler; diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp index 72c0a8ab79..3257d05dd4 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -14,8 +14,8 @@ #include "libGLESv2/main.h" #include "libGLESv2/mathutil.h" #include "libGLESv2/utilities.h" -#ifndef ANGLE_ENABLE_D3D11 -# include "libGLESv2/renderer/Blit.h" +#if defined(ANGLE_ENABLE_D3D9) +# include "libGLESv2/renderer/d3d9/Blit.h" #else # define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN #endif @@ -1362,10 +1362,10 @@ void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size for (int level = 0; level < levels; level++) { + GLsizei mipSize = std::max(1, size >> level); for (int face = 0; face < 6; face++) { - mImageArray[face][level]->redefine(mRenderer, internalformat, size, size, true); - size = std::max(1, size >> 1); + mImageArray[face][level]->redefine(mRenderer, internalformat, mipSize, mipSize, true); } } diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 91719f8e6d..814dfbf965 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -758,7 +758,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, return gl::error(GL_INVALID_OPERATION); } - buffer->bufferData(data, size, usage, target); + buffer->bufferData(data, size, usage); } } catch(std::bad_alloc&) @@ -812,7 +812,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, return gl::error(GL_INVALID_VALUE); } - buffer->bufferSubData(data, size, offset, target); + buffer->bufferSubData(data, size, offset); } } catch(std::bad_alloc&) @@ -3844,9 +3844,9 @@ const GLubyte* __stdcall glGetString(GLenum name) case GL_RENDERER: return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE"); case GL_VERSION: - return (GLubyte*)"OpenGL ES 2.0 (ANGLE " VERSION_STRING ")"; + return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; case GL_SHADING_LANGUAGE_VERSION: - return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " VERSION_STRING ")"; + return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; case GL_EXTENSIONS: return (GLubyte*)((context != NULL) ? context->getExtensionString() : ""); default: @@ -4893,9 +4893,9 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp case GL_RGB565: case GL_RGB8_OES: case GL_RGBA8_OES: - case GL_BGRA8_EXT: case GL_STENCIL_INDEX8: case GL_DEPTH24_STENCIL8_OES: + case GL_BGRA8_EXT: context->setRenderbufferStorage(width, height, internalformat, samples); break; default: diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc b/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc index 0ad21e440e..76cd05566e 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc @@ -54,8 +54,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION - PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION + FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 + PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -71,13 +71,14 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library" - VALUE "FileVersion", VERSION_STRING + VALUE "FileVersion", ANGLE_VERSION_STRING VALUE "InternalName", "libGLESv2" VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." VALUE "OriginalFilename", "libGLESv2.dll" - VALUE "PrivateBuild", VERSION_STRING + VALUE "PrivateBuild", ANGLE_VERSION_STRING VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library" - VALUE "ProductVersion", VERSION_STRING + VALUE "ProductVersion", ANGLE_VERSION_STRING + VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE END END BLOCK "VarFileInfo" diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp index defdf35f77..95f4b8de1c 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp @@ -11,15 +11,60 @@ #include "libGLESv2/Context.h" -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - #if !defined(ANGLE_OS_WINRT) static DWORD currentTLS = TLS_OUT_OF_INDEXES; #else static __declspec(thread) void *currentTLS = 0; #endif -namespace gl { Current *getCurrent(); } +namespace gl +{ + +Current *AllocateCurrent() +{ +#if !defined(ANGLE_OS_WINRT) + Current *current = (Current*)LocalAlloc(LPTR, sizeof(Current)); +#else + currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current)); + Current *current = (Current*)currentTLS; +#endif + + if (!current) + { + ERR("Could not allocate thread local storage."); + return NULL; + } + +#if !defined(ANGLE_OS_WINRT) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + TlsSetValue(currentTLS, current); +#endif + + current->context = NULL; + current->display = NULL; + + return current; +} + +void DeallocateCurrent() +{ +#if !defined(ANGLE_OS_WINRT) + void *current = TlsGetValue(currentTLS); + + if (current) + { + LocalFree((HLOCAL)current); + } +#else + if (currentTLS) + { + HeapFree(GetProcessHeap(), 0, currentTLS); + currentTLS = 0; + } +#endif +} + +} extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { @@ -39,48 +84,19 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved // Fall throught to initialize index case DLL_THREAD_ATTACH: { - gl::Current *current = gl::getCurrent(); - - if (current) - { -#if !defined(ANGLE_OS_WINRT) - TlsSetValue(currentTLS, current); -#endif - current->context = NULL; - current->display = NULL; - } + gl::AllocateCurrent(); } break; case DLL_THREAD_DETACH: { - gl::Current *current = gl::getCurrent(); - - if (current) - { -#if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); -#else - HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); - currentTLS = 0; -#endif - } + gl::DeallocateCurrent(); } break; case DLL_PROCESS_DETACH: { - gl::Current *current = gl::getCurrent(); - - if (current) - { + gl::DeallocateCurrent(); #if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); - } - TlsFree(currentTLS); -#else - HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); - currentTLS = 0; - } #endif } break; @@ -91,33 +107,31 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved return TRUE; } -#endif // !QT_OPENGL_ES_2_ANGLE_STATIC - namespace gl { -Current *getCurrent() + +Current *GetCurrentData() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC #if !defined(ANGLE_OS_WINRT) Current *current = (Current*)TlsGetValue(currentTLS); - if (!current) - current = (Current*)LocalAlloc(LPTR, sizeof(Current)); - return current; #else - if (!currentTLS) - currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); - return (Current*)currentTLS; + Current *current = (Current*)currentTLS; #endif #else // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static gl::Current curr = { 0, 0 }; - return &curr; + static Current s_current = { 0, 0 }; + Current *current = &s_current; #endif + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. + return (current ? current : AllocateCurrent()); } void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) { - Current *current = getCurrent(); + Current *current = GetCurrentData(); current->context = context; current->display = display; @@ -130,7 +144,7 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) Context *getContext() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->context; } @@ -156,7 +170,7 @@ Context *getNonLostContext() egl::Display *getDisplay() { - Current *current = getCurrent(); + Current *current = GetCurrentData(); return current->display; } diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h index 196afaeab6..69465c9bbf 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ b/src/3rdparty/angle/src/libGLESv2/main.h @@ -10,7 +10,6 @@ #define LIBGLESV2_MAIN_H_ #include "common/debug.h" -#include "common/system.h" namespace egl { @@ -58,7 +57,7 @@ gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *rend void glDestroyContext(gl::Context *context); void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); gl::Context *glGetCurrentContext(); -rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId); +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId); void glDestroyRenderer(rx::Renderer *renderer); __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h index 083548669a..6474b66745 100644 --- a/src/3rdparty/angle/src/libGLESv2/mathutil.h +++ b/src/3rdparty/angle/src/libGLESv2/mathutil.h @@ -11,7 +11,6 @@ #include -#include "common/system.h" #include "common/debug.h" namespace gl diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h index 823d27bb60..2ff09f531e 100644 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.h +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h @@ -33,26 +33,53 @@ #include #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -#define ANGLE_OS_WINRT -#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -#define ANGLE_OS_WINPHONE -#endif +# define ANGLE_OS_WINRT +# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP +# define ANGLE_OS_WINPHONE +# endif #endif -#ifndef ANGLE_ENABLE_D3D11 -#include -#else -#if !defined(ANGLE_OS_WINRT) -#include -#else -#include -#define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) -#define GetVersion() WINVER +#if defined(ANGLE_ENABLE_D3D9) +# include #endif -#include +#if defined(ANGLE_ENABLE_D3D11) +# if !defined(ANGLE_OS_WINRT) +# include +# else +# include +# define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) +# define GetVersion() WINVER +# define LoadLibrary(x) LoadPackagedLibrary(x, NULL) +# endif +# include #endif -#ifndef ANGLE_OS_WINPHONE -#include +#if !defined(ANGLE_OS_WINPHONE) +# include +#endif + +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0 +#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14) +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL1 +#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0 +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL2 +#define D3DCOMPILE_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) +#endif +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3 +#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15) +#endif +#ifndef D3DCOMPILE_DEBUG +#define D3DCOMPILE_DEBUG (1 << 0) +#endif +#ifndef D3DCOMPILE_SKIP_OPTIMIZATION +#define D3DCOMPILE_SKIP_OPTIMIZATION (1 << 2) +#endif +#ifndef D3DCOMPILE_AVOID_FLOW_CONTROL +#define D3DCOMPILE_AVOID_FLOW_CONTROL (1 << 9) +#endif +#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL +#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10) #endif #ifdef _MSC_VER diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h index 14a8c2765b..ace1a11bae 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h @@ -22,7 +22,7 @@ class BufferStorage // The data returned is only guaranteed valid until next non-const method. virtual void *getData() = 0; - virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target) = 0; + virtual void setData(const void* data, unsigned int size, unsigned int offset) = 0; virtual void clear() = 0; virtual unsigned int getSize() const = 0; virtual bool supportsDirectBinding() const = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp deleted file mode 100644 index 2f694db061..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp +++ /dev/null @@ -1,361 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage11.cpp Defines the BufferStorage11 class. - -#include "libGLESv2/renderer/BufferStorage11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/Renderer11.h" - -namespace rx -{ - -BufferStorage11::BufferStorage11(Renderer11 *renderer) -{ - mRenderer = renderer; - - mStagingBuffer = NULL; - mStagingBufferSize = 0; - - mBuffer = NULL; - mBufferSize = 0; - - mSize = 0; - - mResolvedData = NULL; - mResolvedDataSize = 0; - mResolvedDataValid = false; - - mReadUsageCount = 0; - mWriteUsageCount = 0; -} - -BufferStorage11::~BufferStorage11() -{ - if (mStagingBuffer) - { - mStagingBuffer->Release(); - mStagingBuffer = NULL; - } - - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } - - if (mResolvedData) - { - free(mResolvedData); - mResolvedData = NULL; - } -} - -BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); - return static_cast(bufferStorage); -} - -void *BufferStorage11::getData() -{ - if (!mResolvedDataValid) - { - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - HRESULT result; - - if (!mStagingBuffer || mStagingBufferSize < mBufferSize) - { - if (mStagingBuffer) - { - mStagingBuffer->Release(); - mStagingBuffer = NULL; - mStagingBufferSize = 0; - } - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = mSize; - bufferDesc.Usage = D3D11_USAGE_STAGING; - bufferDesc.BindFlags = 0; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); - } - - mStagingBufferSize = bufferDesc.ByteWidth; - } - - if (!mResolvedData || mResolvedDataSize < mBufferSize) - { - free(mResolvedData); - mResolvedData = malloc(mSize); - mResolvedDataSize = mSize; - } - - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = mSize; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); - } - - memcpy(mResolvedData, mappedResource.pData, mSize); - - context->Unmap(mStagingBuffer, 0); - - mResolvedDataValid = true; - } - - mReadUsageCount = 0; - - return mResolvedData; -} - -void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset, unsigned int target) -{ - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - HRESULT result; - - unsigned int requiredBufferSize = size + offset; - unsigned int requiredStagingSize = size; - bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset); - - if (!directInitialization) - { - if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize) - { - if (mStagingBuffer) - { - mStagingBuffer->Release(); - mStagingBuffer = NULL; - mStagingBufferSize = 0; - } - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = size; - bufferDesc.Usage = D3D11_USAGE_STAGING; - bufferDesc.BindFlags = 0; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - if (data) - { - D3D11_SUBRESOURCE_DATA initialData; - initialData.pSysMem = data; - initialData.SysMemPitch = size; - initialData.SysMemSlicePitch = 0; - - result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer); - } - else - { - result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); - } - - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - mStagingBufferSize = size; - } - else if (data) - { - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - memcpy(mappedResource.pData, data, size); - - context->Unmap(mStagingBuffer, 0); - } - } - - if (!mBuffer || mBufferSize < size + offset) - { - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = requiredBufferSize; - bufferDesc.Usage = D3D11_USAGE_DEFAULT; - if (mRenderer->getFeatureLevel() > D3D_FEATURE_LEVEL_9_3) - bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER; - else - bufferDesc.BindFlags = target == GL_ARRAY_BUFFER ? D3D11_BIND_VERTEX_BUFFER : D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = 0; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - if (directInitialization) - { - // Since the data will fill the entire buffer (being larger than the initial size and having - // no offset), the buffer can be initialized with the data so no staging buffer is required - - // No longer need the old buffer - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - mBufferSize = 0; - } - - if (data) - { - D3D11_SUBRESOURCE_DATA initialData; - initialData.pSysMem = data; - initialData.SysMemPitch = size; - initialData.SysMemSlicePitch = 0; - - result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer); - } - else - { - result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); - } - - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - else if (mBuffer && offset > 0) - { - // If offset is greater than zero and the buffer is non-null, need to preserve the data from - // the old buffer up to offset - ID3D11Buffer *newBuffer = NULL; - - result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = std::min(offset, mBufferSize); - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); - - mBuffer->Release(); - mBuffer = newBuffer; - } - else - { - // Simple case, nothing needs to be copied from the old buffer to the new one, just create - // a new buffer - - // No longer need the old buffer - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - mBufferSize = 0; - } - - // Create a new buffer for data storage - result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - updateSerial(); - mBufferSize = bufferDesc.ByteWidth; - } - - if (!directInitialization) - { - ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize); - - // Data is already put into the staging buffer, copy it over to the data buffer - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = size; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox); - } - - mSize = std::max(mSize, offset + size); - - mWriteUsageCount = 0; - - mResolvedDataValid = false; -} - -void BufferStorage11::clear() -{ - mResolvedDataValid = false; - mSize = 0; -} - -unsigned int BufferStorage11::getSize() const -{ - return mSize; -} - -bool BufferStorage11::supportsDirectBinding() const -{ - return mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0; -} - -void BufferStorage11::markBufferUsage() -{ - mReadUsageCount++; - mWriteUsageCount++; - - static const unsigned int usageLimit = 5; - - if (mReadUsageCount > usageLimit && mResolvedData) - { - free(mResolvedData); - mResolvedData = NULL; - mResolvedDataSize = 0; - mResolvedDataValid = false; - } - - if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer) - { - mStagingBuffer->Release(); - mStagingBuffer = NULL; - mStagingBufferSize = 0; - } -} - -ID3D11Buffer *BufferStorage11::getBuffer() const -{ - return mBuffer; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h deleted file mode 100644 index c9489627c3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage11.h Defines the BufferStorage11 class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ -class Renderer11; - -class BufferStorage11 : public BufferStorage -{ - public: - explicit BufferStorage11(Renderer11 *renderer); - virtual ~BufferStorage11(); - - static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage); - - virtual void *getData(); - virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; - virtual void markBufferUsage(); - - ID3D11Buffer *getBuffer() const; - - private: - Renderer11 *mRenderer; - - ID3D11Buffer *mStagingBuffer; - unsigned int mStagingBufferSize; - - ID3D11Buffer *mBuffer; - unsigned int mBufferSize; - - unsigned int mSize; - - void *mResolvedData; - unsigned int mResolvedDataSize; - bool mResolvedDataValid; - - unsigned int mReadUsageCount; - unsigned int mWriteUsageCount; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp index 39fd0f41f0..5278113811 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -11,35 +11,26 @@ #include "libGLESv2/main.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" -#ifndef ANGLE_ENABLE_D3D11 -#include "libGLESv2/renderer/Renderer9.h" -#else -#include "libGLESv2/renderer/Renderer11.h" +#if defined(ANGLE_ENABLE_D3D9) +# include "libGLESv2/renderer/d3d9/Renderer9.h" +#endif +#if defined(ANGLE_ENABLE_D3D11) +# include "libGLESv2/renderer/d3d11/Renderer11.h" #endif #include "libGLESv2/utilities.h" #include "third_party/trace_event/trace_event.h" -#if !defined(ANGLE_ENABLE_D3D11) -// Enables use of the Direct3D 11 API for a default display, when available -#define ANGLE_ENABLE_D3D11 0 -#endif - #ifndef D3DERR_OUTOFVIDEOMEMORY #define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) #endif -#ifndef D3DCOMPILER_DLL -#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" // Lowest common denominator -#endif - -#ifndef QT_D3DCOMPILER_DLL -#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL -#endif - #if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) -//Add define + typedefs for older MinGW-w64 headers (pre 5783) -//Also define these on Windows Phone, which doesn't have a shader compiler +#ifndef D3DCOMPILER_DLL + +// Add define + typedefs for older MinGW-w64 headers (pre 5783) + +#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, @@ -48,8 +39,14 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); +#endif // D3DCOMPILER_DLL + #endif // __MINGW32__ || ANGLE_OS_WINPHONE +#ifndef QT_D3DCOMPILER_DLL +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#endif + namespace rx { @@ -82,7 +79,8 @@ bool Renderer::initializeCompiler() break; } } -#else +#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL #if !defined(ANGLE_OS_WINRT) const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); @@ -109,15 +107,11 @@ bool Renderer::initializeCompiler() // Load the first available known compiler DLL for (int i = 0; compilerDlls[i]; ++i) { -#if !defined(ANGLE_OS_WINRT) + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. mD3dCompilerModule = LoadLibrary(compilerDlls[i]); -#else - mD3dCompilerModule = LoadPackagedLibrary(compilerDlls[i], NULL); -#endif if (mD3dCompilerModule) break; } -#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES if (!mD3dCompilerModule) { @@ -230,18 +224,46 @@ ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, co extern "C" { -rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId) +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId) { rx::Renderer *renderer = NULL; EGLint status = EGL_BAD_ALLOC; -#if ANGLE_ENABLE_D3D11 - renderer = new rx::Renderer11(display, hDc); -#else - bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); - renderer = new rx::Renderer9(display, hDc, softwareDevice); +#if defined(ANGLE_OS_WINRT) + if (displayId == EGL_DEFAULT_DISPLAY) + displayId = EGL_D3D11_ONLY_DISPLAY_ANGLE; #endif +#if defined(ANGLE_ENABLE_D3D11) + if (displayId == EGL_DEFAULT_DISPLAY || + displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + renderer = new rx::Renderer11(display); + + if (renderer) + { + status = renderer->initialize(); + } + + if (status == EGL_SUCCESS) + { + return renderer; + } + else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + return NULL; + } + + // Failed to create a D3D11 renderer, try creating a D3D9 renderer + delete renderer; + } +#endif // ANGLE_ENABLE_D3D11 + +#if defined(ANGLE_ENABLE_D3D9) + bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); + renderer = new rx::Renderer9(display, displayId, softwareDevice); + if (renderer) { status = renderer->initialize(); @@ -251,6 +273,7 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayT { return renderer; } +#endif // ANGLE_ENABLE_D3D9 return NULL; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h index ac67c27e71..79578b2458 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -14,30 +14,6 @@ #include "libGLESv2/Uniform.h" #include "libGLESv2/angletypes.h" -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0 -#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14) -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL1 -#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0 -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL2 -#define D3DCOMPILE_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3 -#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15) -#endif -#ifndef D3DCOMPILE_DEBUG -#define D3DCOMPILE_DEBUG (1 << 0) -#endif -#ifndef D3DCOMPILE_SKIP_OPTIMIZATION -#define D3DCOMPILE_SKIP_OPTIMIZATION (1 << 2) -#endif -#ifndef D3DCOMPILE_AVOID_FLOW_CONTROL -#define D3DCOMPILE_AVOID_FLOW_CONTROL (1 << 9) -#endif -#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL -#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10) -#endif #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 #endif @@ -118,6 +94,12 @@ enum ShaderType SHADER_GEOMETRY }; +enum D3DWorkaroundType +{ + ANGLE_D3D_WORKAROUND_NONE, + ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER +}; + class Renderer { public: @@ -138,7 +120,7 @@ class Renderer virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; virtual void setRasterizerState(const gl::RasterizerState &rasterState) = 0; - virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) = 0; virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW) = 0; @@ -232,7 +214,7 @@ class Renderer // Shader operations virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0; - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) = 0; + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) = 0; // Image operations virtual Image *createImage() = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h index a6870ebedc..8231fbcb25 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h @@ -1,3 +1,4 @@ +#include "../precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -12,6 +13,10 @@ #include "common/angleutils.h" +#if !defined(ANGLE_FORCE_VSYNC_OFF) +#define ANGLE_FORCE_VSYNC_OFF 0 +#endif + namespace rx { @@ -33,7 +38,7 @@ class SwapChain virtual HANDLE getShareHandle() {return mShareHandle;}; protected: - const EGLNativeWindowType mWindow; // Window that the surface is created for. + const EGLNativeWindowType mWindow; // Window that the surface is created for. const GLenum mBackBufferFormat; const GLenum mDepthBufferFormat; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp index 7ff5171fca..8034aed8c9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp @@ -266,6 +266,10 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], return GL_OUT_OF_MEMORY; } + mCurrentValue[i][0] = attribs[i].mCurrentValue[0]; + mCurrentValue[i][1] = attribs[i].mCurrentValue[1]; + mCurrentValue[i][2] = attribs[i].mCurrentValue[2]; + mCurrentValue[i][3] = attribs[i].mCurrentValue[3]; mCurrentValueOffsets[i] = streamOffset; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp new file mode 100644 index 0000000000..31d5b8b886 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp @@ -0,0 +1,366 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage11.cpp Defines the BufferStorage11 class. + +#include "libGLESv2/renderer/d3d11/BufferStorage11.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" + +namespace rx +{ + +BufferStorage11::BufferStorage11(Renderer11 *renderer) +{ + mRenderer = renderer; + + mStagingBuffer = NULL; + mStagingBufferSize = 0; + + mSize = 0; + + mResolvedData = NULL; + mResolvedDataSize = 0; + mResolvedDataValid = false; + + mReadUsageCount = 0; + mWriteUsageCount = 0; +} + +BufferStorage11::~BufferStorage11() +{ + SafeRelease(mStagingBuffer); + + if (mResolvedData) + { + free(mResolvedData); + mResolvedData = NULL; + } + + for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++) + { + SafeDelete(it->second); + } +} + +BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) +{ + ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); + return static_cast(bufferStorage); +} + +void *BufferStorage11::getData() +{ + ASSERT(mStagingBuffer); + + if (!mResolvedDataValid) + { + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + HRESULT result; + + if (!mResolvedData || mResolvedDataSize < mStagingBufferSize) + { + free(mResolvedData); + mResolvedData = malloc(mSize); + mResolvedDataSize = mSize; + } + + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } + + memcpy(mResolvedData, mappedResource.pData, mSize); + + context->Unmap(mStagingBuffer, 0); + + mResolvedDataValid = true; + } + + mReadUsageCount = 0; + + return mResolvedData; +} + +void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + HRESULT result; + + const unsigned int requiredStagingBufferSize = size + offset; + const bool createStagingBuffer = !mStagingBuffer || mStagingBufferSize < requiredStagingBufferSize; + + if (createStagingBuffer) + { + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = requiredStagingBufferSize; + bufferDesc.Usage = D3D11_USAGE_STAGING; + bufferDesc.BindFlags = 0; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result; + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ID3D11Buffer *newStagingBuffer; + + if (data && offset == 0) + { + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = data; + initialData.SysMemPitch = requiredStagingBufferSize; + initialData.SysMemSlicePitch = 0; + + result = device->CreateBuffer(&bufferDesc, &initialData, &newStagingBuffer); + } + else + { + result = device->CreateBuffer(&bufferDesc, NULL, &newStagingBuffer); + } + + if (FAILED(result)) + { + mStagingBufferSize = 0; + return gl::error(GL_OUT_OF_MEMORY); + } + + mStagingBufferSize = requiredStagingBufferSize; + + if (mStagingBuffer && offset > 0) + { + // If offset is greater than zero and the buffer is non-null, need to preserve the data from + // the old buffer up to offset + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = std::min(offset, requiredStagingBufferSize); + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(newStagingBuffer, 0, 0, 0, 0, mStagingBuffer, 0, &srcBox); + } + + SafeRelease(mStagingBuffer); + mStagingBuffer = newStagingBuffer; + } + + if (data && (offset != 0 || !createStagingBuffer)) + { + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + + unsigned char *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; + memcpy(offsetBufferPointer, data, size); + + context->Unmap(mStagingBuffer, 0); + } + + for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++) + { + it->second->markDirty(); + } + + mSize = std::max(mSize, requiredStagingBufferSize); + mWriteUsageCount = 0; + + mResolvedDataValid = false; +} + +void BufferStorage11::copyData(BufferStorage* sourceStorage, unsigned int size, + unsigned int sourceOffset, unsigned int destOffset) +{ + BufferStorage11* source = makeBufferStorage11(sourceStorage); + if (source) + { + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_BOX srcBox; + srcBox.left = sourceOffset; + srcBox.right = sourceOffset + size; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + ASSERT(mStagingBuffer && source->mStagingBuffer); + context->CopySubresourceRegion(mStagingBuffer, 0, destOffset, 0, 0, source->mStagingBuffer, 0, &srcBox); + } +} + +void BufferStorage11::clear() +{ + mResolvedDataValid = false; + mSize = 0; +} + +unsigned int BufferStorage11::getSize() const +{ + return mSize; +} + +bool BufferStorage11::supportsDirectBinding() const +{ + return true; +} + +void BufferStorage11::markBufferUsage() +{ + mReadUsageCount++; + mWriteUsageCount++; + + const unsigned int usageLimit = 5; + + if (mReadUsageCount > usageLimit && mResolvedData) + { + free(mResolvedData); + mResolvedData = NULL; + mResolvedDataSize = 0; + mResolvedDataValid = false; + } +} + +ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage) +{ + markBufferUsage(); + + DirectBufferStorage11 *directBuffer = NULL; + + auto directBufferIt = mDirectBuffers.find(usage); + if (directBufferIt != mDirectBuffers.end()) + { + directBuffer = directBufferIt->second; + } + + if (directBuffer) + { + if (directBuffer->isDirty()) + { + // if updateFromStagingBuffer returns true, the D3D buffer has been recreated + // and we should update our serial + if (directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0)) + { + updateSerial(); + } + } + } + else + { + // buffer is not allocated, create it + directBuffer = new DirectBufferStorage11(mRenderer, usage); + directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0); + + mDirectBuffers.insert(std::make_pair(usage, directBuffer)); + updateSerial(); + } + + return directBuffer->getD3DBuffer(); +} + +DirectBufferStorage11::DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage) + : mRenderer(renderer), + mUsage(usage), + mDirectBuffer(NULL), + mBufferSize(0), + mDirty(false) +{ +} + +DirectBufferStorage11::~DirectBufferStorage11() +{ + SafeRelease(mDirectBuffer); +} + +BufferUsage DirectBufferStorage11::getUsage() const +{ + return mUsage; +} + +// Returns true if it recreates the direct buffer +bool DirectBufferStorage11::updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + // unused for now + ASSERT(offset == 0); + + unsigned int requiredBufferSize = size + offset; + bool createBuffer = !mDirectBuffer || mBufferSize < requiredBufferSize; + + // (Re)initialize D3D buffer if needed + if (createBuffer) + { + D3D11_BUFFER_DESC bufferDesc; + fillBufferDesc(&bufferDesc, mRenderer, mUsage, requiredBufferSize); + + ID3D11Buffer *newBuffer; + HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); + + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, false); + } + + // No longer need the old buffer + SafeRelease(mDirectBuffer); + mDirectBuffer = newBuffer; + + mBufferSize = bufferDesc.ByteWidth; + } + + // Copy data via staging buffer + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = size; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(mDirectBuffer, 0, offset, 0, 0, stagingBuffer, 0, &srcBox); + + mDirty = false; + + return createBuffer; +} + +void DirectBufferStorage11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize) +{ + bufferDesc->ByteWidth = bufferSize; + bufferDesc->MiscFlags = 0; + bufferDesc->StructureByteStride = 0; + + switch (usage) + { + case BUFFER_USAGE_VERTEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_INDEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + default: + UNREACHABLE(); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h new file mode 100644 index 0000000000..a6afafe1b4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h @@ -0,0 +1,92 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferStorage11.h Defines the BufferStorage11 class. + +#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ +#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ + +#include "libGLESv2/renderer/BufferStorage.h" + +namespace rx +{ +class Renderer; +class Renderer11; +class DirectBufferStorage11; + +enum BufferUsage +{ + BUFFER_USAGE_VERTEX, + BUFFER_USAGE_INDEX, +}; + +class BufferStorage11 : public BufferStorage +{ + public: + explicit BufferStorage11(Renderer11 *renderer); + virtual ~BufferStorage11(); + + static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage); + + virtual void *getData(); + virtual void setData(const void* data, unsigned int size, unsigned int offset); + virtual void copyData(BufferStorage* sourceStorage, unsigned int size, + unsigned int sourceOffset, unsigned int destOffset); + virtual void clear(); + virtual unsigned int getSize() const; + virtual bool supportsDirectBinding() const; + + ID3D11Buffer *getBuffer(BufferUsage usage); + + private: + Renderer11 *mRenderer; + + ID3D11Buffer *mStagingBuffer; + unsigned int mStagingBufferSize; + + std::map mDirectBuffers; + + unsigned int mSize; + + void *mResolvedData; + unsigned int mResolvedDataSize; + bool mResolvedDataValid; + + unsigned int mReadUsageCount; + unsigned int mWriteUsageCount; + + void markBufferUsage(); +}; + +// Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points +// - vertex buffers +// - index buffers +class DirectBufferStorage11 +{ + public: + DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage); + ~DirectBufferStorage11(); + + BufferUsage getUsage() const; + bool updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset); + + ID3D11Buffer *getD3DBuffer() { return mDirectBuffer; } + bool isDirty() const { return mDirty; } + void markDirty() { mDirty = true; } + + private: + Renderer11 *mRenderer; + const BufferUsage mUsage; + ID3D11Buffer *mDirectBuffer; + size_t mBufferSize; + bool mDirty; + + static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize); +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp similarity index 96% rename from src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp index 9d11c9a0fc..2a7d4d43ef 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp @@ -7,9 +7,9 @@ // Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. -#include "libGLESv2/renderer/Fence11.h" +#include "libGLESv2/renderer/d3d11/Fence11.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/Fence11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp similarity index 89% rename from src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp index 81e9e9ecb2..5d039a35e8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp @@ -8,15 +8,15 @@ // Image11.h: Implements the rx::Image11 class, which acts as the interface to // the actual underlying resources of a Texture -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/renderer/Image11.h" -#include "libGLESv2/renderer/TextureStorage11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d11/TextureStorage11.h" #include "libGLESv2/Framebuffer.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/main.h" #include "libGLESv2/utilities.h" -#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" #include "libGLESv2/renderer/generatemip.h" namespace rx @@ -106,9 +106,15 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src) dest->markDirty(); } +static bool FormatRequiresInitialization(DXGI_FORMAT dxgiFormat, GLenum internalFormat) +{ + return (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(internalFormat) == 0) || + (dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(internalFormat) == 0); +} + bool Image11::isDirty() const { - return (mStagingTexture && mDirty); + return ((mStagingTexture || FormatRequiresInitialization(mDXGIFormat, mInternalFormat)) && mDirty); } bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) @@ -374,6 +380,27 @@ unsigned int Image11::getStagingSubresource() return mStagingSubresource; } +template +static void setDefaultData(ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, UINT subresource, + GLsizei width, GLsizei height, const T (&defaultData)[N]) +{ + D3D11_MAPPED_SUBRESOURCE map; + deviceContext->Map(texture, subresource, D3D11_MAP_WRITE, 0, &map); + + unsigned char* ptr = reinterpret_cast(map.pData); + size_t pixelSize = sizeof(T) * N; + + for (GLsizei y = 0; y < height; y++) + { + for (GLsizei x = 0; x < width; x++) + { + memcpy(ptr + (y * map.RowPitch) + (x * pixelSize), defaultData, pixelSize); + } + } + + deviceContext->Unmap(texture, subresource); +} + void Image11::createStagingTexture() { if (mStagingTexture) @@ -421,6 +448,17 @@ void Image11::createStagingTexture() mStagingTexture = newTexture; mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); mDirty = false; + + if (mDXGIFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(mInternalFormat) == 0) + { + unsigned char defaultPixel[4] = { 0, 0, 0, 255 }; + setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel); + } + else if (mDXGIFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(mInternalFormat) == 0) + { + float defaultPixel[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel); + } } HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/Image11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp similarity index 95% rename from src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp index 36a62adc1c..44f9976d43 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp @@ -7,8 +7,8 @@ // IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. -#include "libGLESv2/renderer/IndexBuffer11.h" -#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" namespace rx { @@ -170,7 +170,7 @@ DXGI_FORMAT IndexBuffer11::getIndexFormat() const { case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT; case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT; - case GL_UNSIGNED_INT: return mRenderer->get32BitIndexSupport() ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT; default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; } } @@ -180,4 +180,4 @@ ID3D11Buffer *IndexBuffer11::getBuffer() const return mBuffer; } -} +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp similarity index 94% rename from src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp index 1552f3a326..4940b8c638 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp @@ -8,10 +8,10 @@ // InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches // D3D11 input layouts. -#include "libGLESv2/renderer/InputLayoutCache.h" -#include "libGLESv2/renderer/VertexBuffer11.h" -#include "libGLESv2/renderer/BufferStorage11.h" -#include "libGLESv2/renderer/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d11/BufferStorage11.h" +#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Context.h" #include "libGLESv2/renderer/VertexDataManager.h" @@ -103,10 +103,10 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M // Record the type of the associated vertex shader vector in our key // This will prevent mismatched vertex shaders from using the same input layout GLint attributeSize; - programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); + programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; - ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i]; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT; ilKey.elements[ilKey.elementCount].desc.InputSlot = i; ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; @@ -114,7 +114,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; ilKey.elementCount++; - vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer(); + vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX) : vertexBuffer->getBuffer(); vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial(); vertexStrides[i] = attributes[i].stride; vertexOffsets[i] = attributes[i].offset; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp similarity index 96% rename from src/3rdparty/angle/src/libGLESv2/renderer/Query11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp index 13210fc929..24c0330a1e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Query11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp @@ -7,8 +7,8 @@ // Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. -#include "libGLESv2/renderer/Query11.h" -#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" #include "libGLESv2/main.h" namespace rx diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/Query11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp similarity index 88% rename from src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp index fd388dfe08..a1c324cd80 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp @@ -8,9 +8,12 @@ // RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render // state objects. -#include "libGLESv2/renderer/RenderStateCache.h" -#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/utilities.h" #include "common/debug.h" #include "third_party/murmurhash/MurmurHash3.h" @@ -71,21 +74,21 @@ void RenderStateCache::clear() mSamplerStateCache.clear(); } -std::size_t RenderStateCache::hashBlendState(const gl::BlendState &blendState) +std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) { static const unsigned int seed = 0xABCDEF98; std::size_t hash = 0; - MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash); + MurmurHash3_x86_32(&blendState, sizeof(BlendStateKey), seed, &hash); return hash; } -bool RenderStateCache::compareBlendStates(const gl::BlendState &a, const gl::BlendState &b) +bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b) { return memcmp(&a, &b, sizeof(gl::BlendState)) == 0; } -ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendState) +ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState) { if (!mDevice) { @@ -93,7 +96,36 @@ ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendSta return NULL; } - BlendStateMap::iterator i = mBlendStateCache.find(blendState); + bool mrt = false; + + BlendStateKey key = { 0 }; + key.blendState = blendState; + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + gl::Renderbuffer *renderBuffer = framebuffer->getColorbuffer(i); + if (renderBuffer) + { + if (i > 0) + { + mrt = true; + } + + GLenum internalFormat = renderBuffer->getInternalFormat(); + key.rtChannels[i][0] = gl::GetRedSize(internalFormat) > 0; + key.rtChannels[i][1] = gl::GetGreenSize(internalFormat) > 0; + key.rtChannels[i][2] = gl::GetBlueSize(internalFormat) > 0;; + key.rtChannels[i][3] = gl::GetAlphaSize(internalFormat) > 0; + } + else + { + key.rtChannels[i][0] = false; + key.rtChannels[i][1] = false; + key.rtChannels[i][2] = false; + key.rtChannels[i][3] = false; + } + } + + BlendStateMap::iterator i = mBlendStateCache.find(key); if (i != mBlendStateCache.end()) { BlendStateCounterPair &state = i->second; @@ -122,7 +154,7 @@ ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendSta // Create a new blend state and insert it into the cache D3D11_BLEND_DESC blendDesc = { 0 }; blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; - blendDesc.IndependentBlendEnable = FALSE; + blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { @@ -140,10 +172,10 @@ ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendSta rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); } - rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendState.colorMaskRed, - blendState.colorMaskGreen, - blendState.colorMaskBlue, - blendState.colorMaskAlpha); + rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, + key.rtChannels[i][1] && blendState.colorMaskGreen, + key.rtChannels[i][2] && blendState.colorMaskBlue, + key.rtChannels[i][3] && blendState.colorMaskAlpha); } ID3D11BlendState *dx11BlendState = NULL; @@ -154,7 +186,7 @@ ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendSta return NULL; } - mBlendStateCache.insert(std::make_pair(blendState, std::make_pair(dx11BlendState, mCounter++))); + mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); return dx11BlendState; } @@ -404,4 +436,4 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa } } -} \ No newline at end of file +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h similarity index 83% rename from src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h index f8b5111de4..b4b871a4bd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h @@ -13,6 +13,11 @@ #include "libGLESv2/angletypes.h" #include "common/angleutils.h" +namespace gl +{ +class Framebuffer; +} + namespace rx { @@ -26,7 +31,7 @@ class RenderStateCache void clear(); // Increments refcount on the returned blend state, Release() must be called. - ID3D11BlendState *getBlendState(const gl::BlendState &blendState); + ID3D11BlendState *getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState); ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, unsigned int depthSize); ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState); @@ -38,14 +43,19 @@ class RenderStateCache unsigned long long mCounter; // Blend state cache - static std::size_t hashBlendState(const gl::BlendState &blendState); - static bool compareBlendStates(const gl::BlendState &a, const gl::BlendState &b); + struct BlendStateKey + { + gl::BlendState blendState; + bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + static std::size_t hashBlendState(const BlendStateKey &blendState); + static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b); static const unsigned int kMaxBlendStates; - typedef std::size_t (*BlendStateHashFunction)(const gl::BlendState &); - typedef bool (*BlendStateEqualityFunction)(const gl::BlendState &, const gl::BlendState &); + typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); + typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); typedef std::pair BlendStateCounterPair; - typedef std::unordered_map BlendStateMap; + typedef std::unordered_map BlendStateMap; BlendStateMap mBlendStateCache; // Rasterizer state cache diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp similarity index 98% rename from src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp index 2667cc6fa7..3707097aa4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp @@ -8,10 +8,10 @@ // RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers // retained by Renderbuffers. -#include "libGLESv2/renderer/RenderTarget11.h" -#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" #include "libGLESv2/main.h" namespace rx diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp similarity index 94% rename from src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp index f83e9e91ce..31d976dec4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp @@ -12,31 +12,31 @@ #include "libGLESv2/Buffer.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/RenderBuffer.h" -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/renderer/RenderTarget11.h" -#include "libGLESv2/renderer/renderer11_utils.h" -#include "libGLESv2/renderer/ShaderExecutable11.h" -#include "libGLESv2/renderer/SwapChain11.h" -#include "libGLESv2/renderer/Image11.h" -#include "libGLESv2/renderer/VertexBuffer11.h" -#include "libGLESv2/renderer/IndexBuffer11.h" -#include "libGLESv2/renderer/BufferStorage11.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d11/BufferStorage11.h" #include "libGLESv2/renderer/VertexDataManager.h" #include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/TextureStorage11.h" -#include "libGLESv2/renderer/Query11.h" -#include "libGLESv2/renderer/Fence11.h" +#include "libGLESv2/renderer/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d11/Fence11.h" -#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughrgb11ps.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughlum11ps.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h" -#include "libGLESv2/renderer/shaders/compiled/clear11vs.h" -#include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h" -#include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h" #include "libEGL/Display.h" @@ -66,7 +66,7 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 }; -Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc) +Renderer11::Renderer11(egl::Display *display) : Renderer(display) { mVertexDataManager = NULL; mIndexDataManager = NULL; @@ -147,6 +147,7 @@ EGLint Renderer11::initialize() return EGL_NOT_INITIALIZED; } + // create the D3D11 device ASSERT(mDevice == NULL); PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); @@ -160,13 +161,14 @@ EGLint Renderer11::initialize() D3D_FEATURE_LEVEL featureLevels[] = { - D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, +#if !defined(ANGLE_ENABLE_D3D9) D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, +#endif }; HRESULT result = S_OK; @@ -253,8 +255,6 @@ EGLint Renderer11::initialize() { D3D11_MESSAGE_ID hideMessages[] = { - D3D11_MESSAGE_ID_DEVICE_OMSETRENDERTARGETS_HAZARD, - D3D11_MESSAGE_ID_DEVICE_PSSETSHADERRESOURCES_HAZARD, D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET }; @@ -670,7 +670,7 @@ void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) mForceSetRasterState = false; } -void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, +void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) { if (mForceSetBlendState || @@ -678,7 +678,7 @@ void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 || sampleMask != mCurSampleMask) { - ID3D11BlendState *dxBlendState = mStateCache.getBlendState(blendState); + ID3D11BlendState *dxBlendState = mStateCache.getBlendState(framebuffer, blendState); if (!dxBlendState) { ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " @@ -929,6 +929,25 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) renderTargetFormat = colorbuffer->getActualFormat(); missingColorRenderTarget = false; } + +#ifdef _DEBUG + // Workaround for Debug SETSHADERRESOURCES_HAZARD D3D11 warnings + for (unsigned int vertexSerialIndex = 0; vertexSerialIndex < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; vertexSerialIndex++) + { + if (colorbuffer->getTextureSerial() != 0 && mCurVertexTextureSerials[vertexSerialIndex] == colorbuffer->getTextureSerial()) + { + setTexture(gl::SAMPLER_VERTEX, vertexSerialIndex, NULL); + } + } + + for (unsigned int pixelSerialIndex = 0; pixelSerialIndex < gl::MAX_TEXTURE_IMAGE_UNITS; pixelSerialIndex++) + { + if (colorbuffer->getTextureSerial() != 0 && mCurPixelTextureSerials[pixelSerialIndex] == colorbuffer->getTextureSerial()) + { + setTexture(gl::SAMPLER_PIXEL, pixelSerialIndex, NULL); + } + } +#endif } } @@ -1056,7 +1075,7 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); - mDeviceContext->IASetIndexBuffer(storage->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); + mDeviceContext->IASetIndexBuffer(storage->getBuffer(BUFFER_USAGE_INDEX), indexBuffer->getIndexFormat(), indexInfo->startOffset); mAppliedIBSerial = 0; mAppliedStorageIBSerial = storage->getSerial(); @@ -1118,43 +1137,6 @@ void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLv } } -template -static void drawLineLoopIndexed(T *data, GLenum type, const GLvoid *indices, GLsizei count) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } -} - void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) { // Get the raw indices for an indexed draw @@ -1203,13 +1185,42 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, return gl::error(GL_OUT_OF_MEMORY); } - if (get32BitIndexSupport()) - drawLineLoopIndexed(reinterpret_cast(mappedMemory), type, indices, count); - else - drawLineLoopIndexed(reinterpret_cast(mappedMemory), type, indices, count); - + unsigned int *data = reinterpret_cast(mappedMemory); unsigned int indexBufferOffset = offset; + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + if (!mLineLoopIB->unmapBuffer()) { ERR("Could not unmap index buffer for GL_LINE_LOOP."); @@ -1229,47 +1240,6 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); } -template -static void drawTriangleFanIndexed(T *data, GLenum type, const GLvoid *indices, unsigned int numTris) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = 0; - data[i*3 + 1] = i + 1; - data[i*3 + 2] = i + 2; - } - break; - case GL_UNSIGNED_BYTE: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_SHORT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_INT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - default: UNREACHABLE(); - } -} - void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) { // Get the raw indices for an indexed draw @@ -1320,13 +1290,46 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic return gl::error(GL_OUT_OF_MEMORY); } - if (get32BitIndexSupport()) - drawTriangleFanIndexed(reinterpret_cast(mappedMemory), type, indices, numTris); - else - drawTriangleFanIndexed(reinterpret_cast(mappedMemory), type, indices, numTris); - + unsigned int *data = reinterpret_cast(mappedMemory); unsigned int indexBufferOffset = offset; + switch (type) + { + case GL_NONE: // Non-indexed draw + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = 0; + data[i*3 + 1] = i + 1; + data[i*3 + 2] = i + 2; + } + break; + case GL_UNSIGNED_BYTE: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_SHORT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_INT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + default: UNREACHABLE(); + } + if (!mTriangleFanIB->unmapBuffer()) { ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); @@ -1544,10 +1547,14 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) { - bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; + gl::Renderbuffer *firstRenderbuffer = frameBuffer->getFirstColorbuffer(); + GLenum internalFormat = firstRenderbuffer ? firstRenderbuffer->getInternalFormat() : GL_NONE; + bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && - !(clearParams.colorMaskRed && clearParams.colorMaskGreen && - clearParams.colorMaskBlue && alphaUnmasked); + ((!clearParams.colorMaskRed && gl::GetRedSize(internalFormat) > 0) || + (!clearParams.colorMaskGreen && gl::GetGreenSize(internalFormat) > 0) || + (!clearParams.colorMaskBlue && gl::GetBlueSize(internalFormat) > 0) || + (!clearParams.colorMaskAlpha && gl::GetAlphaSize(internalFormat) > 0)); unsigned int stencilUnmasked = 0x0; if (frameBuffer->hasStencil()) @@ -1564,7 +1571,7 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer * if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear) { - maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers()); + maskedClear(clearParams, frameBuffer); } else { @@ -1591,10 +1598,12 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer * return; } - const float clearValues[4] = { clearParams.colorClearValue.red, - clearParams.colorClearValue.green, - clearParams.colorClearValue.blue, - clearParams.colorClearValue.alpha }; + GLenum format = renderbufferObject->getInternalFormat(); + + const float clearValues[4] = { (gl::GetRedSize(format) > 0) ? clearParams.colorClearValue.red : 0.0f, + (gl::GetGreenSize(format) > 0) ? clearParams.colorClearValue.green : 0.0f, + (gl::GetBlueSize(format) > 0) ? clearParams.colorClearValue.blue : 0.0f, + (gl::GetAlphaSize(format) > 0) ? clearParams.colorClearValue.alpha : 1.0f }; mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues); } } @@ -1638,7 +1647,7 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer * } } -void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers) +void Renderer11::maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) { HRESULT result; @@ -1758,7 +1767,7 @@ void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingE static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; static const UINT sampleMask = 0xFFFFFFFF; - ID3D11BlendState *blendState = mStateCache.getBlendState(glBlendState); + ID3D11BlendState *blendState = mStateCache.getBlendState(frameBuffer, glBlendState); // Set the vertices D3D11_MAPPED_SUBRESOURCE mappedResource; @@ -1785,7 +1794,7 @@ void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingE mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS); // Apply shaders - ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS; + ID3D11PixelShader *pixelShader = frameBuffer->usingExtendedDrawBuffers() ? mClearMultiplePS : mClearSinglePS; mDeviceContext->IASetInputLayout(mClearIL); mDeviceContext->VSSetShader(mClearVS, NULL, 0); @@ -1949,13 +1958,14 @@ bool Renderer11::testDeviceResettable() D3D_FEATURE_LEVEL featureLevels[] = { - D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, +#if !defined(ANGLE_ENABLE_D3D9) D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, +#endif }; ID3D11Device* dummyDevice; @@ -2134,7 +2144,6 @@ float Renderer11::getTextureMaxAnisotropy() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; case D3D_FEATURE_LEVEL_10_1: @@ -2159,7 +2168,6 @@ Range Renderer11::getViewportBounds() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); case D3D_FEATURE_LEVEL_10_1: @@ -2180,7 +2188,6 @@ unsigned int Renderer11::getMaxVertexTextureImageUnits() const META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: @@ -2212,41 +2219,15 @@ unsigned int Renderer11::getReservedFragmentUniformVectors() const unsigned int Renderer11::getMaxVertexUniformVectors() const { META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return MAX_VERTEX_UNIFORM_VECTORS_D3D11; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return MAX_VERTEX_UNIFORM_VECTORS_D3D9; - default: - UNIMPLEMENTED(); - return 0; - } + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_VERTEX_UNIFORM_VECTORS_D3D11; } unsigned int Renderer11::getMaxFragmentUniformVectors() const { META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; - case D3D_FEATURE_LEVEL_9_3: - return 221; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 29; - default: UNREACHABLE(); - return 0; - } + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; } unsigned int Renderer11::getMaxVaryingVectors() const @@ -2254,11 +2235,9 @@ unsigned int Renderer11::getMaxVaryingVectors() const META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT; case D3D_FEATURE_LEVEL_10_1: - return D3D10_1_VS_OUTPUT_REGISTER_COUNT; case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT; case D3D_FEATURE_LEVEL_9_3: @@ -2274,7 +2253,6 @@ bool Renderer11::getNonPower2TextureSupport() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: @@ -2292,10 +2270,10 @@ bool Renderer11::getOcclusionQuerySupport() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: + return true; case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: return true; @@ -2310,12 +2288,11 @@ bool Renderer11::getInstancingSupport() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_9_3: - return true; + return true; case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: return false; @@ -2336,10 +2313,10 @@ bool Renderer11::getDerivativeInstructionSupport() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: + return true; case D3D_FEATURE_LEVEL_9_3: return true; case D3D_FEATURE_LEVEL_9_2: @@ -2360,13 +2337,12 @@ int Renderer11::getMajorShaderModel() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 4; // SM4 level 9, but treat as 4 + case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 (level 9) default: UNREACHABLE(); return 0; } } @@ -2375,13 +2351,12 @@ int Renderer11::getMinorShaderModel() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; + case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 (level 9) default: UNREACHABLE(); return 0; } } @@ -2402,8 +2377,7 @@ int Renderer11::getMaxViewportDimension() const switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: @@ -2422,7 +2396,6 @@ int Renderer11::getMaxTextureWidth() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 @@ -2437,7 +2410,6 @@ int Renderer11::getMaxTextureHeight() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 @@ -2452,8 +2424,7 @@ bool Renderer11::get32BitIndexSupport() const { switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true case D3D_FEATURE_LEVEL_9_3: @@ -2510,17 +2481,17 @@ unsigned int Renderer11::getMaxRenderTargets() const switch (mFeatureLevel) { - case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: - return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 - case D3D_FEATURE_LEVEL_9_3: - return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4 + case D3D_FEATURE_LEVEL_9_3: // return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4 case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1 + case D3D_FEATURE_LEVEL_9_1: // return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1 + // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader + // outputs to multiple RTs that are not bound. + // TODO: Remove pixel shader outputs for render targets that are not bound. + return 1; default: UNREACHABLE(); return 1; @@ -2703,7 +2674,7 @@ bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectang samplerDesc.BorderColor[2] = 0.0f; samplerDesc.BorderColor[3] = 0.0f; samplerDesc.MinLOD = 0.0f; - samplerDesc.MaxLOD = 0.0f; + samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? 0.0f : FLT_MAX; result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler); ASSERT(SUCCEEDED(result)); @@ -2946,7 +2917,7 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length return executable; } -ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) +ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) { std::string profile; @@ -3124,7 +3095,7 @@ void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsi area.width = width; area.height = height; - readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, + readTextureData(colorBufferTexture, subresourceIndex, area, colorbuffer->getActualFormat(), format, type, outputPitch, packReverseRowOrder, packAlignment, pixels); colorBufferTexture->Release(); @@ -3160,7 +3131,7 @@ TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internal return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size); } -static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) +static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum sourceGLFormat, GLenum destFormat, GLenum destType) { if (sourceFormat == DXGI_FORMAT_A8_UNORM && destFormat == GL_ALPHA && @@ -3168,9 +3139,10 @@ static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum { return 1; } - else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM && - destFormat == GL_RGBA && - destType == GL_UNSIGNED_BYTE) + else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM && + sourceGLFormat == GL_RGBA8_OES && + destFormat == GL_RGBA && + destType == GL_UNSIGNED_BYTE) { return 4; } @@ -3180,9 +3152,10 @@ static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum { return 4; } - else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT && - destFormat == GL_RGBA && - destType == GL_HALF_FLOAT_OES) + else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT && + sourceGLFormat == GL_RGBA16F_EXT && + destFormat == GL_RGBA && + destType == GL_HALF_FLOAT_OES) { return 8; } @@ -3192,9 +3165,10 @@ static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum { return 12; } - else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && - destFormat == GL_RGBA && - destType == GL_FLOAT) + else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && + sourceGLFormat == GL_RGBA32F_EXT && + destFormat == GL_RGBA && + destType == GL_FLOAT) { return 16; } @@ -3204,7 +3178,7 @@ static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum } } -static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, unsigned int x, +static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, GLenum glFormat, unsigned int x, unsigned int y, int inputPitch, gl::Color *outColor) { switch (format) @@ -3215,7 +3189,15 @@ static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF); outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00); outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000); - outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000); + + if (gl::GetAlphaSize(glFormat) > 0) + { + outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000); + } + else + { + outColor->alpha = 1.0f; + } } break; @@ -3233,7 +3215,15 @@ static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, outColor->red = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 0); outColor->green = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 1); outColor->blue = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 2); - outColor->alpha = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 3); + + if (gl::GetAlphaSize(glFormat) > 0) + { + outColor->alpha = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 3); + } + else + { + outColor->alpha = 1.0f; + } } break; @@ -3251,7 +3241,15 @@ static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 0)); outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 1)); outColor->blue = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 2)); - outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 3)); + + if (gl::GetAlphaSize(glFormat) > 0) + { + outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 3)); + } + else + { + outColor->alpha = 1.0f; + } } break; @@ -3413,7 +3411,7 @@ static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum } void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, - GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, + GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void *pixels) { D3D11_TEXTURE2D_DESC textureDesc; @@ -3502,7 +3500,7 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou inputPitch = static_cast(mapping.RowPitch); } - unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, format, type); + unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, sourceFormat, format, type); if (fastPixelSize != 0) { unsigned char *dest = static_cast(pixels); @@ -3537,7 +3535,7 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou { for (int i = 0; i < area.width; i++) { - readPixelColor(source, textureDesc.Format, i, j, inputPitch, &pixelColor); + readPixelColor(source, textureDesc.Format, sourceFormat, i, j, inputPitch, &pixelColor); writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h similarity index 95% rename from src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h index 433945da7a..a8a722c56c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h @@ -14,8 +14,8 @@ #include "libGLESv2/mathutil.h" #include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/RenderStateCache.h" -#include "libGLESv2/renderer/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" #include "libGLESv2/renderer/RenderTarget.h" namespace gl @@ -32,7 +32,6 @@ class StreamingIndexBufferInterface; enum { - MAX_VERTEX_UNIFORM_VECTORS_D3D9 = 254, MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 }; @@ -40,7 +39,7 @@ enum class Renderer11 : public Renderer { public: - Renderer11(egl::Display *display, HDC hDc); + Renderer11(egl::Display *display); virtual ~Renderer11(); static Renderer11 *makeRenderer11(Renderer *renderer); @@ -59,7 +58,7 @@ class Renderer11 : public Renderer virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask); virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW); @@ -156,7 +155,7 @@ class Renderer11 : public Renderer // Shader operations virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); // Image operations virtual Image *createImage(); @@ -178,7 +177,7 @@ class Renderer11 : public Renderer ID3D11Device *getDevice() { return mDevice; } ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; - D3D_FEATURE_LEVEL getFeatureLevel() const { return mFeatureLevel; } + D3D_FEATURE_LEVEL getFeatureLevel() { return mFeatureLevel; } bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); void unapplyRenderTargets(); @@ -193,10 +192,10 @@ class Renderer11 : public Renderer void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, - GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, + GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void *pixels); - void maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers); + void maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); rx::Range getViewportBounds() const; bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, @@ -205,7 +204,6 @@ class Renderer11 : public Renderer HMODULE mD3d11Module; HMODULE mDxgiModule; - HDC mDc; bool mDeviceLost; @@ -237,7 +235,7 @@ class Renderer11 : public Renderer unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; }; - typedef std::unordered_map MultisampleSupportMap; + typedef std::unordered_map > MultisampleSupportMap; MultisampleSupportMap mMultisampleSupportMap; unsigned int mMaxSupportedSamples; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp similarity index 98% rename from src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp index e1eb560334..2e455e3af5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp @@ -8,7 +8,7 @@ // ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader // executable implementation details. -#include "libGLESv2/renderer/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" #include "common/debug.h" diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp similarity index 86% rename from src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp index 2fe15ff5b8..bd97d5cff5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp @@ -7,12 +7,13 @@ // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. -#include "libGLESv2/renderer/SwapChain11.h" +#include "libGLESv2/renderer/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/renderer11_utils.h" -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" + +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h" +#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h" namespace rx { @@ -48,83 +49,19 @@ SwapChain11::~SwapChain11() void SwapChain11::release() { - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBufferTexture) - { - mBackBufferTexture->Release(); - mBackBufferTexture = NULL; - } - - if (mBackBufferRTView) - { - mBackBufferRTView->Release(); - mBackBufferRTView = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mOffscreenRTView) - { - mOffscreenRTView->Release(); - mOffscreenRTView = NULL; - } - - if (mOffscreenSRView) - { - mOffscreenSRView->Release(); - mOffscreenSRView = NULL; - } - - if (mDepthStencilTexture) - { - mDepthStencilTexture->Release(); - mDepthStencilTexture = NULL; - } - - if (mDepthStencilDSView) - { - mDepthStencilDSView->Release(); - mDepthStencilDSView = NULL; - } - - if (mQuadVB) - { - mQuadVB->Release(); - mQuadVB = NULL; - } - - if (mPassThroughSampler) - { - mPassThroughSampler->Release(); - mPassThroughSampler = NULL; - } - - if (mPassThroughIL) - { - mPassThroughIL->Release(); - mPassThroughIL = NULL; - } - - if (mPassThroughVS) - { - mPassThroughVS->Release(); - mPassThroughVS = NULL; - } - - if (mPassThroughPS) - { - mPassThroughPS->Release(); - mPassThroughPS = NULL; - } + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); + SafeRelease(mQuadVB); + SafeRelease(mPassThroughSampler); + SafeRelease(mPassThroughIL); + SafeRelease(mPassThroughVS); + SafeRelease(mPassThroughPS); if (!mAppCreatedShareHandle) { @@ -134,35 +71,11 @@ void SwapChain11::release() void SwapChain11::releaseOffscreenTexture() { - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mOffscreenRTView) - { - mOffscreenRTView->Release(); - mOffscreenRTView = NULL; - } - - if (mOffscreenSRView) - { - mOffscreenSRView->Release(); - mOffscreenSRView = NULL; - } - - if (mDepthStencilTexture) - { - mDepthStencilTexture->Release(); - mDepthStencilTexture = NULL; - } - - if (mDepthStencilDSView) - { - mDepthStencilDSView->Release(); - mDepthStencilDSView = NULL; - } + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); } EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) @@ -369,23 +282,17 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) return EGL_BAD_ACCESS; } - if (!mSwapChain) - reset(backbufferWidth, backbufferHeight, mSwapInterval); + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + return EGL_SUCCESS; + } // Can only call resize if we have already created our swap buffer and resources ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); - if (mBackBufferTexture) - { - mBackBufferTexture->Release(); - mBackBufferTexture = NULL; - } - - if (mBackBufferRTView) - { - mBackBufferRTView->Release(); - mBackBufferRTView = NULL; - } + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); // Resize swap chain DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); @@ -434,23 +341,9 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap // Release specific resources to free up memory for the new render target, while the // old render target still exists for the purpose of preserving its contents. - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBufferTexture) - { - mBackBufferTexture->Release(); - mBackBufferTexture = NULL; - } - - if (mBackBufferRTView) - { - mBackBufferRTView->Release(); - mBackBufferRTView = NULL; - } + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); mSwapInterval = static_cast(swapInterval); if (mSwapInterval > 4) @@ -469,25 +362,13 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap if (mWindow) { #if !defined(ANGLE_OS_WINRT) - // We cannot create a swap chain for an HWND that is owned by a different process - DWORD currentProcessId = GetCurrentProcessId(); - DWORD wndProcessId; - GetWindowThreadProcessId(mWindow, &wndProcessId); - - if (currentProcessId != wndProcessId) - { - ERR("Could not create swap chain, window owned by different process"); - release(); - return EGL_BAD_NATIVE_WINDOW; - } - IDXGIFactory *factory = mRenderer->getDxgiFactory(); DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; - swapChainDesc.BufferCount = 2; swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); swapChainDesc.BufferDesc.Width = backbufferWidth; swapChainDesc.BufferDesc.Height = backbufferHeight; + swapChainDesc.BufferCount = 2; swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; @@ -512,7 +393,6 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; #endif #endif - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.Flags = 0; swapChainDesc.SampleDesc.Count = 1; @@ -535,10 +415,28 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap { return EGL_CONTEXT_LOST; } +#if !defined(ANGLE_OS_WINRT) else { - return EGL_BAD_ALLOC; + // We cannot create a swap chain for an HWND that is owned by a different process on some versions of + // windows + DWORD currentProcessId = GetCurrentProcessId(); + DWORD wndProcessId; + GetWindowThreadProcessId(mWindow, &wndProcessId); + + if (currentProcessId != wndProcessId) + { + ERR("Could not create swap chain, window owned by different process"); + return EGL_BAD_NATIVE_WINDOW; + } + else + { + return EGL_BAD_ALLOC; + } } +#else + return EGL_BAD_ALLOC; +#endif } result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); @@ -697,7 +595,12 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) // Draw deviceContext->Draw(4, 0); + +#if ANGLE_FORCE_VSYNC_OFF + result = mSwapChain->Present(0, 0); +#else result = mSwapChain->Present(mSwapInterval, 0); +#endif if (result == DXGI_ERROR_DEVICE_REMOVED) { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp similarity index 97% rename from src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp index 32a407a988..fdfbe526ec 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp @@ -8,12 +8,12 @@ // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. -#include "libGLESv2/renderer/TextureStorage11.h" +#include "libGLESv2/renderer/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/Renderer11.h" -#include "libGLESv2/renderer/RenderTarget11.h" -#include "libGLESv2/renderer/SwapChain11.h" -#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" #include "libGLESv2/utilities.h" #include "libGLESv2/main.h" @@ -229,7 +229,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum mRenderTarget[i] = NULL; } - DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()); + DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); if (d3d11::IsDepthStencilFormat(convertedFormat)) { mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); @@ -331,7 +331,7 @@ RenderTarget *TextureStorage11_2D::getRenderTarget(int level) srvDesc.Format = mShaderResourceFormat; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MostDetailedMip = level; - srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MipLevels = level ? 1 : -1; ID3D11ShaderResourceView *srv; result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); @@ -450,7 +450,7 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLe } } - DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()); + DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); if (d3d11::IsDepthStencilFormat(convertedFormat)) { mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); @@ -549,7 +549,7 @@ RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int leve D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube srvDesc.Texture2DArray.MostDetailedMip = level; srvDesc.Texture2DArray.MipLevels = 1; srvDesc.Texture2DArray.FirstArraySlice = faceIdx; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp similarity index 99% rename from src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp index 521da80c3d..6f9b4181f1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp @@ -7,11 +7,11 @@ // VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. -#include "libGLESv2/renderer/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" #include "libGLESv2/renderer/BufferStorage.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/Renderer11.h" +#include "libGLESv2/renderer/d3d11/Renderer11.h" #include "libGLESv2/Context.h" namespace rx diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp similarity index 99% rename from src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp index 0624a61160..34b8259a80 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp @@ -8,7 +8,7 @@ // renderer11_utils.cpp: Conversion functions and other utility routines // specific to the D3D11 renderer. -#include "libGLESv2/renderer/renderer11_utils.h" +#include "libGLESv2/renderer/d3d11/renderer11_utils.h" #include "common/debug.h" diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp similarity index 96% rename from src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp index 2a3ce39c63..d73df6418d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp @@ -7,23 +7,23 @@ // Blit.cpp: Surface copy utility class. -#include "libGLESv2/renderer/Blit.h" +#include "libGLESv2/renderer/d3d9/Blit.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/TextureStorage9.h" -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" #include "libGLESv2/Framebuffer.h" #include "libGLESv2/Renderbuffer.h" namespace { -#include "libGLESv2/renderer/shaders/compiled/standardvs.h" -#include "libGLESv2/renderer/shaders/compiled/flipyvs.h" -#include "libGLESv2/renderer/shaders/compiled/passthroughps.h" -#include "libGLESv2/renderer/shaders/compiled/luminanceps.h" -#include "libGLESv2/renderer/shaders/compiled/componentmaskps.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h" +#include "libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h" const BYTE* const g_shaderCode[] = { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Blit.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/Blit.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp similarity index 94% rename from src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp index 57fd29bf80..9fdc1246f1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp @@ -7,7 +7,7 @@ // BufferStorage9.cpp Defines the BufferStorage9 class. -#include "libGLESv2/renderer/BufferStorage9.h" +#include "libGLESv2/renderer/d3d9/BufferStorage9.h" #include "common/debug.h" namespace rx @@ -36,7 +36,7 @@ void *BufferStorage9::getData() return mMemory; } -void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset, unsigned int) +void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset) { if (!mMemory || offset + size > mAllocatedSize) { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h similarity index 95% rename from src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h index 82ae577e23..3e803969bc 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h @@ -23,7 +23,7 @@ class BufferStorage9 : public BufferStorage static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage); virtual void *getData(); - virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target = 0); + virtual void setData(const void* data, unsigned int size, unsigned int offset); virtual void clear(); virtual unsigned int getSize() const; virtual bool supportsDirectBinding() const; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp similarity index 95% rename from src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp index 86064d7e52..639c37b4e4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp @@ -7,10 +7,10 @@ // Fence9.cpp: Defines the rx::Fence9 class. -#include "libGLESv2/renderer/Fence9.h" +#include "libGLESv2/renderer/d3d9/Fence9.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/Fence9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp similarity index 98% rename from src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp index 53030b7f1e..cd12d8cc9e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp @@ -8,16 +8,16 @@ // Image9.cpp: Implements the rx::Image9 class, which acts as the interface to // the actual underlying surfaces of a Texture. -#include "libGLESv2/renderer/Image9.h" +#include "libGLESv2/renderer/d3d9/Image9.h" #include "libGLESv2/main.h" #include "libGLESv2/Framebuffer.h" #include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/Renderer9.h" -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/TextureStorage9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" #include "libGLESv2/renderer/generatemip.h" namespace rx @@ -733,4 +733,4 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, mDirty = true; } -} \ No newline at end of file +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/Image9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp similarity index 97% rename from src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp index c6d83c5dca..7cb5d13a18 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp @@ -7,8 +7,8 @@ // Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. -#include "libGLESv2/renderer/IndexBuffer9.h" -#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp similarity index 94% rename from src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp index ef694267dd..72781cbc39 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp @@ -8,10 +8,10 @@ // Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. -#include "libGLESv2/renderer/Query9.h" +#include "libGLESv2/renderer/d3d9/Query9.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/Query9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp similarity index 95% rename from src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp index a84c709059..090431db99 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp @@ -8,10 +8,10 @@ // RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 // pointers retained by renderbuffers. -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" #include "libGLESv2/main.h" namespace rx diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp similarity index 96% rename from src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp index d3f3814ae5..97a10d64bf 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp @@ -14,19 +14,19 @@ #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/Renderer9.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/ShaderExecutable9.h" -#include "libGLESv2/renderer/SwapChain9.h" -#include "libGLESv2/renderer/TextureStorage9.h" -#include "libGLESv2/renderer/Image9.h" -#include "libGLESv2/renderer/Blit.h" -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/VertexBuffer9.h" -#include "libGLESv2/renderer/IndexBuffer9.h" -#include "libGLESv2/renderer/BufferStorage9.h" -#include "libGLESv2/renderer/Query9.h" -#include "libGLESv2/renderer/Fence9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" +#include "libGLESv2/renderer/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d9/Image9.h" +#include "libGLESv2/renderer/d3d9/Blit.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d9/BufferStorage9.h" +#include "libGLESv2/renderer/d3d9/Query9.h" +#include "libGLESv2/renderer/d3d9/Fence9.h" #include "libEGL/Display.h" @@ -121,8 +121,6 @@ Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Rend Renderer9::~Renderer9() { - releaseDeviceResources(); - if (mDevice) { // If the device is lost, reset it first to prevent leaving the driver in an unstable state @@ -130,22 +128,19 @@ Renderer9::~Renderer9() { resetDevice(); } - - mDevice->Release(); - mDevice = NULL; } - if (mDeviceEx) - { - mDeviceEx->Release(); - mDeviceEx = NULL; - } + deinitialize(); +} - if (mD3d9) - { - mD3d9->Release(); - mD3d9 = NULL; - } +void Renderer9::deinitialize() +{ + releaseDeviceResources(); + + SafeRelease(mDevice); + SafeRelease(mDeviceEx); + SafeRelease(mD3d9); + SafeRelease(mD3d9Ex); if (mDeviceWindow) { @@ -153,12 +148,6 @@ Renderer9::~Renderer9() mDeviceWindow = NULL; } - if (mD3d9Ex) - { - mD3d9Ex->Release(); - mD3d9Ex = NULL; - } - if (mD3d9Module) { mD3d9Module = NULL; @@ -863,7 +852,7 @@ void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) mForceSetRasterState = false; } -void Renderer9::setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) +void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) { bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0; @@ -1465,7 +1454,7 @@ void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvo if (mode == GL_POINTS) { - drawIndexedPoints(count, type, indices, elementArrayBuffer); + drawIndexedPoints(count, type, indices, indexInfo.minIndex, elementArrayBuffer); } else if (mode == GL_LINE_LOOP) { @@ -1669,16 +1658,16 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } template -static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices) +static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) { for (int i = 0; i < count; i++) { - unsigned int indexValue = static_cast(static_cast(indices)[i]); + unsigned int indexValue = static_cast(static_cast(indices)[i]) - minIndex; device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); } } -void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer) +void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) { // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call // for each individual point. This call is not expected to happen often. @@ -1692,9 +1681,9 @@ void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indi switch (type) { - case GL_UNSIGNED_BYTE: drawPoints(mDevice, count, indices); break; - case GL_UNSIGNED_SHORT: drawPoints(mDevice, count, indices); break; - case GL_UNSIGNED_INT: drawPoints(mDevice, count, indices); break; + case GL_UNSIGNED_BYTE: drawPoints(mDevice, count, indices, minIndex); break; + case GL_UNSIGNED_SHORT: drawPoints(mDevice, count, indices, minIndex); break; + case GL_UNSIGNED_INT: drawPoints(mDevice, count, indices, minIndex); break; default: UNREACHABLE(); } } @@ -2045,31 +2034,19 @@ void Renderer9::releaseDeviceResources() mEventQueryPool.pop_back(); } - if (mMaskedClearSavedState) - { - mMaskedClearSavedState->Release(); - mMaskedClearSavedState = NULL; - } + SafeRelease(mMaskedClearSavedState); mVertexShaderCache.clear(); mPixelShaderCache.clear(); - delete mBlit; - mBlit = NULL; - - delete mVertexDataManager; - mVertexDataManager = NULL; - - delete mIndexDataManager; - mIndexDataManager = NULL; - - delete mLineLoopIB; - mLineLoopIB = NULL; + SafeDelete(mBlit); + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) { - delete mNullColorbufferCache[i].buffer; - mNullColorbufferCache[i].buffer = NULL; + SafeDelete(mNullColorbufferCache[i].buffer); } } @@ -2089,22 +2066,8 @@ bool Renderer9::isDeviceLost() // set notify to true to broadcast a message to all contexts of the device loss bool Renderer9::testDeviceLost(bool notify) { - HRESULT status = S_OK; - - if (mDeviceEx) - { - status = mDeviceEx->CheckDeviceState(NULL); - } - else if (mDevice) - { - status = mDevice->TestCooperativeLevel(); - } - else - { - // No device yet, so no reset required - } - - bool isLost = FAILED(status) || d3d9::isDeviceLostError(status); + HRESULT status = getDeviceStatusCode(); + bool isLost = FAILED(status); if (isLost) { @@ -2123,7 +2086,7 @@ bool Renderer9::testDeviceLost(bool notify) return isLost; } -bool Renderer9::testDeviceResettable() +HRESULT Renderer9::getDeviceStatusCode() { HRESULT status = D3D_OK; @@ -2136,9 +2099,14 @@ bool Renderer9::testDeviceResettable() status = mDevice->TestCooperativeLevel(); } + return status; +} + +bool Renderer9::testDeviceResettable() +{ // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted // DEVICEREMOVED indicates the device has been stopped and must be recreated - switch (status) + switch (getDeviceStatusCode()) { case D3DERR_DEVICENOTRESET: case D3DERR_DEVICEHUNG: @@ -2146,8 +2114,8 @@ bool Renderer9::testDeviceResettable() case D3DERR_DEVICELOST: return (mDeviceEx != NULL); case D3DERR_DEVICEREMOVED: - UNIMPLEMENTED(); - return false; + ASSERT(mDeviceEx != NULL); + return isRemovedDeviceResettable(); default: return false; } @@ -2161,14 +2129,26 @@ bool Renderer9::resetDevice() HRESULT result = D3D_OK; bool lost = testDeviceLost(false); - int attempts = 3; + bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); - while (lost && attempts > 0) + // Device Removed is a feature which is only present with D3D9Ex + ASSERT(mDeviceEx != NULL || !removedDevice); + + for (int attempts = 3; lost && attempts > 0; attempts--) { - if (mDeviceEx) + if (removedDevice) + { + // Device removed, which may trigger on driver reinstallation, + // may cause a longer wait other reset attempts before the + // system is ready to handle creating a new device. + Sleep(800); + lost = !resetRemovedDevice(); + } + else if (mDeviceEx) { Sleep(500); // Give the graphics driver some CPU time result = mDeviceEx->ResetEx(&presentParameters, NULL); + lost = testDeviceLost(false); } else { @@ -2183,10 +2163,8 @@ bool Renderer9::resetDevice() { result = mDevice->Reset(&presentParameters); } + lost = testDeviceLost(false); } - - lost = testDeviceLost(false); - attempts --; } if (FAILED(result)) @@ -2195,13 +2173,58 @@ bool Renderer9::resetDevice() return false; } - // reset device defaults - initializeDevice(); + if (removedDevice && lost) + { + ERR("Device lost reset failed multiple times"); + return false; + } + + // If the device was removed, we already finished re-initialization in resetRemovedDevice + if (!removedDevice) + { + // reset device defaults + initializeDevice(); + } + mDeviceLost = false; return true; } +bool Renderer9::isRemovedDeviceResettable() const +{ + bool success = false; + +#ifdef ANGLE_ENABLE_D3D9EX + IDirect3D9Ex *d3d9Ex = NULL; + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex))) + { + D3DCAPS9 deviceCaps; + HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps); + success = SUCCEEDED(result); + } + + SafeRelease(d3d9Ex); +#else + ASSERT(UNREACHABLE()); +#endif + + return success; +} + +bool Renderer9::resetRemovedDevice() +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: + // The hardware adapter has been removed. Application must destroy the device, do enumeration of + // adapters and create another Direct3D device. If application continues rendering without + // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. + deinitialize(); + return (initialize() == EGL_SUCCESS); +} + DWORD Renderer9::getAdapterVendor() const { return mAdapterIdentifier.VendorId; @@ -3129,7 +3152,7 @@ ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, return executable; } -ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) +ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) { const char *profile = NULL; @@ -3146,7 +3169,11 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha return NULL; } - ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, ANGLE_COMPILE_OPTIMIZATION_LEVEL, true); + // ANGLE issue 486: + // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization + UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL); + + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true); if (!binary) return NULL; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h similarity index 96% rename from src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h index f8932c4fd4..24fd2bdd84 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h @@ -12,7 +12,7 @@ #include "common/angleutils.h" #include "libGLESv2/mathutil.h" #include "libGLESv2/renderer/ShaderCache.h" -#include "libGLESv2/renderer/VertexDeclarationCache.h" +#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/RenderTarget.h" @@ -72,7 +72,7 @@ class Renderer9 : public Renderer virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(const gl::BlendState &blendState, const gl::Color &blendColor, + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask); virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW); @@ -170,7 +170,7 @@ class Renderer9 : public Renderer // Shader operations virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); // Image operations virtual Image *createImage(); @@ -198,12 +198,14 @@ class Renderer9 : public Renderer private: DISALLOW_COPY_AND_ASSIGN(Renderer9); + void deinitialize(); + void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v); void applyUniformniv(gl::Uniform *targetUniform, const GLint *v); void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v); void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer); + void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); @@ -218,6 +220,10 @@ class Renderer9 : public Renderer D3DPRESENT_PARAMETERS getDefaultPresentParameters(); void releaseDeviceResources(); + HRESULT getDeviceStatusCode(); + bool isRemovedDeviceResettable() const; + bool resetRemovedDevice(); + UINT mAdapter; D3DDEVTYPE mDeviceType; bool mSoftwareDevice; // FIXME: Deprecate diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp similarity index 96% rename from src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp index 98868a3fbf..5decf9664d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp @@ -8,7 +8,7 @@ // ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader // executable implementation details. -#include "libGLESv2/renderer/ShaderExecutable9.h" +#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" #include "common/debug.h" diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp similarity index 95% rename from src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp index f57a874688..dd8895d18d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp @@ -7,9 +7,9 @@ // SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. -#include "libGLESv2/renderer/SwapChain9.h" -#include "libGLESv2/renderer/renderer9_utils.h" -#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" namespace rx { @@ -71,6 +71,9 @@ void SwapChain9::release() static DWORD convertInterval(EGLint interval) { +#if ANGLE_FORCE_VSYNC_OFF + return D3DPRESENT_INTERVAL_IMMEDIATE; +#else switch(interval) { case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; @@ -82,6 +85,7 @@ static DWORD convertInterval(EGLint interval) } return D3DPRESENT_INTERVAL_DEFAULT; +#endif } EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) @@ -137,21 +141,6 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI pShareHandle = &mShareHandle; } - // CreateTexture will fail on zero dimensions, so just release old target - if (!backbufferWidth || !backbufferHeight) - { - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - - return EGL_SUCCESS; - } - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); @@ -323,6 +312,11 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++) + { + device->SetStreamSourceFreq(streamIndex, 1); + } + D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; device->SetViewport(&viewport); @@ -357,17 +351,19 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) mRenderer->markAllStateDirty(); - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) { return EGL_BAD_ALLOC; } - ASSERT(SUCCEEDED(result)); + // http://crbug.com/313210 + // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific + // device removed bug with lost contexts when reinstalling drivers. + if (FAILED(result)) + { + mRenderer->notifyDeviceLost(); + return EGL_CONTEXT_LOST; + } return EGL_SUCCESS; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp similarity index 97% rename from src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp index 8aa74a7cba..2486a9a5bf 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp @@ -10,11 +10,11 @@ // D3D9 texture. #include "libGLESv2/main.h" -#include "libGLESv2/renderer/Renderer9.h" -#include "libGLESv2/renderer/TextureStorage9.h" -#include "libGLESv2/renderer/SwapChain9.h" -#include "libGLESv2/renderer/RenderTarget9.h" -#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" #include "libGLESv2/Texture.h" namespace rx diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp similarity index 99% rename from src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp index b017b3af33..57f5bcd256 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp @@ -7,11 +7,11 @@ // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. -#include "libGLESv2/renderer/VertexBuffer9.h" -#include "libGLESv2/renderer/vertexconversion.h" +#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d9/vertexconversion.h" #include "libGLESv2/renderer/BufferStorage.h" #include "libGLESv2/Context.h" -#include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/d3d9/Renderer9.h" #include "libGLESv2/Buffer.h" @@ -182,7 +182,7 @@ bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const { - return formatConverter(attrib).identity; + return !formatConverter(attrib).identity; } unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp similarity index 98% rename from src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp index 9b83a6476e..e5c8a14232 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp @@ -9,8 +9,8 @@ #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Context.h" -#include "libGLESv2/renderer/VertexBuffer9.h" -#include "libGLESv2/renderer/VertexDeclarationCache.h" +#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp similarity index 99% rename from src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.cpp rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp index da75d465e3..b7f2ffb1d9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp @@ -8,7 +8,7 @@ // renderer9_utils.cpp: Conversion functions and other utility routines // specific to the D3D9 renderer. -#include "libGLESv2/renderer/renderer9_utils.h" +#include "libGLESv2/renderer/d3d9/renderer9_utils.h" #include "libGLESv2/mathutil.h" #include "libGLESv2/Context.h" diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.ps rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.vs rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h similarity index 100% rename from src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h rename to src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp index 8fd193b164..30765ffba0 100644 --- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp +++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp @@ -9,13 +9,13 @@ #include "libGLESv2/utilities.h" #include "libGLESv2/mathutil.h" - #if defined(ANGLE_OS_WINRT) -#include -#include -#include -#include -using namespace ABI::Windows::Storage; +# include +# include +# include +# include + using namespace Microsoft::WRL; + using namespace ABI::Windows::Storage; #endif namespace gl @@ -745,29 +745,43 @@ bool IsTriangleMode(GLenum drawMode) std::string getTempPath() { -#if defined(ANGLE_OS_WINRT) +#if !defined(ANGLE_OS_WINRT) + char path[MAX_PATH]; + DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); + if (pathLen == 0) + { + UNREACHABLE(); + return std::string(); + } + UINT unique = GetTempFileNameA(path, "sh", 0, path); + if (unique == 0) + { + UNREACHABLE(); + return std::string(); + } +#else static std::string path; while (path.empty()) { - IApplicationDataStatics *applicationDataFactory; - HRESULT result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), - IID_PPV_ARGS(&applicationDataFactory)); + ComPtr factory; + Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); + HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); if (FAILED(result)) break; - IApplicationData *applicationData; - result = applicationDataFactory->get_Current(&applicationData); + ComPtr applicationData; + result = factory->get_Current(&applicationData); if (FAILED(result)) break; - IStorageFolder *storageFolder; + ComPtr storageFolder; result = applicationData->get_LocalFolder(&storageFolder); if (FAILED(result)) break; - IStorageItem *localFolder; - result = storageFolder->QueryInterface(IID_PPV_ARGS(&localFolder)); + ComPtr localFolder; + result = storageFolder.As(&localFolder); if (FAILED(result)) break; @@ -784,25 +798,6 @@ std::string getTempPath() break; } } - -#else - - char path[MAX_PATH]; - - DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); - if (pathLen == 0) - { - UNREACHABLE(); - return std::string(); - } - - UINT unique = GetTempFileNameA(path, "sh", 0, path); - if (unique == 0) - { - UNREACHABLE(); - return std::string(); - } - #endif return path; diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h index 0d4e1a374c..f725f55b57 100644 --- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h +++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h @@ -28,8 +28,8 @@ #include "GLSLANG/ShaderLang.h" -#include "compiler/InfoSink.h" -#include "compiler/intermediate.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/intermediate.h" class ArrayBoundsClamper { public: diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h index 72d354dd64..96ac910b08 100644 --- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h @@ -574,8 +574,6 @@ namespace gl { -extern long **traceSamplingState; - namespace TraceEvent { // Specify these values when the corresponding argument of addTraceEvent is not @@ -793,6 +791,7 @@ private: // TraceEventSamplingStateScope records the current sampling state // and sets a new sampling state. When the scope exists, it restores // the sampling state having recorded. +#if 0 // This is not used by ANGLE and causes a compilation error on MinGW template class SamplingStateScope { public: @@ -820,6 +819,7 @@ public: private: const char* m_previousState; }; +#endif } // namespace TraceEvent diff --git a/src/angle/patches/0001-ANGLE-Fix-compilation-with-MSVC2013.patch b/src/angle/patches/0001-ANGLE-Fix-compilation-with-MSVC2013.patch deleted file mode 100644 index cf32a20d46..0000000000 --- a/src/angle/patches/0001-ANGLE-Fix-compilation-with-MSVC2013.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 4863cf64cd332a5fcefe453634c3c5ef62cb758c Mon Sep 17 00:00:00 2001 -From: Friedemann Kleint -Date: Thu, 24 Oct 2013 12:49:59 +0300 -Subject: [PATCH] ANGLE: Fix compilation with MSVC2013. - -Add missing include for std::min(), std::max(). - -Change-Id: I740e5db94f9f958ac65de8dd7baab7e203482637 ---- - src/3rdparty/angle/src/libEGL/Surface.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp -index b47a7bc..83fbbf5 100644 ---- a/src/3rdparty/angle/src/libEGL/Surface.cpp -+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp -@@ -20,6 +20,8 @@ - #include "libEGL/main.h" - #include "libEGL/Display.h" - -+#include -+ - namespace egl - { - --- -1.8.3.msysgit.0 - diff --git a/src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch b/src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch index 2fa23aed8f..06ab16abdb 100644 --- a/src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch +++ b/src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch @@ -1,32 +1,31 @@ -From d4776adddb971642164de54141e015abde881740 Mon Sep 17 00:00:00 2001 +From 88297d02fd1aed6cac258b72d9d0a8baabad6203 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann -Date: Tue, 8 Oct 2013 09:46:54 +0200 +Date: Mon, 17 Feb 2014 16:56:51 +0200 Subject: [PATCH] Fix compilation for MSVC 2008 and std::tuple For MSVC 2008 make_tuple is in the tr1 namespace. Change-Id: I4a51f6cabdf068993869b404b12ed1484a21a9d4 --- - .../src/libGLESv2/renderer/IndexRangeCache.cpp | 6 +++++- - 1 files changed, 5 insertions(+), 1 deletions(-) + src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp | 4 ++++ + 1 file changed, 4 insertions(+) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp -index 610a5ef..95a6961 100644 +index 610a5ef..51d7f0b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp @@ -81,7 +81,11 @@ IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const { -- return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count); +#if defined(_MSC_VER) && _MSC_VER < 1600 + return std::tr1::make_tuple(type, offset, count) < std::tr1::make_tuple(rhs.type, rhs.offset, rhs.count); +#else -+ return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count); + return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count); +#endif } IndexRangeCache::IndexBounds::IndexBounds() -- -1.7.6.msysgit.0 +1.8.4.msysgit.0 diff --git a/src/angle/patches/0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch b/src/angle/patches/0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch deleted file mode 100644 index 9de8c54fb6..0000000000 --- a/src/angle/patches/0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch +++ /dev/null @@ -1,200 +0,0 @@ -From f1eeb288ae18f3015f435fc2df25ec1eb0f15e1a Mon Sep 17 00:00:00 2001 -From: Friedemann Kleint -Date: Sat, 14 Sep 2013 11:07:17 +0300 -Subject: [PATCH] Make it possible to link ANGLE statically for - single-thread use. - -Fix exports and provide static instances of thread-local -data depending on QT_OPENGL_ES_2_ANGLE_STATIC. - -Change-Id: Ifab25a820adf5953bb3b09036de53dbf7f1a7fd5 ---- - src/3rdparty/angle/include/KHR/khrplatform.h | 2 +- - src/3rdparty/angle/src/libEGL/main.cpp | 35 ++++++++++++++++++++-------- - src/3rdparty/angle/src/libGLESv2/main.cpp | 21 ++++++++++++++--- - 3 files changed, 44 insertions(+), 14 deletions(-) - -diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h -index 8ec0d19..541bfa9 100644 ---- a/src/3rdparty/angle/include/KHR/khrplatform.h -+++ b/src/3rdparty/angle/include/KHR/khrplatform.h -@@ -97,7 +97,7 @@ - *------------------------------------------------------------------------- - * This precedes the return type of the function in the function prototype. - */ --#if defined(_WIN32) && !defined(__SCITECH_SNAP__) -+#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) - # define KHRONOS_APICALL __declspec(dllimport) - #elif defined (__SYMBIAN32__) - # define KHRONOS_APICALL IMPORT_C -diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp -index 424ec3f..7dea5fc 100644 ---- a/src/3rdparty/angle/src/libEGL/main.cpp -+++ b/src/3rdparty/angle/src/libEGL/main.cpp -@@ -10,6 +10,8 @@ - - #include "common/debug.h" - -+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC -+ - static DWORD currentTLS = TLS_OUT_OF_INDEXES; - - extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -@@ -86,74 +88,87 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - return TRUE; - } - -+#endif // !QT_OPENGL_ES_2_ANGLE_STATIC -+ - namespace egl - { -+Current *getCurrent() -+{ -+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC -+ return (Current*)TlsGetValue(currentTLS); -+#else -+ // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. -+ static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; -+ return &curr; -+#endif -+} -+ - void setCurrentError(EGLint error) - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - current->error = error; - } - - EGLint getCurrentError() - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - return current->error; - } - - void setCurrentAPI(EGLenum API) - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - current->API = API; - } - - EGLenum getCurrentAPI() - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - return current->API; - } - - void setCurrentDisplay(EGLDisplay dpy) - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - current->display = dpy; - } - - EGLDisplay getCurrentDisplay() - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - return current->display; - } - - void setCurrentDrawSurface(EGLSurface surface) - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - current->drawSurface = surface; - } - - EGLSurface getCurrentDrawSurface() - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - return current->drawSurface; - } - - void setCurrentReadSurface(EGLSurface surface) - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - current->readSurface = surface; - } - - EGLSurface getCurrentReadSurface() - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - return current->readSurface; - } -diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp -index 6d7a241..730a6ac 100644 ---- a/src/3rdparty/angle/src/libGLESv2/main.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/main.cpp -@@ -11,6 +11,8 @@ - - #include "libGLESv2/Context.h" - -+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC -+ - static DWORD currentTLS = TLS_OUT_OF_INDEXES; - - extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -@@ -69,11 +71,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - return TRUE; - } - -+#endif // !QT_OPENGL_ES_2_ANGLE_STATIC -+ - namespace gl - { -+Current *getCurrent() -+{ -+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC -+ return (Current*)TlsGetValue(currentTLS); -+#else -+ // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. -+ static gl::Current curr = { 0, 0 }; -+ return &curr; -+#endif -+} -+ - void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - current->context = context; - current->display = display; -@@ -86,7 +101,7 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) - - Context *getContext() - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - return current->context; - } -@@ -112,7 +127,7 @@ Context *getNonLostContext() - - egl::Display *getDisplay() - { -- Current *current = (Current*)TlsGetValue(currentTLS); -+ Current *current = getCurrent(); - - return current->display; - } --- -1.8.1.msysgit.1 - diff --git a/src/angle/patches/0001-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch b/src/angle/patches/0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch similarity index 83% rename from src/angle/patches/0001-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch rename to src/angle/patches/0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch index 498cce1b7c..8b91d4b8ea 100644 --- a/src/angle/patches/0001-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch +++ b/src/angle/patches/0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch @@ -1,6 +1,6 @@ -From 58a797397378aff3aa039a8b2a2d7011fe788737 Mon Sep 17 00:00:00 2001 +From 95e3ca47772ef0552662b1d04b7ee08d9d1d2338 Mon Sep 17 00:00:00 2001 From: Kai Koehne -Date: Tue, 21 Jan 2014 10:23:38 +0100 +Date: Mon, 17 Feb 2014 16:59:19 +0200 Subject: [PATCH] Fix compilation of ANGLE with mingw-tdm64 gcc 4.8.1 Do not rely on sprintf_s being declared/defined. This also fixes @@ -16,7 +16,7 @@ Change-Id: I520e2f61aeab34963e7a57baafd413c7db93f110 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp -index a382c3b..82b48ce 100644 +index a382c3b..13ef701 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -523,7 +523,7 @@ void Display::initVendorString() @@ -24,10 +24,10 @@ index a382c3b..82b48ce 100644 { char adapterLuidString[64]; - sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); -+ snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08l%08l)", adapterLuid.HighPart, adapterLuid.LowPart); ++ snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); mVendorString += adapterLuidString; } -- -1.8.5.2.msysgit.0 +1.8.4.msysgit.0 diff --git a/src/angle/patches/0001-Fix-compilation-with-MinGW-gcc-64-bit.patch b/src/angle/patches/0003-Fix-compilation-with-MinGW-gcc-64-bit.patch similarity index 83% rename from src/angle/patches/0001-Fix-compilation-with-MinGW-gcc-64-bit.patch rename to src/angle/patches/0003-Fix-compilation-with-MinGW-gcc-64-bit.patch index 0420694c91..7d70057a9a 100644 --- a/src/angle/patches/0001-Fix-compilation-with-MinGW-gcc-64-bit.patch +++ b/src/angle/patches/0003-Fix-compilation-with-MinGW-gcc-64-bit.patch @@ -1,6 +1,6 @@ -From 821c28d387b332bf16b6ea35ec22a77d3ba41632 Mon Sep 17 00:00:00 2001 +From a03d8f647816767525489a2b26663d897f0264a0 Mon Sep 17 00:00:00 2001 From: Kai Koehne -Date: Mon, 28 Oct 2013 10:27:53 +0100 +Date: Tue, 18 Feb 2014 09:34:39 +0200 Subject: [PATCH] Fix compilation with MinGW gcc 64 bit Fix compilation of ANGLE with gcc 4.8.0 64 bit: The @@ -18,10 +18,10 @@ Change-Id: Ibde75dd4b5536f3827bdf0ab02a15e93a1a8a4f0 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h -index 113b126..72d354d 100644 +index 1880056..637cf9a 100644 --- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h -@@ -589,7 +589,7 @@ const unsigned long long noEventId = 0; +@@ -587,7 +587,7 @@ const unsigned long long noEventId = 0; class TraceID { public: explicit TraceID(const void* id, unsigned char* flags) : @@ -31,5 +31,5 @@ index 113b126..72d354d 100644 *flags |= TRACE_EVENT_FLAG_MANGLE_ID; } -- -1.8.3.msysgit.0 +1.8.4.msysgit.0 diff --git a/src/angle/patches/0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch b/src/angle/patches/0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch deleted file mode 100644 index 6eb84fd02e..0000000000 --- a/src/angle/patches/0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 991dfbdfc018cb30bc1ac4df429411680b47d674 Mon Sep 17 00:00:00 2001 -From: Miikka Heikkinen -Date: Sat, 14 Sep 2013 11:07:45 +0300 -Subject: [PATCH] Fix black screen after minimizing OpenGL window with - ANGLE - -CreateTexture will fail on zero dimensions, so just release old target -and reset dimensions when resetSwapChain is called with zero size area. - -Task-number: QTBUG-27994 -Change-Id: I1e500c4fd4b92f7d9ea2a49a44f3fb930b575cd1 -Reviewed-by: Friedemann Kleint ---- - src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp -index 0324d01..f57a874 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp -@@ -137,6 +137,21 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI - pShareHandle = &mShareHandle; - } - -+ // CreateTexture will fail on zero dimensions, so just release old target -+ if (!backbufferWidth || !backbufferHeight) -+ { -+ if (mRenderTarget) -+ { -+ mRenderTarget->Release(); -+ mRenderTarget = NULL; -+ } -+ -+ mWidth = backbufferWidth; -+ mHeight = backbufferHeight; -+ -+ return EGL_SUCCESS; -+ } -+ - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT, - &mOffscreenTexture, pShareHandle); --- -1.8.1.msysgit.1 - diff --git a/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch b/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch new file mode 100644 index 0000000000..2c95c5bcfa --- /dev/null +++ b/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch @@ -0,0 +1,68 @@ +From 9b24b25eeb5ca97d7978c6840fdb1e903bf63a55 Mon Sep 17 00:00:00 2001 +From: Friedemann Kleint +Date: Tue, 18 Feb 2014 09:52:52 +0200 +Subject: [PATCH] Make it possible to link ANGLE statically for + single-thread use. + +Fix exports and provide static instances of thread-local +data depending on QT_OPENGL_ES_2_ANGLE_STATIC. + +Change-Id: Ifab25a820adf5953bb3b09036de53dbf7f1a7fd5 +--- + src/3rdparty/angle/include/KHR/khrplatform.h | 2 +- + src/3rdparty/angle/src/libEGL/main.cpp | 6 ++++++ + src/3rdparty/angle/src/libGLESv2/main.cpp | 6 ++++++ + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h +index c9e6f17..1ac2d3f 100644 +--- a/src/3rdparty/angle/include/KHR/khrplatform.h ++++ b/src/3rdparty/angle/include/KHR/khrplatform.h +@@ -97,7 +97,7 @@ + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +-#if defined(_WIN32) && !defined(__SCITECH_SNAP__) ++#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) + # define KHRONOS_APICALL __declspec(dllimport) + #elif defined (__SYMBIAN32__) + # define KHRONOS_APICALL IMPORT_C +diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp +index 80dcc34..772b8eb 100644 +--- a/src/3rdparty/angle/src/libEGL/main.cpp ++++ b/src/3rdparty/angle/src/libEGL/main.cpp +@@ -106,7 +106,13 @@ namespace egl + + Current *GetCurrentData() + { ++#ifndef QT_OPENGL_ES_2_ANGLE_STATIC + Current *current = (Current*)TlsGetValue(currentTLS); ++#else ++ // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. ++ static Current s_current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; ++ Current *current = &s_current; ++#endif + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. +diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp +index 50e2593..6b459d3 100644 +--- a/src/3rdparty/angle/src/libGLESv2/main.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/main.cpp +@@ -89,7 +89,13 @@ namespace gl + + Current *GetCurrentData() + { ++#ifndef QT_OPENGL_ES_2_ANGLE_STATIC + Current *current = (Current*)TlsGetValue(currentTLS); ++#else ++ // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. ++ static Current s_current = { 0, 0 }; ++ Current *current = &s_current; ++#endif + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. +-- +1.8.4.msysgit.0 + diff --git a/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch b/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch index 840f6dc36e..475ec55b0e 100644 --- a/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch +++ b/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch @@ -1,6 +1,6 @@ -From af7cb8e35774f5cba15256cb463da8c1c4d533f3 Mon Sep 17 00:00:00 2001 +From cebc37237a74a130dffaefad0a10da17abc42981 Mon Sep 17 00:00:00 2001 From: Andy Shaw -Date: Sat, 14 Sep 2013 11:25:53 +0300 +Date: Tue, 18 Feb 2014 09:59:17 +0200 Subject: [PATCH] Fix build when SSE2 is not available. Although SSE2 support is detected at runtime it still may not be @@ -9,15 +9,15 @@ when it is available at build time too. Change-Id: I86c45a6466ab4cec79aa0f62b0d5230a78ad825a --- - src/3rdparty/angle/src/libGLESv2/mathutil.h | 2 ++ - src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp | 4 ++++ - 2 files changed, 6 insertions(+) + src/3rdparty/angle/src/libGLESv2/mathutil.h | 2 ++ + src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp | 6 +++++- + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h -index bb48b94..0835486 100644 +index f902131..6474b66 100644 --- a/src/3rdparty/angle/src/libGLESv2/mathutil.h +++ b/src/3rdparty/angle/src/libGLESv2/mathutil.h -@@ -93,6 +93,7 @@ inline bool supportsSSE2() +@@ -92,6 +92,7 @@ inline bool supportsSSE2() return supports; } @@ -25,7 +25,7 @@ index bb48b94..0835486 100644 int info[4]; __cpuid(info, 0); -@@ -102,6 +103,7 @@ inline bool supportsSSE2() +@@ -101,6 +102,7 @@ inline bool supportsSSE2() supports = (info[3] >> 26) & 1; } @@ -33,10 +33,10 @@ index bb48b94..0835486 100644 checked = true; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp -index b3dcc59..53030b7 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp +index 8511946..cd12d8c 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp @@ -373,11 +373,13 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heigh switch (mInternalFormat) { @@ -65,6 +65,13 @@ index b3dcc59..53030b7 100644 { loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); } +@@ -729,4 +733,4 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, + mDirty = true; + } + +-} +\ No newline at end of file ++} -- -1.8.1.msysgit.1 +1.8.4.msysgit.0 diff --git a/src/angle/patches/0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch b/src/angle/patches/0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch similarity index 84% rename from src/angle/patches/0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch rename to src/angle/patches/0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch index 9189501b59..cf31245b95 100644 --- a/src/angle/patches/0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch +++ b/src/angle/patches/0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch @@ -1,7 +1,8 @@ -From 6d8be1da6a5a5177289200247f98e0200e0e3df3 Mon Sep 17 00:00:00 2001 +From 68ba96d224a84389567f506661a78c32b307e84d Mon Sep 17 00:00:00 2001 From: Kai Koehne -Date: Sat, 14 Sep 2013 11:38:47 +0300 -Subject: [PATCH] Fix compilation of libGLESv2 with older MinGW-w64 headers +Date: Tue, 18 Feb 2014 10:29:14 +0200 +Subject: [PATCH] Fix compilation of libGLESv2 with older MinGW-w64 + headers Fix compilation of libGLESv2 for mingw-headers predating MinGW-w64 svn commit 5567 (like MinGW-builds gcc 4.7.2-rev8, the toolchain @@ -18,18 +19,18 @@ Change-Id: I31272a1a991c4fc0f1611f8fb7510be51d6bb925 1 file changed, 19 insertions(+) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -index 70b9326..d1d234b 100644 +index 3407353..e74120d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -@@ -21,6 +21,25 @@ - #define ANGLE_ENABLE_D3D11 0 +@@ -24,6 +24,25 @@ + #define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) #endif +#ifdef __MINGW32__ + +#ifndef D3DCOMPILER_DLL + -+//Add define + typedefs for older MinGW-w64 headers (pre 5783) ++// Add define + typedefs for older MinGW-w64 headers (pre 5783) + +#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" + @@ -48,5 +49,5 @@ index 70b9326..d1d234b 100644 { -- -1.8.1.msysgit.1 +1.8.4.msysgit.0 diff --git a/src/angle/patches/0006-Make-DX9-DX11-mutually-exclusive.patch b/src/angle/patches/0006-Make-DX9-DX11-mutually-exclusive.patch deleted file mode 100644 index 1e618d43c7..0000000000 --- a/src/angle/patches/0006-Make-DX9-DX11-mutually-exclusive.patch +++ /dev/null @@ -1,149 +0,0 @@ -From c2eb5746cdf65091932558ac48ae1e6175d45a3c Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Sat, 14 Sep 2013 12:01:19 +0300 -Subject: [PATCH] Make DX9/DX11 mutually exclusive - -ANGLE supports selecting the renderer on creation, choosing between -D3D11 and D3D9 backends. This patch removes that feature, and makes the -D3D version a compile-time decision. This makes the binary size smaller -(no extra render is built) and ensures compatibility with Windows Runtime, -which supports only Direct3D 11. - -Change-Id: Id9473e0e631721083fe4026d475e37603a144c37 ---- - src/3rdparty/angle/src/common/RefCountObject.cpp | 1 - - src/3rdparty/angle/src/common/debug.cpp | 4 +++ - src/3rdparty/angle/src/libGLESv2/Texture.cpp | 6 +++- - src/3rdparty/angle/src/libGLESv2/precompiled.h | 3 ++ - .../angle/src/libGLESv2/renderer/Renderer.cpp | 37 +++++++--------------- - 5 files changed, 24 insertions(+), 27 deletions(-) - -diff --git a/src/3rdparty/angle/src/common/RefCountObject.cpp b/src/3rdparty/angle/src/common/RefCountObject.cpp -index 0364adf..c1ef90c 100644 ---- a/src/3rdparty/angle/src/common/RefCountObject.cpp -+++ b/src/3rdparty/angle/src/common/RefCountObject.cpp -@@ -1,4 +1,3 @@ --#include "precompiled.h" - // - // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. - // Use of this source code is governed by a BSD-style license that can be -diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp -index 2333740..9b93256 100644 ---- a/src/3rdparty/angle/src/common/debug.cpp -+++ b/src/3rdparty/angle/src/common/debug.cpp -@@ -8,7 +8,11 @@ - - #include "common/debug.h" - #include "common/system.h" -+#ifndef ANGLE_ENABLE_D3D11 - #include -+#else -+typedef DWORD D3DCOLOR; -+#endif - - namespace gl - { -diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp -index ae83037..72c0a8a 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp -@@ -14,7 +14,11 @@ - #include "libGLESv2/main.h" - #include "libGLESv2/mathutil.h" - #include "libGLESv2/utilities.h" --#include "libGLESv2/renderer/Blit.h" -+#ifndef ANGLE_ENABLE_D3D11 -+# include "libGLESv2/renderer/Blit.h" -+#else -+# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN -+#endif - #include "libGLESv2/Renderbuffer.h" - #include "libGLESv2/renderer/Image.h" - #include "libGLESv2/renderer/Renderer.h" -diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h -index a850d57..50dec6b 100644 ---- a/src/3rdparty/angle/src/libGLESv2/precompiled.h -+++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h -@@ -32,9 +32,12 @@ - #include - #include - -+#ifndef ANGLE_ENABLE_D3D11 - #include -+#else - #include - #include -+#endif - #include - - #ifdef _MSC_VER -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -index d1d234b..21ad223 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -@@ -11,8 +11,11 @@ - #include "libGLESv2/main.h" - #include "libGLESv2/Program.h" - #include "libGLESv2/renderer/Renderer.h" -+#ifndef ANGLE_ENABLE_D3D11 - #include "libGLESv2/renderer/Renderer9.h" -+#else - #include "libGLESv2/renderer/Renderer11.h" -+#endif - #include "libGLESv2/utilities.h" - #include "third_party/trace_event/trace_event.h" - -@@ -21,6 +24,10 @@ - #define ANGLE_ENABLE_D3D11 0 - #endif - -+#ifndef D3DERR_OUTOFVIDEOMEMORY -+#define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) -+#endif -+ - #ifdef __MINGW32__ - - #ifndef D3DCOMPILER_DLL -@@ -192,34 +199,14 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayT - { - rx::Renderer *renderer = NULL; - EGLint status = EGL_BAD_ALLOC; -- -- if (ANGLE_ENABLE_D3D11 || -- displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || -- displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) -- { -- renderer = new rx::Renderer11(display, hDc); -- -- if (renderer) -- { -- status = renderer->initialize(); -- } -- -- if (status == EGL_SUCCESS) -- { -- return renderer; -- } -- else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) -- { -- return NULL; -- } -- -- // Failed to create a D3D11 renderer, try creating a D3D9 renderer -- delete renderer; -- } - -+#if ANGLE_ENABLE_D3D11 -+ renderer = new rx::Renderer11(display, hDc); -+#else - bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); - renderer = new rx::Renderer9(display, hDc, softwareDevice); -- -+#endif -+ - if (renderer) - { - status = renderer->initialize(); --- -1.8.1.msysgit.1 - diff --git a/src/angle/patches/0007-ANGLE-Fix-typedefs-for-Win64.patch b/src/angle/patches/0007-ANGLE-Fix-typedefs-for-Win64.patch deleted file mode 100644 index 5779d68e70..0000000000 --- a/src/angle/patches/0007-ANGLE-Fix-typedefs-for-Win64.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 2c7319083bc7bac6faafdf29b3a1d5440abf1313 Mon Sep 17 00:00:00 2001 -From: Jonathan Liu -Date: Sat, 14 Sep 2013 11:32:01 +0300 -Subject: [PATCH] ANGLE: Fix typedefs for Win64 - -The long int type is incorrect for Windows 64-bit as LLP64 is used -there. - -Change-Id: Ibbe6f94bffd511ab1285020c89874021a762c2af ---- - src/3rdparty/angle/include/KHR/khrplatform.h | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h -index 541bfa9..001e925 100644 ---- a/src/3rdparty/angle/include/KHR/khrplatform.h -+++ b/src/3rdparty/angle/include/KHR/khrplatform.h -@@ -221,10 +221,17 @@ typedef signed char khronos_int8_t; - typedef unsigned char khronos_uint8_t; - typedef signed short int khronos_int16_t; - typedef unsigned short int khronos_uint16_t; -+#ifdef _WIN64 -+typedef signed long long int khronos_intptr_t; -+typedef unsigned long long int khronos_uintptr_t; -+typedef signed long long int khronos_ssize_t; -+typedef unsigned long long int khronos_usize_t; -+#else - typedef signed long int khronos_intptr_t; - typedef unsigned long int khronos_uintptr_t; - typedef signed long int khronos_ssize_t; - typedef unsigned long int khronos_usize_t; -+#endif - - #if KHRONOS_SUPPORT_FLOAT - /* --- -1.8.1.msysgit.1 - diff --git a/src/angle/patches/0007-Make-DX9-DX11-mutually-exclusive.patch b/src/angle/patches/0007-Make-DX9-DX11-mutually-exclusive.patch new file mode 100644 index 0000000000..25a2f12847 --- /dev/null +++ b/src/angle/patches/0007-Make-DX9-DX11-mutually-exclusive.patch @@ -0,0 +1,141 @@ +From e1b26c6669cafb5c1298d6e5476c24686fccf1bd Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Thu, 20 Feb 2014 16:46:15 +0200 +Subject: [PATCH] Make DX9/DX11 support configurable + +ANGLE supports selecting the renderer on creation, choosing between +D3D11 and D3D9 backends. This patch improves upon this by enabling the +D3D backend(s) at compile time. This can make the binary size smaller +(no extra render is built) and ensures compatibility with Windows Runtime +when building only the D3D11 renderer. + +Change-Id: Id9473e0e631721083fe4026d475e37603a144c37 +--- + src/3rdparty/angle/src/libEGL/Display.cpp | 4 +++- + src/3rdparty/angle/src/libGLESv2/Texture.cpp | 6 +++++- + src/3rdparty/angle/src/libGLESv2/precompiled.h | 10 +++++++--- + .../angle/src/libGLESv2/renderer/Renderer.cpp | 19 +++++++++++++------ + 4 files changed, 28 insertions(+), 11 deletions(-) + +diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp +index 13ef701..a7f5f5a 100644 +--- a/src/3rdparty/angle/src/libEGL/Display.cpp ++++ b/src/3rdparty/angle/src/libEGL/Display.cpp +@@ -471,7 +471,6 @@ bool Display::hasExistingWindowSurface(HWND window) + + void Display::initExtensionString() + { +- HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + bool shareHandleSupported = mRenderer->getShareHandleSupport(); + + mExtensionString = ""; +@@ -487,10 +486,13 @@ void Display::initExtensionString() + + mExtensionString += "EGL_ANGLE_query_surface_pointer "; + ++#if defined(ANGLE_ENABLE_D3D9) ++ HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + if (swiftShader) + { + mExtensionString += "EGL_ANGLE_software_display "; + } ++#endif + + if (shareHandleSupported) + { +diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp +index 3deecaf..3257d05 100644 +--- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp +@@ -14,7 +14,11 @@ + #include "libGLESv2/main.h" + #include "libGLESv2/mathutil.h" + #include "libGLESv2/utilities.h" +-#include "libGLESv2/renderer/d3d9/Blit.h" ++#if defined(ANGLE_ENABLE_D3D9) ++# include "libGLESv2/renderer/d3d9/Blit.h" ++#else ++# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN ++#endif + #include "libGLESv2/Renderbuffer.h" + #include "libGLESv2/renderer/Image.h" + #include "libGLESv2/renderer/Renderer.h" +diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h +index 58ad181..79490b1 100644 +--- a/src/3rdparty/angle/src/libGLESv2/precompiled.h ++++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h +@@ -32,9 +32,13 @@ + #include + #include + +-#include +-#include +-#include ++#if defined(ANGLE_ENABLE_D3D9) ++# include ++#endif ++#if defined(ANGLE_ENABLE_D3D11) ++# include ++# include ++#endif + #include + + #ifdef _MSC_VER +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +index 86be93f..3407353 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +@@ -11,14 +11,17 @@ + #include "libGLESv2/main.h" + #include "libGLESv2/Program.h" + #include "libGLESv2/renderer/Renderer.h" +-#include "libGLESv2/renderer/d3d9/Renderer9.h" +-#include "libGLESv2/renderer/d3d11/Renderer11.h" ++#if defined(ANGLE_ENABLE_D3D9) ++# include "libGLESv2/renderer/d3d9/Renderer9.h" ++#endif ++#if defined(ANGLE_ENABLE_D3D11) ++# include "libGLESv2/renderer/d3d11/Renderer11.h" ++#endif + #include "libGLESv2/utilities.h" + #include "third_party/trace_event/trace_event.h" + +-#if !defined(ANGLE_ENABLE_D3D11) +-// Enables use of the Direct3D 11 API for a default display, when available +-#define ANGLE_ENABLE_D3D11 0 ++#ifndef D3DERR_OUTOFVIDEOMEMORY ++#define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) + #endif + + namespace rx +@@ -177,7 +180,8 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayT + rx::Renderer *renderer = NULL; + EGLint status = EGL_BAD_ALLOC; + +- if (ANGLE_ENABLE_D3D11 || ++#if defined(ANGLE_ENABLE_D3D11) ++ if (displayId == EGL_DEFAULT_DISPLAY || + displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { +@@ -200,7 +204,9 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayT + // Failed to create a D3D11 renderer, try creating a D3D9 renderer + delete renderer; + } ++#endif // ANGLE_ENABLE_D3D11 + ++#if defined(ANGLE_ENABLE_D3D9) + bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); + renderer = new rx::Renderer9(display, hDc, softwareDevice); + +@@ -213,6 +219,7 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayT + { + return renderer; + } ++#endif // ANGLE_ENABLE_D3D9 + + return NULL; + } +-- +1.8.4.msysgit.0 + diff --git a/src/angle/patches/0008-ANGLE-DX11-Prevent-assert-when-view-is-minimized-or-.patch b/src/angle/patches/0008-ANGLE-DX11-Prevent-assert-when-view-is-minimized-or-.patch deleted file mode 100644 index 10b36c2096..0000000000 --- a/src/angle/patches/0008-ANGLE-DX11-Prevent-assert-when-view-is-minimized-or-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 6f4600a842bbc7438c8d330305de82b960598ad3 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Sun, 15 Sep 2013 00:18:44 +0300 -Subject: [PATCH] ANGLE DX11: Prevent assert when view is minimized or size - goes to 0x0 - -This allows the Direct3D 11 version of ANGLE to gracefully allow -surfaces with dimensions of 0. This is important because Qt may resize -the surface to 0x0 because of window minimization or other user -action (window resize). As EGL specifies that empty (0x0) surfaces are -valid, this makes sure an assert doesn't occur in the case that a valid -surface is resized to an empty one. - -Change-Id: Ia60c4c694090d03c1da7f43c56e90b925c8eab6d ---- - src/3rdparty/angle/src/libEGL/Surface.cpp | 9 ++++++++- - src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp | 3 +++ - 2 files changed, 11 insertions(+), 1 deletion(-) - -diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp -index 311790c..b47a7bc 100644 ---- a/src/3rdparty/angle/src/libEGL/Surface.cpp -+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp -@@ -135,9 +135,16 @@ bool Surface::resetSwapChain() - - bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) - { -- ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); - ASSERT(mSwapChain); - -+ // Prevent bad swap chain resize by calling reset if size is invalid -+ if (backbufferWidth < 1 || backbufferHeight < 1) -+ { -+ mWidth = backbufferWidth; -+ mHeight = backbufferHeight; -+ return mSwapChain->reset(0, 0, mSwapInterval) == EGL_SUCCESS; -+ } -+ - EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); - - if (status == EGL_CONTEXT_LOST) -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -index a50db3b..0da58cb 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -@@ -369,6 +369,9 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) - return EGL_BAD_ACCESS; - } - -+ if (!mSwapChain) -+ reset(backbufferWidth, backbufferHeight, mSwapInterval); -+ - // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); - --- -1.8.1.msysgit.1 - diff --git a/src/angle/patches/0015-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch b/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch similarity index 63% rename from src/angle/patches/0015-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch rename to src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch index 1955e12bf3..c7cfafc246 100644 --- a/src/angle/patches/0015-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch +++ b/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-of-k.patch @@ -1,6 +1,6 @@ -From 806fbe22a3515792b6716b5072a2131e2ce3437a Mon Sep 17 00:00:00 2001 +From 0fede57f6fc052942b910995fdfa4cd76a32f586 Mon Sep 17 00:00:00 2001 From: Andrew Knight -Date: Sat, 7 Dec 2013 23:57:39 +0200 +Date: Tue, 18 Feb 2014 12:11:45 +0200 Subject: [PATCH] ANGLE: Dynamically load D3D compiler from a list or the environment @@ -11,36 +11,29 @@ QT_D3DCOMPILER_DLL. Change-Id: I0d7a8a8a36cc571836f8fa59ea14513b9b19c19b --- - .../angle/src/libGLESv2/renderer/Renderer.cpp | 44 ++++++++++++++++++---- - 1 file changed, 36 insertions(+), 8 deletions(-) + .../angle/src/libGLESv2/renderer/Renderer.cpp | 34 ++++++++++++++++++++-- + 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -index 7ba183d..39fd0f4 100644 +index e74120d..94cbc0e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -@@ -29,12 +29,12 @@ - #endif +@@ -43,6 +43,10 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const + + #endif // __MINGW32__ - #ifndef D3DCOMPILER_DLL --#ifndef ANGLE_OS_WINPHONE - #define D3DCOMPILER_DLL L"d3dcompiler_43.dll" // Lowest common denominator --#else --#define D3DCOMPILER_DLL L"qtd3dcompiler.dll" // Placeholder DLL for phone --#endif // ANGLE_OS_WINPHONE --#endif // D3DCOMPILER_DLL -+#endif -+ +#ifndef QT_D3DCOMPILER_DLL +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#endif ++ + namespace rx + { - #if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) - -@@ -83,12 +83,40 @@ bool Renderer::initializeCompiler() - } +@@ -77,10 +81,36 @@ bool Renderer::initializeCompiler() } - #else -- // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. + #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + +- if (!mD3dCompilerModule) + // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL +#if !defined(ANGLE_OS_WINRT) + const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); @@ -66,18 +59,13 @@ index 7ba183d..39fd0f4 100644 + + // Load the first available known compiler DLL + for (int i = 0; compilerDlls[i]; ++i) -+ { - #if !defined(ANGLE_OS_WINRT) -- mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL); + { + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. +- mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL); + mD3dCompilerModule = LoadLibrary(compilerDlls[i]); - #else -- mD3dCompilerModule = LoadPackagedLibrary(D3DCOMPILER_DLL, NULL); -+ mD3dCompilerModule = LoadPackagedLibrary(compilerDlls[i], NULL); - #endif + if (mD3dCompilerModule) + break; -+ } - #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + } if (!mD3dCompilerModule) -- diff --git a/src/angle/patches/0012-ANGLE-Support-WinRT.patch b/src/angle/patches/0009-ANGLE-Support-WinRT.patch similarity index 55% rename from src/angle/patches/0012-ANGLE-Support-WinRT.patch rename to src/angle/patches/0009-ANGLE-Support-WinRT.patch index 8a5b96c7c0..92909d37d8 100644 --- a/src/angle/patches/0012-ANGLE-Support-WinRT.patch +++ b/src/angle/patches/0009-ANGLE-Support-WinRT.patch @@ -1,10 +1,10 @@ -From 67c318c7b9c6d95d3170d11956dbec56494511ca Mon Sep 17 00:00:00 2001 +From 46b8b123ada1787c68525cd07dcdbfdbc003bcc5 Mon Sep 17 00:00:00 2001 From: Andrew Knight -Date: Tue, 1 Oct 2013 09:43:29 +0300 +Date: Thu, 20 Feb 2014 16:49:13 +0200 Subject: [PATCH] ANGLE: Support WinRT This enables EGL for WinRT's native types, and adjusts some codepaths -to accommodate differences in between desktop Windows and WinRT. +to accommodate differences between desktop Windows and WinRT. - WinRT native handles added to eglplatform.h - References to native handles in libEGL/libGLESv2 follow eglplatform.h @@ -16,31 +16,32 @@ Change-Id: Ia90377e700d335a1c569c2145008dd4b0dfd84d3 Reviewed-by: Friedemann Kleint --- src/3rdparty/angle/include/EGL/eglplatform.h | 10 ++- - src/3rdparty/angle/src/compiler/osinclude.h | 35 ++++------ - src/3rdparty/angle/src/compiler/ossource_posix.cpp | 8 +++ - src/3rdparty/angle/src/compiler/ossource_win.cpp | 8 +++ - src/3rdparty/angle/src/compiler/ossource_winrt.cpp | 75 ++++++++++++++++++++++ - src/3rdparty/angle/src/libEGL/Display.cpp | 8 ++- - src/3rdparty/angle/src/libEGL/Display.h | 4 +- - src/3rdparty/angle/src/libEGL/Surface.cpp | 35 +++++++++- - src/3rdparty/angle/src/libEGL/Surface.h | 7 +- + .../angle/src/compiler/translator/osinclude.h | 20 +++--- + .../src/compiler/translator/ossource_posix.cpp | 8 +++ + .../angle/src/compiler/translator/ossource_win.cpp | 8 +++ + .../src/compiler/translator/ossource_winrt.cpp | 75 ++++++++++++++++++++++ + src/3rdparty/angle/src/libEGL/Display.cpp | 11 ++-- + src/3rdparty/angle/src/libEGL/Display.h | 7 +- + src/3rdparty/angle/src/libEGL/Surface.cpp | 42 +++++++++++- + src/3rdparty/angle/src/libEGL/Surface.h | 6 +- src/3rdparty/angle/src/libEGL/libEGL.cpp | 4 +- - src/3rdparty/angle/src/libEGL/main.cpp | 40 ++++++++++-- - src/3rdparty/angle/src/libGLESv2/main.cpp | 39 +++++++++-- - src/3rdparty/angle/src/libGLESv2/precompiled.h | 15 +++++ - .../angle/src/libGLESv2/renderer/Renderer.cpp | 23 ++++--- - .../angle/src/libGLESv2/renderer/Renderer.h | 27 +++++++- - .../angle/src/libGLESv2/renderer/Renderer11.cpp | 10 ++- - .../angle/src/libGLESv2/renderer/Renderer11.h | 2 +- - .../angle/src/libGLESv2/renderer/SwapChain.h | 4 +- - .../angle/src/libGLESv2/renderer/SwapChain11.cpp | 29 +++++++-- - .../angle/src/libGLESv2/renderer/SwapChain11.h | 2 +- - src/3rdparty/angle/src/libGLESv2/utilities.cpp | 53 +++++++++++++++ - src/angle/src/common/common.pri | 2 +- - src/angle/src/compiler/translator_common.pro | 7 +- - src/angle/src/config.pri | 5 +- - 24 files changed, 386 insertions(+), 66 deletions(-) - create mode 100644 src/3rdparty/angle/src/compiler/ossource_winrt.cpp + src/3rdparty/angle/src/libEGL/main.cpp | 29 ++++++++- + src/3rdparty/angle/src/libGLESv2/Context.cpp | 1 + + src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 1 + + src/3rdparty/angle/src/libGLESv2/main.cpp | 27 ++++++++ + src/3rdparty/angle/src/libGLESv2/main.h | 2 +- + src/3rdparty/angle/src/libGLESv2/precompiled.h | 45 ++++++++++++- + .../angle/src/libGLESv2/renderer/Renderer.cpp | 15 +++-- + .../angle/src/libGLESv2/renderer/Renderer.h | 3 +- + .../angle/src/libGLESv2/renderer/SwapChain.h | 5 +- + .../src/libGLESv2/renderer/d3d11/Renderer11.cpp | 13 +++- + .../src/libGLESv2/renderer/d3d11/Renderer11.h | 5 +- + .../src/libGLESv2/renderer/d3d11/SwapChain11.cpp | 37 +++++++++-- + .../src/libGLESv2/renderer/d3d11/SwapChain11.h | 2 +- + .../libGLESv2/renderer/d3d11/shaders/Clear11.hlsl | 4 ++ + src/3rdparty/angle/src/libGLESv2/utilities.cpp | 48 ++++++++++++++ + 25 files changed, 378 insertions(+), 50 deletions(-) + create mode 100644 src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h index 34283f2..eb15ae5 100644 @@ -63,17 +64,14 @@ index 34283f2..eb15ae5 100644 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif -diff --git a/src/3rdparty/angle/src/compiler/osinclude.h b/src/3rdparty/angle/src/compiler/osinclude.h -index d8bb1a7..60177d5 100644 ---- a/src/3rdparty/angle/src/compiler/osinclude.h -+++ b/src/3rdparty/angle/src/compiler/osinclude.h -@@ -13,27 +13,26 @@ +diff --git a/src/3rdparty/angle/src/compiler/translator/osinclude.h b/src/3rdparty/angle/src/compiler/translator/osinclude.h +index c3063d6..cccfa63 100644 +--- a/src/3rdparty/angle/src/compiler/translator/osinclude.h ++++ b/src/3rdparty/angle/src/compiler/translator/osinclude.h +@@ -13,7 +13,11 @@ // #if defined(_WIN32) || defined(_WIN64) -+#define STRICT -+#define VC_EXTRALEAN 1 -+#include +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +#define ANGLE_OS_WINRT +#else @@ -81,31 +79,17 @@ index d8bb1a7..60177d5 100644 +#endif #elif defined(__APPLE__) || defined(__linux__) || \ defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__sun) || defined(ANDROID) || \ - defined(__GLIBC__) || defined(__GNU__) || \ - defined(__QNX__) - #define ANGLE_OS_POSIX --#else --#error Unsupported platform. --#endif -- + defined(__NetBSD__) || defined(__DragonFly__) || \ +@@ -25,7 +29,7 @@ + #error Unsupported platform. + #endif + -#if defined(ANGLE_OS_WIN) --#define STRICT --#define VC_EXTRALEAN 1 --#include --#elif defined(ANGLE_OS_POSIX) - #include - #include - #include --#endif // ANGLE_OS_WIN -- -+#else -+#error Unsupported platform. -+#endif - - #include "compiler/debug.h" - -@@ -43,23 +42,17 @@ ++#if defined(ANGLE_OS_WIN) || defined(ANGLE_OS_WINRT) + #define STRICT + #define VC_EXTRALEAN 1 + #include +@@ -44,23 +48,17 @@ #if defined(ANGLE_OS_WIN) typedef DWORD OS_TLSIndex; #define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) @@ -133,10 +117,10 @@ index d8bb1a7..60177d5 100644 -} - #endif // __OSINCLUDE_H -diff --git a/src/3rdparty/angle/src/compiler/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/ossource_posix.cpp -index 1e1e699..35510c1 100644 ---- a/src/3rdparty/angle/src/compiler/ossource_posix.cpp -+++ b/src/3rdparty/angle/src/compiler/ossource_posix.cpp +diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp +index 90a3757..d4bba4c 100644 +--- a/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp ++++ b/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp @@ -33,6 +33,14 @@ OS_TLSIndex OS_AllocTLSIndex() } @@ -152,10 +136,10 @@ index 1e1e699..35510c1 100644 bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) { if (nIndex == OS_INVALID_TLS_INDEX) { -diff --git a/src/3rdparty/angle/src/compiler/ossource_win.cpp b/src/3rdparty/angle/src/compiler/ossource_win.cpp -index 89922fe..708a1ad 100644 ---- a/src/3rdparty/angle/src/compiler/ossource_win.cpp -+++ b/src/3rdparty/angle/src/compiler/ossource_win.cpp +diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp +index 2cc5871..abd8bc7 100644 +--- a/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp ++++ b/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp @@ -29,6 +29,14 @@ OS_TLSIndex OS_AllocTLSIndex() } @@ -171,11 +155,11 @@ index 89922fe..708a1ad 100644 bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) { if (nIndex == OS_INVALID_TLS_INDEX) { -diff --git a/src/3rdparty/angle/src/compiler/ossource_winrt.cpp b/src/3rdparty/angle/src/compiler/ossource_winrt.cpp +diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp new file mode 100644 -index 0000000..84443ab +index 0000000..bb061ca --- /dev/null -+++ b/src/3rdparty/angle/src/compiler/ossource_winrt.cpp ++++ b/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. @@ -183,7 +167,7 @@ index 0000000..84443ab +// found in the LICENSE file. +// + -+#include "compiler/osinclude.h" ++#include "compiler/translator/osinclude.h" +// +// This file contains contains Windows Runtime specific functions +// @@ -253,10 +237,40 @@ index 0000000..84443ab + return true; +} diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp -index a382c3b..14973af 100644 +index a7f5f5a..e75a4b6 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp -@@ -186,7 +186,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) +@@ -1,3 +1,4 @@ ++#include "../libGLESv2/precompiled.h" + // + // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be +@@ -40,13 +41,13 @@ egl::Display *Display::getDisplay(EGLNativeDisplayType displayId) + + // FIXME: Check if displayId is a valid display device context + +- egl::Display *display = new egl::Display(displayId, (HDC)displayId); ++ egl::Display *display = new egl::Display(displayId); + + displays[displayId] = display; + return display; + } + +-Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext) ++Display::Display(EGLNativeDisplayType displayId) + { + mDisplayId = displayId; + mRenderer = NULL; +@@ -71,7 +72,7 @@ bool Display::initialize() + return true; + } + +- mRenderer = glCreateRenderer(this, mDc, mDisplayId); ++ mRenderer = glCreateRenderer(this, mDisplayId); + + if (!mRenderer) + { +@@ -186,7 +187,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) @@ -265,7 +279,7 @@ index a382c3b..14973af 100644 { const Config *configuration = mConfigSet.get(config); EGLint postSubBufferSupported = EGL_FALSE; -@@ -456,7 +456,7 @@ bool Display::isValidSurface(egl::Surface *surface) +@@ -456,7 +457,7 @@ bool Display::isValidSurface(egl::Surface *surface) return mSurfaceSet.find(surface) != mSurfaceSet.end(); } @@ -274,33 +288,11 @@ index a382c3b..14973af 100644 { for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) { -@@ -471,7 +471,6 @@ bool Display::hasExistingWindowSurface(HWND window) - - void Display::initExtensionString() - { -- HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); - bool shareHandleSupported = mRenderer->getShareHandleSupport(); - - mExtensionString = ""; -@@ -487,10 +486,13 @@ void Display::initExtensionString() - - mExtensionString += "EGL_ANGLE_query_surface_pointer "; - -+#if !defined(ANGLE_OS_WINRT) -+ HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); - if (swiftShader) - { - mExtensionString += "EGL_ANGLE_software_display "; - } -+#endif - - if (shareHandleSupported) - { diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h -index 58c3940..5d55410 100644 +index c816e4e..cd07bb3 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h -@@ -40,7 +40,7 @@ class Display +@@ -38,7 +38,7 @@ class Display bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); @@ -309,7 +301,7 @@ index 58c3940..5d55410 100644 EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList); EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess); -@@ -51,7 +51,7 @@ class Display +@@ -49,7 +49,7 @@ class Display bool isValidConfig(EGLConfig config); bool isValidContext(gl::Context *context); bool isValidSurface(egl::Surface *surface); @@ -318,11 +310,30 @@ index 58c3940..5d55410 100644 rx::Renderer *getRenderer() { return mRenderer; }; +@@ -63,12 +63,11 @@ class Display + private: + DISALLOW_COPY_AND_ASSIGN(Display); + +- Display(EGLNativeDisplayType displayId, HDC deviceContext); ++ Display(EGLNativeDisplayType displayId); + + bool restoreLostDevice(); + + EGLNativeDisplayType mDisplayId; +- const HDC mDc; + + bool mSoftwareDevice; + diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp -index b47a7bc..abc6d7d 100644 +index 12f8dfd..3443355 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp -@@ -20,10 +20,15 @@ +@@ -1,3 +1,4 @@ ++#include "../libGLESv2/precompiled.h" + // + // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be +@@ -22,10 +23,15 @@ #include "libEGL/main.h" #include "libEGL/Display.h" @@ -334,12 +345,12 @@ index b47a7bc..abc6d7d 100644 namespace egl { --Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) +-Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) +Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported) : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) { mRenderer = mDisplay->getRenderer(); -@@ -96,6 +101,7 @@ bool Surface::resetSwapChain() +@@ -98,6 +104,7 @@ bool Surface::resetSwapChain() if (mWindow) { @@ -347,14 +358,16 @@ index b47a7bc..abc6d7d 100644 RECT windowRect; if (!GetClientRect(getWindowHandle(), &windowRect)) { -@@ -107,6 +113,14 @@ bool Surface::resetSwapChain() +@@ -109,6 +116,16 @@ bool Surface::resetSwapChain() width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; +#else + ABI::Windows::Foundation::Rect windowRect; + ABI::Windows::UI::Core::ICoreWindow *window; -+ ASSERT(SUCCEEDED(mWindow->QueryInterface(IID_PPV_ARGS(&window)))); ++ HRESULT hr = mWindow->QueryInterface(IID_PPV_ARGS(&window)); ++ if (FAILED(hr)) ++ return false; + window->get_Bounds(&windowRect); + width = windowRect.Width; + height = windowRect.Height; @@ -362,7 +375,7 @@ index b47a7bc..abc6d7d 100644 } else { -@@ -226,7 +240,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +@@ -221,7 +238,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return true; } @@ -371,7 +384,7 @@ index b47a7bc..abc6d7d 100644 { return mWindow; } -@@ -235,6 +249,7 @@ HWND Surface::getWindowHandle() +@@ -230,6 +247,7 @@ HWND Surface::getWindowHandle() #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") @@ -379,7 +392,7 @@ index b47a7bc..abc6d7d 100644 static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { if (message == WM_SIZE) -@@ -248,9 +263,13 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam +@@ -243,9 +261,13 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); } @@ -393,7 +406,7 @@ index b47a7bc..abc6d7d 100644 if (!mWindow) { return; -@@ -274,10 +293,12 @@ void Surface::subclassWindow() +@@ -269,10 +291,12 @@ void Surface::subclassWindow() SetProp(mWindow, kSurfaceProperty, reinterpret_cast(this)); SetProp(mWindow, kParentWndProc, reinterpret_cast(oldWndProc)); mWindowSubclassed = true; @@ -406,7 +419,7 @@ index b47a7bc..abc6d7d 100644 if(!mWindowSubclassed) { return; -@@ -300,10 +321,12 @@ void Surface::unsubclassWindow() +@@ -295,10 +319,12 @@ void Surface::unsubclassWindow() RemoveProp(mWindow, kSurfaceProperty); RemoveProp(mWindow, kParentWndProc); mWindowSubclassed = false; @@ -419,34 +432,38 @@ index b47a7bc..abc6d7d 100644 RECT client; if (!GetClientRect(getWindowHandle(), &client)) { -@@ -314,6 +337,14 @@ bool Surface::checkForOutOfDateSwapChain() +@@ -309,14 +335,26 @@ bool Surface::checkForOutOfDateSwapChain() // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. int clientWidth = client.right - client.left; int clientHeight = client.bottom - client.top; +#else + ABI::Windows::Foundation::Rect windowRect; + ABI::Windows::UI::Core::ICoreWindow *window; -+ ASSERT(SUCCEEDED(mWindow->QueryInterface(IID_PPV_ARGS(&window)))); ++ HRESULT hr = mWindow->QueryInterface(IID_PPV_ARGS(&window)); ++ if (FAILED(hr)) ++ return false; + window->get_Bounds(&windowRect); + int clientWidth = windowRect.Width; + int clientHeight = windowRect.Height; +#endif bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - if (mSwapIntervalDirty) ++#if !defined(ANGLE_OS_WINRT) + if (IsIconic(getWindowHandle())) + { + // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized + // because that's not a useful size to render to. + sizeDirty = false; + } ++#endif + + bool wasDirty = (mSwapIntervalDirty || sizeDirty); + diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h -index 938b800..ae9a380 100644 +index 938b800..1d2303c 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ b/src/3rdparty/angle/src/libEGL/Surface.h -@@ -15,6 +15,7 @@ - #include - - #include "common/angleutils.h" -+#include "windows.h" - - namespace gl - { -@@ -34,7 +35,7 @@ class Config; +@@ -34,7 +34,7 @@ class Config; class Surface { public: @@ -455,7 +472,7 @@ index 938b800..ae9a380 100644 Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); ~Surface(); -@@ -43,7 +44,7 @@ class Surface +@@ -43,7 +43,7 @@ class Surface void release(); bool resetSwapChain(); @@ -464,17 +481,17 @@ index 938b800..ae9a380 100644 bool swap(); bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); -@@ -79,7 +80,7 @@ private: +@@ -79,7 +79,7 @@ private: bool resetSwapChain(int backbufferWidth, int backbufferHeight); bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - const HWND mWindow; // Window that the surface is created for. -+ const EGLNativeWindowType mWindow; // Window that the surface is created for. ++ const EGLNativeWindowType mWindow; // Window that the surface is created for. bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking const egl::Config *mConfig; // EGL config surface was created with EGLint mHeight; // Height of surface diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp -index 6e10c39..5bcb5d5 100644 +index 0ea46d4..b2944d5 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -308,14 +308,16 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG @@ -496,7 +513,7 @@ index 6e10c39..5bcb5d5 100644 catch(std::bad_alloc&) { diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp -index 7dea5fc..964b4b2 100644 +index 772b8eb..e972691 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -1,3 +1,4 @@ @@ -504,24 +521,67 @@ index 7dea5fc..964b4b2 100644 // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be -@@ -12,7 +13,13 @@ +@@ -10,14 +11,23 @@ - #ifndef QT_OPENGL_ES_2_ANGLE_STATIC + #include "common/debug.h" +#if !defined(ANGLE_OS_WINRT) static DWORD currentTLS = TLS_OUT_OF_INDEXES; +#else +static __declspec(thread) void *currentTLS = 0; +#endif -+ -+namespace egl { Current *getCurrent(); } - extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) + namespace egl { -@@ -35,22 +42,25 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved + + Current *AllocateCurrent() + { ++#if !defined(ANGLE_OS_WINRT) + Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); ++#else ++ currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current)); ++ Current *current = (egl::Current*)currentTLS; ++#endif + + if (!current) + { +@@ -25,8 +35,10 @@ Current *AllocateCurrent() + return NULL; + } + ++#if !defined(ANGLE_OS_WINRT) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + TlsSetValue(currentTLS, current); ++#endif + + current->error = EGL_SUCCESS; + current->API = EGL_OPENGL_ES_API; +@@ -39,12 +51,20 @@ Current *AllocateCurrent() + + void DeallocateCurrent() + { ++#if !defined(ANGLE_OS_WINRT) + void *current = TlsGetValue(currentTLS); + + if (current) + { + LocalFree((HLOCAL)current); + } ++#else ++ if (currentTLS) ++ { ++ HeapFree(GetProcessHeap(), 0, currentTLS); ++ currentTLS = 0; ++ } ++#endif + } + + } +@@ -69,13 +89,14 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved + } } #endif - +- +#if !defined(ANGLE_OS_WINRT) currentTLS = TlsAlloc(); @@ -533,94 +593,114 @@ index 7dea5fc..964b4b2 100644 } // Fall throught to initialize index case DLL_THREAD_ATTACH: - { -- egl::Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); -+ egl::Current *current = egl::getCurrent(); - - if (current) - { -+#if !defined(ANGLE_OS_WINRT) - TlsSetValue(currentTLS, current); -- -+#endif - current->error = EGL_SUCCESS; - current->API = EGL_OPENGL_ES_API; - current->display = EGL_NO_DISPLAY; -@@ -61,24 +71,35 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - break; - case DLL_THREAD_DETACH: - { -- void *current = TlsGetValue(currentTLS); -+ egl::Current *current = egl::getCurrent(); - - if (current) - { -+#if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); -+#else -+ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); -+ currentTLS = 0; -+#endif - } - } - break; +@@ -91,7 +112,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved case DLL_PROCESS_DETACH: { -- void *current = TlsGetValue(currentTLS); -+ egl::Current *current = egl::getCurrent(); - - if (current) - { + egl::DeallocateCurrent(); +#if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); - } - TlsFree(currentTLS); -+#else -+ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); -+ currentTLS = 0; -+ } +#endif } break; default: -@@ -95,7 +116,16 @@ namespace egl - Current *getCurrent() +@@ -107,8 +130,12 @@ namespace egl + Current *GetCurrentData() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC -- return (Current*)TlsGetValue(currentTLS); +#if !defined(ANGLE_OS_WINRT) -+ Current *current = (Current*)TlsGetValue(currentTLS); -+ if (!current) -+ current = (Current*)LocalAlloc(LPTR, sizeof(Current)); -+ return current; -+#else -+ if (!currentTLS) -+ currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); -+ return (Current*)currentTLS; -+#endif + Current *current = (Current*)TlsGetValue(currentTLS); #else ++ Current *current = (Current*)currentTLS; ++#endif ++#else // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; + static Current s_current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; + Current *current = &s_current; +diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp +index 1a058b6..e651785 100644 +--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp +@@ -1076,6 +1076,7 @@ void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum inter + case GL_RGB565: + case GL_RGB8_OES: + case GL_RGBA8_OES: ++ case GL_BGRA8_EXT: + renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples); + break; + case GL_STENCIL_INDEX8: +diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +index a33481e..814dfbf 100644 +--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +@@ -4895,6 +4895,7 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp + case GL_RGBA8_OES: + case GL_STENCIL_INDEX8: + case GL_DEPTH24_STENCIL8_OES: ++ case GL_BGRA8_EXT: + context->setRenderbufferStorage(width, height, internalformat, samples); + break; + default: diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp -index 730a6ac..defdf35 100644 +index 6b459d3..95f4b8d 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp -@@ -13,7 +13,13 @@ +@@ -11,14 +11,23 @@ - #ifndef QT_OPENGL_ES_2_ANGLE_STATIC + #include "libGLESv2/Context.h" +#if !defined(ANGLE_OS_WINRT) static DWORD currentTLS = TLS_OUT_OF_INDEXES; +#else +static __declspec(thread) void *currentTLS = 0; +#endif -+ -+namespace gl { Current *getCurrent(); } - extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) + namespace gl { -@@ -21,22 +27,25 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved + + Current *AllocateCurrent() + { ++#if !defined(ANGLE_OS_WINRT) + Current *current = (Current*)LocalAlloc(LPTR, sizeof(Current)); ++#else ++ currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current)); ++ Current *current = (Current*)currentTLS; ++#endif + + if (!current) + { +@@ -26,8 +35,10 @@ Current *AllocateCurrent() + return NULL; + } + ++#if !defined(ANGLE_OS_WINRT) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + TlsSetValue(currentTLS, current); ++#endif + + current->context = NULL; + current->display = NULL; +@@ -37,12 +48,20 @@ Current *AllocateCurrent() + + void DeallocateCurrent() + { ++#if !defined(ANGLE_OS_WINRT) + void *current = TlsGetValue(currentTLS); + + if (current) + { + LocalFree((HLOCAL)current); + } ++#else ++ if (currentTLS) ++ { ++ HeapFree(GetProcessHeap(), 0, currentTLS); ++ currentTLS = 0; ++ } ++#endif + } + + } +@@ -53,12 +72,14 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved { case DLL_PROCESS_ATTACH: { @@ -635,178 +715,77 @@ index 730a6ac..defdf35 100644 } // Fall throught to initialize index case DLL_THREAD_ATTACH: - { -- gl::Current *current = (gl::Current*)LocalAlloc(LPTR, sizeof(gl::Current)); -+ gl::Current *current = gl::getCurrent(); - - if (current) - { -+#if !defined(ANGLE_OS_WINRT) - TlsSetValue(currentTLS, current); -- -+#endif - current->context = NULL; - current->display = NULL; - } -@@ -44,24 +53,35 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - break; - case DLL_THREAD_DETACH: - { -- void *current = TlsGetValue(currentTLS); -+ gl::Current *current = gl::getCurrent(); - - if (current) - { -+#if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); -+#else -+ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); -+ currentTLS = 0; -+#endif - } - } - break; +@@ -74,7 +95,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved case DLL_PROCESS_DETACH: { -- void *current = TlsGetValue(currentTLS); -+ gl::Current *current = gl::getCurrent(); - - if (current) - { + gl::DeallocateCurrent(); +#if !defined(ANGLE_OS_WINRT) - LocalFree((HLOCAL)current); - } - TlsFree(currentTLS); -+#else -+ HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, current); -+ currentTLS = 0; -+ } +#endif } break; default: -@@ -78,7 +98,16 @@ namespace gl - Current *getCurrent() +@@ -90,8 +113,12 @@ namespace gl + Current *GetCurrentData() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC -- return (Current*)TlsGetValue(currentTLS); +#if !defined(ANGLE_OS_WINRT) -+ Current *current = (Current*)TlsGetValue(currentTLS); -+ if (!current) -+ current = (Current*)LocalAlloc(LPTR, sizeof(Current)); -+ return current; -+#else -+ if (!currentTLS) -+ currentTLS = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, sizeof(Current)); -+ return (Current*)currentTLS; -+#endif + Current *current = (Current*)TlsGetValue(currentTLS); #else ++ Current *current = (Current*)currentTLS; ++#endif ++#else // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static gl::Current curr = { 0, 0 }; + static Current s_current = { 0, 0 }; + Current *current = &s_current; +diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h +index b413f23..69465c9 100644 +--- a/src/3rdparty/angle/src/libGLESv2/main.h ++++ b/src/3rdparty/angle/src/libGLESv2/main.h +@@ -57,7 +57,7 @@ gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *rend + void glDestroyContext(gl::Context *context); + void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); + gl::Context *glGetCurrentContext(); +-rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId); ++rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId); + void glDestroyRenderer(rx::Renderer *renderer); + + __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h -index 50dec6b..823d27b 100644 +index 79490b1..2ff09f5 100644 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.h +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h -@@ -32,13 +32,28 @@ +@@ -32,14 +32,55 @@ #include #include +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -+#define ANGLE_OS_WINRT -+#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+#define ANGLE_OS_WINPHONE -+#endif ++# define ANGLE_OS_WINRT ++# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP ++# define ANGLE_OS_WINPHONE ++# endif +#endif + - #ifndef ANGLE_ENABLE_D3D11 - #include - #else -+#if !defined(ANGLE_OS_WINRT) - #include -+#else -+#include -+#define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) -+#define GetVersion() WINVER -+#endif - #include + #if defined(ANGLE_ENABLE_D3D9) + # include #endif -+#ifndef ANGLE_OS_WINPHONE - #include -+#endif - - #ifdef _MSC_VER - #include -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -index 21ad223..7ba183d 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -@@ -28,13 +28,18 @@ - #define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) + #if defined(ANGLE_ENABLE_D3D11) +-# include ++# if !defined(ANGLE_OS_WINRT) ++# include ++# else ++# include ++# define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) ++# define GetVersion() WINVER ++# define LoadLibrary(x) LoadPackagedLibrary(x, NULL) ++# endif + # include #endif - --#ifdef __MINGW32__ -- - #ifndef D3DCOMPILER_DLL -+#ifndef ANGLE_OS_WINPHONE -+#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" // Lowest common denominator -+#else -+#define D3DCOMPILER_DLL L"qtd3dcompiler.dll" // Placeholder DLL for phone -+#endif // ANGLE_OS_WINPHONE -+#endif // D3DCOMPILER_DLL - --//Add define + typedefs for older MinGW-w64 headers (pre 5783) -+#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) - --#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" -+//Add define + typedefs for older MinGW-w64 headers (pre 5783) -+//Also define these on Windows Phone, which doesn't have a shader compiler - - HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, - const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, -@@ -43,9 +48,7 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const - const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, - const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); - --#endif // D3DCOMPILER_DLL -- --#endif // __MINGW32__ -+#endif // __MINGW32__ || ANGLE_OS_WINPHONE - - namespace rx - { -@@ -81,7 +84,11 @@ bool Renderer::initializeCompiler() - } - #else - // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. -+#if !defined(ANGLE_OS_WINRT) - mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL); -+#else -+ mD3dCompilerModule = LoadPackagedLibrary(D3DCOMPILER_DLL, NULL); +-#include ++#if !defined(ANGLE_OS_WINPHONE) ++# include +#endif - #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES - - if (!mD3dCompilerModule) -@@ -225,4 +232,4 @@ void glDestroyRenderer(rx::Renderer *renderer) - delete renderer; - } - --} -\ No newline at end of file -+} -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h -index 04e877b..ac67c27 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h -@@ -1,3 +1,4 @@ -+#include "../precompiled.h" - // - // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. - // Use of this source code is governed by a BSD-style license that can be -@@ -13,6 +14,30 @@ - #include "libGLESv2/Uniform.h" - #include "libGLESv2/angletypes.h" - ++ +#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0 +#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14) +#endif @@ -831,10 +810,75 @@ index 04e877b..ac67c27 100644 +#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL +#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10) +#endif - #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) - #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 + + #ifdef _MSC_VER + #include +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +index 94cbc0e..5278113 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +@@ -24,7 +24,7 @@ + #define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) #endif -@@ -107,7 +132,7 @@ class Renderer + +-#ifdef __MINGW32__ ++#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) + + #ifndef D3DCOMPILER_DLL + +@@ -41,7 +41,7 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const + + #endif // D3DCOMPILER_DLL + +-#endif // __MINGW32__ ++#endif // __MINGW32__ || ANGLE_OS_WINPHONE + + #ifndef QT_D3DCOMPILER_DLL + #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +@@ -224,17 +224,22 @@ ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, co + extern "C" + { + +-rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId) ++rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId) + { + rx::Renderer *renderer = NULL; + EGLint status = EGL_BAD_ALLOC; + ++#if defined(ANGLE_OS_WINRT) ++ if (displayId == EGL_DEFAULT_DISPLAY) ++ displayId = EGL_D3D11_ONLY_DISPLAY_ANGLE; ++#endif ++ + #if defined(ANGLE_ENABLE_D3D11) + if (displayId == EGL_DEFAULT_DISPLAY || + displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { +- renderer = new rx::Renderer11(display, hDc); ++ renderer = new rx::Renderer11(display); + + if (renderer) + { +@@ -257,7 +262,7 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayT + + #if defined(ANGLE_ENABLE_D3D9) + bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); +- renderer = new rx::Renderer9(display, hDc, softwareDevice); ++ renderer = new rx::Renderer9(display, displayId, softwareDevice); + + if (renderer) + { +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +index 7244a0a..79578b2 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +@@ -1,3 +1,4 @@ ++#include "../precompiled.h" + // + // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be +@@ -113,7 +114,7 @@ class Renderer virtual void sync(bool block) = 0; @@ -843,10 +887,46 @@ index 04e877b..ac67c27 100644 virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp -index a431018..d04467b 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +index f09f19b..8231fbc 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +@@ -1,3 +1,4 @@ ++#include "../precompiled.h" + // + // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be +@@ -22,7 +23,7 @@ namespace rx + class SwapChain + { + public: +- SwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) ++ SwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) + { + } +@@ -37,7 +38,7 @@ class SwapChain + virtual HANDLE getShareHandle() {return mShareHandle;}; + + protected: +- const HWND mWindow; // Window that the surface is created for. ++ const EGLNativeWindowType mWindow; // Window that the surface is created for. + const GLenum mBackBufferFormat; + const GLenum mDepthBufferFormat; + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +index d9fcb7a..7f166fd 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +@@ -66,7 +66,7 @@ enum + MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 + }; + +-Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc) ++Renderer11::Renderer11(egl::Display *display) : Renderer(display) + { + mVertexDataManager = NULL; + mIndexDataManager = NULL; @@ -137,6 +137,7 @@ EGLint Renderer11::initialize() return EGL_NOT_INITIALIZED; } @@ -855,7 +935,15 @@ index a431018..d04467b 100644 mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); -@@ -155,6 +156,7 @@ EGLint Renderer11::initialize() +@@ -146,6 +147,7 @@ EGLint Renderer11::initialize() + return EGL_NOT_INITIALIZED; + } + ++ + // create the D3D11 device + ASSERT(mDevice == NULL); + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); +@@ -155,6 +157,7 @@ EGLint Renderer11::initialize() ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); return EGL_NOT_INITIALIZED; } @@ -863,7 +951,7 @@ index a431018..d04467b 100644 D3D_FEATURE_LEVEL featureLevels[] = { -@@ -203,8 +205,12 @@ EGLint Renderer11::initialize() +@@ -203,8 +206,12 @@ EGLint Renderer11::initialize() } } @@ -877,7 +965,7 @@ index a431018..d04467b 100644 if (FAILED(result)) { -@@ -524,7 +530,7 @@ void Renderer11::sync(bool block) +@@ -522,7 +529,7 @@ void Renderer11::sync(bool block) } } @@ -886,10 +974,19 @@ index a431018..d04467b 100644 { return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); } -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h -index f024855..a7f5a39 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +index 1b6760b..ba3f0c6 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +@@ -39,7 +39,7 @@ enum + class Renderer11 : public Renderer + { + public: +- Renderer11(egl::Display *display, HDC hDc); ++ Renderer11(egl::Display *display); + virtual ~Renderer11(); + + static Renderer11 *makeRenderer11(Renderer *renderer); @@ -52,7 +52,7 @@ class Renderer11 : public Renderer virtual void sync(bool block); @@ -899,33 +996,19 @@ index f024855..a7f5a39 100644 virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -index 14c0515..a6870eb 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -@@ -18,7 +18,7 @@ namespace rx - class SwapChain - { - public: -- SwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) -+ SwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) - : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) - { - } -@@ -33,7 +33,7 @@ class SwapChain - virtual HANDLE getShareHandle() {return mShareHandle;}; +@@ -203,7 +203,6 @@ class Renderer11 : public Renderer - protected: -- const HWND mWindow; // Window that the surface is created for. -+ const EGLNativeWindowType mWindow; // Window that the surface is created for. - const GLenum mBackBufferFormat; - const GLenum mDepthBufferFormat; + HMODULE mD3d11Module; + HMODULE mDxgiModule; +- HDC mDc; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -index 0da58cb..0797fd7 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -@@ -17,7 +17,7 @@ + bool mDeviceLost; + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp +index d2b53a7..bd97d5c 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp +@@ -18,7 +18,7 @@ namespace rx { @@ -934,15 +1017,20 @@ index 0da58cb..0797fd7 100644 GLenum backBufferFormat, GLenum depthBufferFormat) : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) { -@@ -468,6 +468,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap +@@ -361,25 +361,50 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap if (mWindow) { +#if !defined(ANGLE_OS_WINRT) - // We cannot create a swap chain for an HWND that is owned by a different process - DWORD currentProcessId = GetCurrentProcessId(); - DWORD wndProcessId; -@@ -491,14 +492,34 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap + IDXGIFactory *factory = mRenderer->getDxgiFactory(); + + DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; +- swapChainDesc.BufferCount = 2; + swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + swapChainDesc.BufferDesc.Width = backbufferWidth; + swapChainDesc.BufferDesc.Height = backbufferHeight; ++ swapChainDesc.BufferCount = 2; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; @@ -954,14 +1042,18 @@ index 0da58cb..0797fd7 100644 + ASSERT(SUCCEEDED(result)); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; -+ swapChainDesc.BufferCount = 2; + swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + swapChainDesc.Width = backbufferWidth; + swapChainDesc.Height = backbufferHeight; + swapChainDesc.Stereo = FALSE; ++#if !defined(ANGLE_OS_WINPHONE) ++ swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; ++#else ++ swapChainDesc.BufferCount = 1; ++ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; ++#endif +#endif -+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.Flags = 0; - swapChainDesc.OutputWindow = mWindow; @@ -969,9 +1061,8 @@ index 0da58cb..0797fd7 100644 swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.Windowed = TRUE; -- HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); +#if !defined(ANGLE_OS_WINRT) -+ result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); +#else + IDXGISwapChain1 *swapChain; + result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); @@ -980,10 +1071,28 @@ index 0da58cb..0797fd7 100644 if (FAILED(result)) { -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h +@@ -390,6 +415,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap + { + return EGL_CONTEXT_LOST; + } ++#if !defined(ANGLE_OS_WINRT) + else + { + // We cannot create a swap chain for an HWND that is owned by a different process on some versions of +@@ -408,6 +434,9 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap + return EGL_BAD_ALLOC; + } + } ++#else ++ return EGL_BAD_ALLOC; ++#endif + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h index 8001046..2a030c8 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h @@ -19,7 +19,7 @@ class Renderer11; class SwapChain11 : public SwapChain { @@ -993,52 +1102,89 @@ index 8001046..2a030c8 100644 GLenum backBufferFormat, GLenum depthBufferFormat); virtual ~SwapChain11(); +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl +index 042ac69..cb132dc 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl +@@ -12,10 +12,12 @@ struct PS_OutputMultiple + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; ++#ifdef SM4 + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float4 color7 : SV_TARGET7; ++#endif + }; + + PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +@@ -25,10 +27,12 @@ PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; ++#ifdef SM4 + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; ++#endif + return outColor; + } + diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp -index 32df49e..8fd193b 100644 +index 32df49e..30765ff 100644 --- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp +++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp -@@ -10,6 +10,14 @@ +@@ -9,6 +9,14 @@ + #include "libGLESv2/utilities.h" #include "libGLESv2/mathutil.h" - +#if defined(ANGLE_OS_WINRT) -+#include -+#include -+#include -+#include -+using namespace ABI::Windows::Storage; ++# include ++# include ++# include ++# include ++ using namespace Microsoft::WRL; ++ using namespace ABI::Windows::Storage; +#endif -+ + namespace gl { - -@@ -737,7 +745,50 @@ bool IsTriangleMode(GLenum drawMode) +@@ -737,6 +745,7 @@ bool IsTriangleMode(GLenum drawMode) std::string getTempPath() { -+#if defined(ANGLE_OS_WINRT) -+ ++#if !defined(ANGLE_OS_WINRT) + char path[MAX_PATH]; + DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); + if (pathLen == 0) +@@ -751,6 +760,45 @@ std::string getTempPath() + UNREACHABLE(); + return std::string(); + } ++#else + static std::string path; + + while (path.empty()) { -+ IApplicationDataStatics *applicationDataFactory; -+ HRESULT result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), -+ IID_PPV_ARGS(&applicationDataFactory)); ++ ComPtr factory; ++ Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); ++ HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); + if (FAILED(result)) + break; + -+ IApplicationData *applicationData; -+ result = applicationDataFactory->get_Current(&applicationData); ++ ComPtr applicationData; ++ result = factory->get_Current(&applicationData); + if (FAILED(result)) + break; + -+ IStorageFolder *storageFolder; ++ ComPtr storageFolder; + result = applicationData->get_LocalFolder(&storageFolder); + if (FAILED(result)) + break; + -+ IStorageItem *localFolder; -+ result = storageFolder->QueryInterface(IID_PPV_ARGS(&localFolder)); ++ ComPtr localFolder; ++ result = storageFolder.As(&localFolder); + if (FAILED(result)) + break; + @@ -1055,77 +1201,10 @@ index 32df49e..8fd193b 100644 + break; + } + } -+ -+#else -+ - char path[MAX_PATH]; -+ - DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); - if (pathLen == 0) - { -@@ -751,6 +802,8 @@ std::string getTempPath() - UNREACHABLE(); - return std::string(); - } -+ +#endif return path; } -diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri -index a94b9a6..12e26a9 100644 ---- a/src/angle/src/common/common.pri -+++ b/src/angle/src/common/common.pri -@@ -7,7 +7,7 @@ INCLUDEPATH += \ - LIBS = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_GUI - - # DirectX is included in the Windows 8 Kit, but everything else requires the DX SDK. --win32-msvc2012 { -+win32-msvc2012|winrt { - FXC = fxc.exe - } else { - DX_DIR = $$(DXSDK_DIR) -diff --git a/src/angle/src/compiler/translator_common.pro b/src/angle/src/compiler/translator_common.pro -index b281215..5581c9d 100644 ---- a/src/angle/src/compiler/translator_common.pro -+++ b/src/angle/src/compiler/translator_common.pro -@@ -78,7 +78,6 @@ SOURCES += \ - $$ANGLE_DIR/src/compiler/intermOut.cpp \ - $$ANGLE_DIR/src/compiler/IntermTraverse.cpp \ - $$ANGLE_DIR/src/compiler/MapLongVariableNames.cpp \ -- $$ANGLE_DIR/src/compiler/ossource_win.cpp \ - $$ANGLE_DIR/src/compiler/parseConst.cpp \ - $$ANGLE_DIR/src/compiler/ParseHelper.cpp \ - $$ANGLE_DIR/src/compiler/PoolAlloc.cpp \ -@@ -98,6 +97,12 @@ SOURCES += \ - $$ANGLE_DIR/src/compiler/timing/RestrictVertexShaderTiming.cpp \ - $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp - -+winrt { -+ SOURCES += $$ANGLE_DIR/src/compiler/ossource_winrt.cpp -+} else { -+ SOURCES += $$ANGLE_DIR/src/compiler/ossource_win.cpp -+} -+ - # NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin - flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} - flex.output = ${QMAKE_FILE_BASE}_lex.cpp -diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri -index 1c6d8b0..ed25581 100644 ---- a/src/angle/src/config.pri -+++ b/src/angle/src/config.pri -@@ -37,8 +37,9 @@ DEFINES += _WINDOWS \ - NOMINMAX \ - WIN32_LEAN_AND_MEAN=1 - --# Defines specifying the API version (0x0600 = Vista) --DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 -+# Defines specifying the API version (0x0600 = Vista, 0x0602 = Win8)) -+winrt: DEFINES += _WIN32_WINNT=0x0602 WINVER=0x0602 -+else: DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 - - # ANGLE specific defines - DEFINES += ANGLE_DISABLE_TRACE \ -- 1.8.4.msysgit.0 diff --git a/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch b/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch new file mode 100644 index 0000000000..34c881ba21 --- /dev/null +++ b/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch @@ -0,0 +1,426 @@ +From e84f947df4ae095eae600550749b3a4e8de5ee8b Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Thu, 20 Feb 2014 16:51:36 +0200 +Subject: [PATCH] ANGLE: Enable D3D11 for feature level 9 cards + +Enable use of ANGLE on lower-end hardware, such as Surface RT and +Windows Phone 8. + +Based on https://codereview.appspot.com/12917046/ + +Change-Id: Ice536802e4eedc1d264abd0dd65960638fce59e4 +--- + .../angle/src/libGLESv2/renderer/d3d11/Image11.cpp | 7 +- + .../libGLESv2/renderer/d3d11/RenderStateCache.cpp | 5 +- + .../src/libGLESv2/renderer/d3d11/Renderer11.cpp | 90 ++++++++++++++++++++-- + .../src/libGLESv2/renderer/d3d11/Renderer11.h | 1 + + .../libGLESv2/renderer/d3d11/TextureStorage11.cpp | 10 +-- + .../libGLESv2/renderer/d3d11/renderer11_utils.cpp | 4 +- + .../libGLESv2/renderer/d3d11/renderer11_utils.h | 2 +- + 7 files changed, 100 insertions(+), 19 deletions(-) + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp +index 2b07b9d..5d039a3 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp +@@ -142,7 +142,7 @@ bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, + mHeight = height; + mInternalFormat = internalformat; + // compute the d3d format that will be used +- mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat); ++ mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); + mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat); + + if (mStagingTexture) +@@ -191,7 +191,10 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig + switch (mInternalFormat) + { + case GL_ALPHA8_EXT: +- loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); ++ if (mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0) ++ loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); ++ else ++ loadAlphaDataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + break; + case GL_LUMINANCE8_EXT: + loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp +index 0047e04..a1c324c 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp +@@ -419,7 +419,8 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset); +- samplerDesc.MaxLOD = gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset); ++ samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ++ ? gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset) : FLT_MAX; + + ID3D11SamplerState *dx11SamplerState = NULL; + HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); +@@ -435,4 +436,4 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa + } + } + +-} +\ No newline at end of file ++} +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +index 7f166fd..31d976d 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +@@ -164,6 +164,11 @@ EGLint Renderer11::initialize() + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, ++#if !defined(ANGLE_ENABLE_D3D9) ++ D3D_FEATURE_LEVEL_9_3, ++ D3D_FEATURE_LEVEL_9_2, ++ D3D_FEATURE_LEVEL_9_1, ++#endif + }; + + HRESULT result = S_OK; +@@ -1533,7 +1538,7 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra + } + + // needed for the point sprite geometry shader +- if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) ++ if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + { + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; +@@ -1956,6 +1961,11 @@ bool Renderer11::testDeviceResettable() + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, ++#if !defined(ANGLE_ENABLE_D3D9) ++ D3D_FEATURE_LEVEL_9_3, ++ D3D_FEATURE_LEVEL_9_2, ++ D3D_FEATURE_LEVEL_9_1, ++#endif + }; + + ID3D11Device* dummyDevice; +@@ -2139,6 +2149,11 @@ float Renderer11::getTextureMaxAnisotropy() const + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_MAX_MAXANISOTROPY; ++ case D3D_FEATURE_LEVEL_9_3: ++ case D3D_FEATURE_LEVEL_9_2: ++ return 16; ++ case D3D_FEATURE_LEVEL_9_1: ++ return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + default: UNREACHABLE(); + return 0; + } +@@ -2158,6 +2173,11 @@ Range Renderer11::getViewportBounds() const + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); ++ case D3D_FEATURE_LEVEL_9_3: ++ return Range(D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: ++ return Range(D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); + default: UNREACHABLE(); + return Range(0, 0); + } +@@ -2172,6 +2192,10 @@ unsigned int Renderer11::getMaxVertexTextureImageUnits() const + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; ++ case D3D_FEATURE_LEVEL_9_3: ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: ++ return 0; + default: UNREACHABLE(); + return 0; + } +@@ -2195,14 +2219,14 @@ unsigned int Renderer11::getReservedFragmentUniformVectors() const + unsigned int Renderer11::getMaxVertexUniformVectors() const + { + META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); +- ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); ++ ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_VERTEX_UNIFORM_VECTORS_D3D11; + } + + unsigned int Renderer11::getMaxFragmentUniformVectors() const + { + META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); +- ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); ++ ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; + } + +@@ -2216,6 +2240,10 @@ unsigned int Renderer11::getMaxVaryingVectors() const + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_VS_OUTPUT_REGISTER_COUNT; ++ case D3D_FEATURE_LEVEL_9_3: ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: ++ return 8; + default: UNREACHABLE(); + return 0; + } +@@ -2229,6 +2257,10 @@ bool Renderer11::getNonPower2TextureSupport() const + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; ++ case D3D_FEATURE_LEVEL_9_3: ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: ++ return false; + default: UNREACHABLE(); + return false; + } +@@ -2242,6 +2274,11 @@ bool Renderer11::getOcclusionQuerySupport() const + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; ++ case D3D_FEATURE_LEVEL_9_3: ++ case D3D_FEATURE_LEVEL_9_2: ++ return true; ++ case D3D_FEATURE_LEVEL_9_1: ++ return false; + default: UNREACHABLE(); + return false; + } +@@ -2254,7 +2291,11 @@ bool Renderer11::getInstancingSupport() const + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: +- return true; ++ case D3D_FEATURE_LEVEL_9_3: ++ return true; ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: ++ return false; + default: UNREACHABLE(); + return false; + } +@@ -2276,6 +2317,11 @@ bool Renderer11::getDerivativeInstructionSupport() const + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return true; ++ case D3D_FEATURE_LEVEL_9_3: ++ return true; ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: ++ return false; + default: UNREACHABLE(); + return false; + } +@@ -2294,6 +2340,9 @@ int Renderer11::getMajorShaderModel() const + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 ++ case D3D_FEATURE_LEVEL_9_3: ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 (level 9) + default: UNREACHABLE(); return 0; + } + } +@@ -2305,6 +2354,9 @@ int Renderer11::getMinorShaderModel() const + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 ++ case D3D_FEATURE_LEVEL_9_3: ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 (level 9) + default: UNREACHABLE(); return 0; + } + } +@@ -2330,6 +2382,11 @@ int Renderer11::getMaxViewportDimension() const + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 ++ case D3D_FEATURE_LEVEL_9_3: ++ return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: ++ return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 + default: UNREACHABLE(); + return 0; + } +@@ -2342,6 +2399,9 @@ int Renderer11::getMaxTextureWidth() const + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 ++ case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 + default: UNREACHABLE(); return 0; + } + } +@@ -2353,6 +2413,9 @@ int Renderer11::getMaxTextureHeight() const + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 ++ case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 + default: UNREACHABLE(); return 0; + } + } +@@ -2364,6 +2427,9 @@ bool Renderer11::get32BitIndexSupport() const + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true ++ case D3D_FEATURE_LEVEL_9_3: ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: return false; + default: UNREACHABLE(); return false; + } + } +@@ -2410,6 +2476,8 @@ unsigned int Renderer11::getMaxRenderTargets() const + { + META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); + META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); ++ META_ASSERT(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); ++ META_ASSERT(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); + + switch (mFeatureLevel) + { +@@ -2417,6 +2485,9 @@ unsigned int Renderer11::getMaxRenderTargets() const + return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: ++ case D3D_FEATURE_LEVEL_9_3: // return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4 ++ case D3D_FEATURE_LEVEL_9_2: ++ case D3D_FEATURE_LEVEL_9_1: // return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1 + // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader + // outputs to multiple RTs that are not bound. + // TODO: Remove pixel shader outputs for render targets that are not bound. +@@ -2603,7 +2674,7 @@ bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectang + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = 0.0f; +- samplerDesc.MaxLOD = 0.0f; ++ samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? 0.0f : FLT_MAX; + + result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler); + ASSERT(SUCCEEDED(result)); +@@ -2848,7 +2919,7 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length + + ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) + { +- const char *profile = NULL; ++ std::string profile; + + switch (type) + { +@@ -2866,7 +2937,12 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch + return NULL; + } + +- ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false); ++ if (mFeatureLevel == D3D_FEATURE_LEVEL_9_3) ++ profile += "_level_9_3"; ++ else if (mFeatureLevel == D3D_FEATURE_LEVEL_9_2 || mFeatureLevel == D3D_FEATURE_LEVEL_9_1) ++ profile += "_level_9_1"; ++ ++ ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile.c_str(), D3DCOMPILE_OPTIMIZATION_LEVEL0, false); + if (!binary) + return NULL; + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +index ba3f0c6..a8a722c 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +@@ -177,6 +177,7 @@ class Renderer11 : public Renderer + ID3D11Device *getDevice() { return mDevice; } + ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; + IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; ++ D3D_FEATURE_LEVEL getFeatureLevel() { return mFeatureLevel; } + + bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); + void unapplyRenderTargets(); +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp +index 5f6ea21..fdfbe52 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp +@@ -222,14 +222,14 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch + } + + TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) +- : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) ++ : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) + { + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + } + +- DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); ++ DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); + if (d3d11::IsDepthStencilFormat(convertedFormat)) + { + mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); +@@ -331,7 +331,7 @@ RenderTarget *TextureStorage11_2D::getRenderTarget(int level) + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = level; +- srvDesc.Texture2D.MipLevels = 1; ++ srvDesc.Texture2D.MipLevels = level ? 1 : -1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); +@@ -440,7 +440,7 @@ void TextureStorage11_2D::generateMipmap(int level) + } + + TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) +- : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) ++ : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) + { + for (unsigned int i = 0; i < 6; i++) + { +@@ -450,7 +450,7 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLe + } + } + +- DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); ++ DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); + if (d3d11::IsDepthStencilFormat(convertedFormat)) + { + mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp +index 6f06024..34b8259 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp +@@ -329,7 +329,7 @@ DXGI_FORMAT ConvertRenderbufferFormat(GLenum format) + return DXGI_FORMAT_R8G8B8A8_UNORM; + } + +-DXGI_FORMAT ConvertTextureFormat(GLenum internalformat) ++DXGI_FORMAT ConvertTextureFormat(GLenum internalformat, D3D_FEATURE_LEVEL featureLevel) + { + switch (internalformat) + { +@@ -342,7 +342,7 @@ DXGI_FORMAT ConvertTextureFormat(GLenum internalformat) + case GL_LUMINANCE8_ALPHA8_EXT: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case GL_ALPHA8_EXT: +- return DXGI_FORMAT_A8_UNORM; ++ return featureLevel >= D3D_FEATURE_LEVEL_10_0 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return DXGI_FORMAT_BC1_UNORM; +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h +index 1bc48c1..70ad4fe 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h +@@ -32,7 +32,7 @@ FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset); + FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset); + + DXGI_FORMAT ConvertRenderbufferFormat(GLenum format); +-DXGI_FORMAT ConvertTextureFormat(GLenum format); ++DXGI_FORMAT ConvertTextureFormat(GLenum format, D3D_FEATURE_LEVEL featureLevel); + } + + namespace d3d11_gl +-- +1.8.4.msysgit.0 + diff --git a/src/angle/patches/0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch b/src/angle/patches/0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch new file mode 100644 index 0000000000..fdee11d324 --- /dev/null +++ b/src/angle/patches/0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch @@ -0,0 +1,37 @@ +From 8ea24fcce69900f42299fd01772714a566f9111e Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Mon, 24 Feb 2014 11:08:23 +0200 +Subject: [PATCH] ANGLE: Fix compilation error on MinGW caused by trace_event.h + +The event trace header in ANGLE's third_party directory has an unused +template which causes a compilation error on MinGW. Disable this part +of the code. + +Change-Id: I167eac56507fafba34e3eb5ce6071d8f136a4e41 +--- + src/3rdparty/angle/src/third_party/trace_event/trace_event.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +index 637cf9a..96ac910 100644 +--- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h ++++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +@@ -791,6 +791,7 @@ private: + // TraceEventSamplingStateScope records the current sampling state + // and sets a new sampling state. When the scope exists, it restores + // the sampling state having recorded. ++#if 0 // This is not used by ANGLE and causes a compilation error on MinGW + template + class SamplingStateScope { + public: +@@ -818,6 +819,7 @@ public: + private: + const char* m_previousState; + }; ++#endif + + } // namespace TraceEvent + +-- +1.8.4.msysgit.0 + diff --git a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch b/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch new file mode 100644 index 0000000000..fe16d1d7b2 --- /dev/null +++ b/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch @@ -0,0 +1,48 @@ +From 15b694fa33cf76f93de62b8106972083f5fb3114 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Fri, 21 Feb 2014 13:34:21 +0200 +Subject: [PATCH] ANGLE: fix semantic index lookup + +The sorted semantic index table was returning a direct mapping to the +new indices, instead of the old indices. This caused a mismatch in the +GL type lookup for the translated attribute. + +Change-Id: I75d05ed707f56c45210e3dcbc277f894e3dc5a48 +--- + src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 2 +- + src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +index 41a83b6..13c515a 100644 +--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +@@ -2643,7 +2643,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + int oldIndex = mAttributesByLayout[i]; +- sortedSemanticIndices[i] = mSemanticIndex[oldIndex]; ++ sortedSemanticIndices[i] = oldIndex; + attributes[i] = oldTranslatedAttributes[oldIndex]; + } + } +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp +index 3418e89..4940b8c 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp +@@ -103,10 +103,10 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M + // Record the type of the associated vertex shader vector in our key + // This will prevent mismatched vertex shaders from using the same input layout + GLint attributeSize; +- programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); ++ programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); + + ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; +- ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i]; ++ ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; + ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT; + ilKey.elements[ilKey.elementCount].desc.InputSlot = i; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; +-- +1.8.4.msysgit.0 + diff --git a/src/angle/patches/0013-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch b/src/angle/patches/0013-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch deleted file mode 100644 index 0a8e403e8d..0000000000 --- a/src/angle/patches/0013-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch +++ /dev/null @@ -1,990 +0,0 @@ -From a71ccc033fe2cf1c3c58633d3bd220c52b744478 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Fri, 8 Nov 2013 09:04:59 +0200 -Subject: [PATCH] ANGLE: Enable D3D11 for feature level 9 cards - -Enable use of ANGLE on lower-end hardware, such as Surface RT and -Windows Phone 8. - -Based on https://codereview.appspot.com/12917046/ - -Change-Id: Ice536802e4eedc1d264abd0dd65960638fce59e4 ---- - src/3rdparty/angle/src/libGLESv2/Buffer.cpp | 8 +- - src/3rdparty/angle/src/libGLESv2/Buffer.h | 4 +- - src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 4 +- - .../angle/src/libGLESv2/renderer/BufferStorage.h | 2 +- - .../src/libGLESv2/renderer/BufferStorage11.cpp | 9 +- - .../angle/src/libGLESv2/renderer/BufferStorage11.h | 2 +- - .../src/libGLESv2/renderer/BufferStorage9.cpp | 2 +- - .../angle/src/libGLESv2/renderer/BufferStorage9.h | 2 +- - .../angle/src/libGLESv2/renderer/Image11.cpp | 7 +- - .../angle/src/libGLESv2/renderer/IndexBuffer11.cpp | 4 +- - .../src/libGLESv2/renderer/RenderStateCache.cpp | 3 +- - .../angle/src/libGLESv2/renderer/Renderer11.cpp | 288 +++++++++++++++------ - .../angle/src/libGLESv2/renderer/Renderer11.h | 2 + - .../angle/src/libGLESv2/renderer/SwapChain11.cpp | 7 +- - .../src/libGLESv2/renderer/TextureStorage11.cpp | 8 +- - .../src/libGLESv2/renderer/renderer11_utils.cpp | 4 +- - .../src/libGLESv2/renderer/renderer11_utils.h | 2 +- - .../src/libGLESv2/renderer/shaders/Clear11.hlsl | 4 + - src/angle/src/libGLESv2/libGLESv2.pro | 8 +- - 19 files changed, 260 insertions(+), 110 deletions(-) - -diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp -index c007d5d..40baa95 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp -@@ -37,11 +37,11 @@ Buffer::~Buffer() - delete mStaticIndexBuffer; - } - --void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) -+void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage, GLenum target) - { - mBufferStorage->clear(); - mIndexRangeCache.clear(); -- mBufferStorage->setData(data, size, 0); -+ mBufferStorage->setData(data, size, 0, target); - - mUsage = usage; - -@@ -54,9 +54,9 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) - } - } - --void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) -+void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset, GLenum target) - { -- mBufferStorage->setData(data, size, offset); -+ mBufferStorage->setData(data, size, offset, target); - mIndexRangeCache.invalidateRange(offset, size); - - if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) -diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h -index 4048f4b..9b86b97 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Buffer.h -+++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h -@@ -33,8 +33,8 @@ class Buffer : public RefCountObject - - virtual ~Buffer(); - -- void bufferData(const void *data, GLsizeiptr size, GLenum usage); -- void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); -+ void bufferData(const void *data, GLsizeiptr size, GLenum usage, GLenum target); -+ void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset, GLenum target); - - GLenum usage() const; - -diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp -index 320bbcc..91719f8 100644 ---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp -@@ -758,7 +758,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, - return gl::error(GL_INVALID_OPERATION); - } - -- buffer->bufferData(data, size, usage); -+ buffer->bufferData(data, size, usage, target); - } - } - catch(std::bad_alloc&) -@@ -812,7 +812,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, - return gl::error(GL_INVALID_VALUE); - } - -- buffer->bufferSubData(data, size, offset); -+ buffer->bufferSubData(data, size, offset, target); - } - } - catch(std::bad_alloc&) -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h -index ace1a11..14a8c27 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h -@@ -22,7 +22,7 @@ class BufferStorage - - // The data returned is only guaranteed valid until next non-const method. - virtual void *getData() = 0; -- virtual void setData(const void* data, unsigned int size, unsigned int offset) = 0; -+ virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target) = 0; - virtual void clear() = 0; - virtual unsigned int getSize() const = 0; - virtual bool supportsDirectBinding() const = 0; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp -index 3647d8a..2f694db 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp -@@ -131,7 +131,7 @@ void *BufferStorage11::getData() - return mResolvedData; - } - --void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset) -+void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset, unsigned int target) - { - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); -@@ -201,7 +201,10 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = requiredBufferSize; - bufferDesc.Usage = D3D11_USAGE_DEFAULT; -- bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER; -+ if (mRenderer->getFeatureLevel() > D3D_FEATURE_LEVEL_9_3) -+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER; -+ else -+ bufferDesc.BindFlags = target == GL_ARRAY_BUFFER ? D3D11_BIND_VERTEX_BUFFER : D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = 0; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; -@@ -324,7 +327,7 @@ unsigned int BufferStorage11::getSize() const - - bool BufferStorage11::supportsDirectBinding() const - { -- return true; -+ return mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0; - } - - void BufferStorage11::markBufferUsage() -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h -index b62348b..c948962 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h -@@ -24,7 +24,7 @@ class BufferStorage11 : public BufferStorage - static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage); - - virtual void *getData(); -- virtual void setData(const void* data, unsigned int size, unsigned int offset); -+ virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp -index e69e7a8..57fd29b 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp -@@ -36,7 +36,7 @@ void *BufferStorage9::getData() - return mMemory; - } - --void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset) -+void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset, unsigned int) - { - if (!mMemory || offset + size > mAllocatedSize) - { -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h -index 3e80396..82ae577 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h -@@ -23,7 +23,7 @@ class BufferStorage9 : public BufferStorage - static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage); - - virtual void *getData(); -- virtual void setData(const void* data, unsigned int size, unsigned int offset); -+ virtual void setData(const void* data, unsigned int size, unsigned int offset, unsigned int target = 0); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp -index 09c8922..81e9e9e 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp -@@ -136,7 +136,7 @@ bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, - mHeight = height; - mInternalFormat = internalformat; - // compute the d3d format that will be used -- mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat); -+ mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat); - - if (mStagingTexture) -@@ -185,7 +185,10 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: -- loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); -+ if (mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0) -+ loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); -+ else -+ loadAlphaDataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE8_EXT: - loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp -index 66604c4..36a62ad 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp -@@ -170,7 +170,7 @@ DXGI_FORMAT IndexBuffer11::getIndexFormat() const - { - case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT; - case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT; -- case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT; -+ case GL_UNSIGNED_INT: return mRenderer->get32BitIndexSupport() ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } - } -@@ -180,4 +180,4 @@ ID3D11Buffer *IndexBuffer11::getBuffer() const - return mBuffer; - } - --} -\ No newline at end of file -+} -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp -index b3111af..fd388df 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp -@@ -387,7 +387,8 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset); -- samplerDesc.MaxLOD = gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset); -+ samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 -+ ? gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset) : FLT_MAX; - - ID3D11SamplerState *dx11SamplerState = NULL; - HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp -index d04467b..f83e9e9 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp -@@ -160,9 +160,13 @@ EGLint Renderer11::initialize() - - D3D_FEATURE_LEVEL featureLevels[] = - { -+ D3D_FEATURE_LEVEL_11_1, - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, -+ D3D_FEATURE_LEVEL_9_3, -+ D3D_FEATURE_LEVEL_9_2, -+ D3D_FEATURE_LEVEL_9_1, - }; - - HRESULT result = S_OK; -@@ -1114,6 +1118,43 @@ void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLv - } - } - -+template -+static void drawLineLoopIndexed(T *data, GLenum type, const GLvoid *indices, GLsizei count) -+{ -+ switch (type) -+ { -+ case GL_NONE: // Non-indexed draw -+ for (int i = 0; i < count; i++) -+ { -+ data[i] = i; -+ } -+ data[count] = 0; -+ break; -+ case GL_UNSIGNED_BYTE: -+ for (int i = 0; i < count; i++) -+ { -+ data[i] = static_cast(indices)[i]; -+ } -+ data[count] = static_cast(indices)[0]; -+ break; -+ case GL_UNSIGNED_SHORT: -+ for (int i = 0; i < count; i++) -+ { -+ data[i] = static_cast(indices)[i]; -+ } -+ data[count] = static_cast(indices)[0]; -+ break; -+ case GL_UNSIGNED_INT: -+ for (int i = 0; i < count; i++) -+ { -+ data[i] = static_cast(indices)[i]; -+ } -+ data[count] = static_cast(indices)[0]; -+ break; -+ default: UNREACHABLE(); -+ } -+} -+ - void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) - { - // Get the raw indices for an indexed draw -@@ -1162,59 +1203,71 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, - return gl::error(GL_OUT_OF_MEMORY); - } - -- unsigned int *data = reinterpret_cast(mappedMemory); -+ if (get32BitIndexSupport()) -+ drawLineLoopIndexed(reinterpret_cast(mappedMemory), type, indices, count); -+ else -+ drawLineLoopIndexed(reinterpret_cast(mappedMemory), type, indices, count); -+ - unsigned int indexBufferOffset = offset; - -+ if (!mLineLoopIB->unmapBuffer()) -+ { -+ ERR("Could not unmap index buffer for GL_LINE_LOOP."); -+ return gl::error(GL_OUT_OF_MEMORY); -+ } -+ -+ if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset) -+ { -+ IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); -+ -+ mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); -+ mAppliedIBSerial = mLineLoopIB->getSerial(); -+ mAppliedStorageIBSerial = 0; -+ mAppliedIBOffset = indexBufferOffset; -+ } -+ -+ mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); -+} -+ -+template -+static void drawTriangleFanIndexed(T *data, GLenum type, const GLvoid *indices, unsigned int numTris) -+{ - switch (type) - { - case GL_NONE: // Non-indexed draw -- for (int i = 0; i < count; i++) -+ for (unsigned int i = 0; i < numTris; i++) - { -- data[i] = i; -+ data[i*3 + 0] = 0; -+ data[i*3 + 1] = i + 1; -+ data[i*3 + 2] = i + 2; - } -- data[count] = 0; - break; - case GL_UNSIGNED_BYTE: -- for (int i = 0; i < count; i++) -+ for (unsigned int i = 0; i < numTris; i++) - { -- data[i] = static_cast(indices)[i]; -+ data[i*3 + 0] = static_cast(indices)[0]; -+ data[i*3 + 1] = static_cast(indices)[i + 1]; -+ data[i*3 + 2] = static_cast(indices)[i + 2]; - } -- data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: -- for (int i = 0; i < count; i++) -+ for (unsigned int i = 0; i < numTris; i++) - { -- data[i] = static_cast(indices)[i]; -+ data[i*3 + 0] = static_cast(indices)[0]; -+ data[i*3 + 1] = static_cast(indices)[i + 1]; -+ data[i*3 + 2] = static_cast(indices)[i + 2]; - } -- data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: -- for (int i = 0; i < count; i++) -+ for (unsigned int i = 0; i < numTris; i++) - { -- data[i] = static_cast(indices)[i]; -+ data[i*3 + 0] = static_cast(indices)[0]; -+ data[i*3 + 1] = static_cast(indices)[i + 1]; -+ data[i*3 + 2] = static_cast(indices)[i + 2]; - } -- data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } -- -- if (!mLineLoopIB->unmapBuffer()) -- { -- ERR("Could not unmap index buffer for GL_LINE_LOOP."); -- return gl::error(GL_OUT_OF_MEMORY); -- } -- -- if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset) -- { -- IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); -- -- mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); -- mAppliedIBSerial = mLineLoopIB->getSerial(); -- mAppliedStorageIBSerial = 0; -- mAppliedIBOffset = indexBufferOffset; -- } -- -- mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); - } - - void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) -@@ -1267,45 +1320,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic - return gl::error(GL_OUT_OF_MEMORY); - } - -- unsigned int *data = reinterpret_cast(mappedMemory); -- unsigned int indexBufferOffset = offset; -+ if (get32BitIndexSupport()) -+ drawTriangleFanIndexed(reinterpret_cast(mappedMemory), type, indices, numTris); -+ else -+ drawTriangleFanIndexed(reinterpret_cast(mappedMemory), type, indices, numTris); - -- switch (type) -- { -- case GL_NONE: // Non-indexed draw -- for (unsigned int i = 0; i < numTris; i++) -- { -- data[i*3 + 0] = 0; -- data[i*3 + 1] = i + 1; -- data[i*3 + 2] = i + 2; -- } -- break; -- case GL_UNSIGNED_BYTE: -- for (unsigned int i = 0; i < numTris; i++) -- { -- data[i*3 + 0] = static_cast(indices)[0]; -- data[i*3 + 1] = static_cast(indices)[i + 1]; -- data[i*3 + 2] = static_cast(indices)[i + 2]; -- } -- break; -- case GL_UNSIGNED_SHORT: -- for (unsigned int i = 0; i < numTris; i++) -- { -- data[i*3 + 0] = static_cast(indices)[0]; -- data[i*3 + 1] = static_cast(indices)[i + 1]; -- data[i*3 + 2] = static_cast(indices)[i + 2]; -- } -- break; -- case GL_UNSIGNED_INT: -- for (unsigned int i = 0; i < numTris; i++) -- { -- data[i*3 + 0] = static_cast(indices)[0]; -- data[i*3 + 1] = static_cast(indices)[i + 1]; -- data[i*3 + 2] = static_cast(indices)[i + 2]; -- } -- break; -- default: UNREACHABLE(); -- } -+ unsigned int indexBufferOffset = offset; - - if (!mTriangleFanIB->unmapBuffer()) - { -@@ -1515,7 +1535,7 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra - } - - // needed for the point sprite geometry shader -- if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) -+ if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) - { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; -@@ -1929,9 +1949,13 @@ bool Renderer11::testDeviceResettable() - - D3D_FEATURE_LEVEL featureLevels[] = - { -+ D3D_FEATURE_LEVEL_11_1, - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, -+ D3D_FEATURE_LEVEL_9_3, -+ D3D_FEATURE_LEVEL_9_2, -+ D3D_FEATURE_LEVEL_9_1, - }; - - ID3D11Device* dummyDevice; -@@ -2110,11 +2134,17 @@ float Renderer11::getTextureMaxAnisotropy() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_MAX_MAXANISOTROPY; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_MAX_MAXANISOTROPY; -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ return 16; -+ case D3D_FEATURE_LEVEL_9_1: -+ return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; - default: UNREACHABLE(); - return 0; - } -@@ -2129,11 +2159,17 @@ Range Renderer11::getViewportBounds() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); -+ case D3D_FEATURE_LEVEL_9_3: -+ return Range(D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return Range(D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); - default: UNREACHABLE(); - return Range(0, 0); - } -@@ -2144,10 +2180,15 @@ unsigned int Renderer11::getMaxVertexTextureImageUnits() const - META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return 0; - default: UNREACHABLE(); - return 0; - } -@@ -2171,15 +2212,41 @@ unsigned int Renderer11::getReservedFragmentUniformVectors() const - unsigned int Renderer11::getMaxVertexUniformVectors() const - { - META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); -- ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); -- return MAX_VERTEX_UNIFORM_VECTORS_D3D11; -+ switch (mFeatureLevel) -+ { -+ case D3D_FEATURE_LEVEL_11_1: -+ case D3D_FEATURE_LEVEL_11_0: -+ case D3D_FEATURE_LEVEL_10_1: -+ case D3D_FEATURE_LEVEL_10_0: -+ return MAX_VERTEX_UNIFORM_VECTORS_D3D11; -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return MAX_VERTEX_UNIFORM_VECTORS_D3D9; -+ default: -+ UNIMPLEMENTED(); -+ return 0; -+ } - } - - unsigned int Renderer11::getMaxFragmentUniformVectors() const - { - META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); -- ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0); -- return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; -+ switch (mFeatureLevel) -+ { -+ case D3D_FEATURE_LEVEL_11_1: -+ case D3D_FEATURE_LEVEL_11_0: -+ case D3D_FEATURE_LEVEL_10_1: -+ case D3D_FEATURE_LEVEL_10_0: -+ return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; -+ case D3D_FEATURE_LEVEL_9_3: -+ return 221; -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return 29; -+ default: UNREACHABLE(); -+ return 0; -+ } - } - - unsigned int Renderer11::getMaxVaryingVectors() const -@@ -2187,11 +2254,17 @@ unsigned int Renderer11::getMaxVaryingVectors() const - META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_VS_OUTPUT_REGISTER_COUNT; - case D3D_FEATURE_LEVEL_10_1: -+ return D3D10_1_VS_OUTPUT_REGISTER_COUNT; - case D3D_FEATURE_LEVEL_10_0: - return D3D10_VS_OUTPUT_REGISTER_COUNT; -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return 8; - default: UNREACHABLE(); - return 0; - } -@@ -2201,10 +2274,15 @@ bool Renderer11::getNonPower2TextureSupport() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return true; -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return false; - default: UNREACHABLE(); - return false; - } -@@ -2214,10 +2292,15 @@ bool Renderer11::getOcclusionQuerySupport() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: - return true; -+ case D3D_FEATURE_LEVEL_9_1: -+ return false; - default: UNREACHABLE(); - return false; - } -@@ -2227,10 +2310,15 @@ bool Renderer11::getInstancingSupport() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: -+ case D3D_FEATURE_LEVEL_9_3: - return true; -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return false; - default: UNREACHABLE(); - return false; - } -@@ -2248,10 +2336,15 @@ bool Renderer11::getDerivativeInstructionSupport() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: -+ case D3D_FEATURE_LEVEL_9_3: - return true; -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return false; - default: UNREACHABLE(); - return false; - } -@@ -2267,9 +2360,13 @@ int Renderer11::getMajorShaderModel() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: return 4; // SM4 level 9, but treat as 4 - default: UNREACHABLE(); return 0; - } - } -@@ -2278,9 +2375,13 @@ int Renderer11::getMinorShaderModel() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: return 0; - default: UNREACHABLE(); return 0; - } - } -@@ -2301,11 +2402,17 @@ int Renderer11::getMaxViewportDimension() const - - switch (mFeatureLevel) - { -- case D3D_FEATURE_LEVEL_11_0: -+ case D3D_FEATURE_LEVEL_11_1: -+ case D3D_FEATURE_LEVEL_11_0: - return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 -+ case D3D_FEATURE_LEVEL_9_3: -+ return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); - return 0; - } -@@ -2315,9 +2422,13 @@ int Renderer11::getMaxTextureWidth() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 -+ case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } - } -@@ -2326,9 +2437,13 @@ int Renderer11::getMaxTextureHeight() const - { - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 -+ case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } - } -@@ -2337,9 +2452,13 @@ bool Renderer11::get32BitIndexSupport() const - { - switch (mFeatureLevel) - { -- case D3D_FEATURE_LEVEL_11_0: -+ case D3D_FEATURE_LEVEL_11_1: -+ case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: return false; - default: UNREACHABLE(); return false; - } - } -@@ -2386,14 +2505,22 @@ unsigned int Renderer11::getMaxRenderTargets() const - { - META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); -+ META_ASSERT(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); -+ META_ASSERT(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - - switch (mFeatureLevel) - { -+ case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: - return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 -+ case D3D_FEATURE_LEVEL_9_3: -+ return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4 -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: -+ return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1 - default: - UNREACHABLE(); - return 1; -@@ -2821,7 +2948,7 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length - - ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type) - { -- const char *profile = NULL; -+ std::string profile; - - switch (type) - { -@@ -2839,7 +2966,12 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch - return NULL; - } - -- ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false); -+ if (mFeatureLevel == D3D_FEATURE_LEVEL_9_3) -+ profile += "_level_9_3"; -+ else if (mFeatureLevel == D3D_FEATURE_LEVEL_9_2 || mFeatureLevel == D3D_FEATURE_LEVEL_9_1) -+ profile += "_level_9_1"; -+ -+ ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile.c_str(), D3DCOMPILE_OPTIMIZATION_LEVEL0, false); - if (!binary) - return NULL; - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h -index a7f5a39..433945d 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h -@@ -32,6 +32,7 @@ class StreamingIndexBufferInterface; - - enum - { -+ MAX_VERTEX_UNIFORM_VECTORS_D3D9 = 254, - MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, - MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 - }; -@@ -177,6 +178,7 @@ class Renderer11 : public Renderer - ID3D11Device *getDevice() { return mDevice; } - ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; - IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; -+ D3D_FEATURE_LEVEL getFeatureLevel() const { return mFeatureLevel; } - - bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); - void unapplyRenderTargets(); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -index 0797fd7..9770772 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -@@ -500,12 +500,17 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap - ASSERT(SUCCEEDED(result)); - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; -- swapChainDesc.BufferCount = 2; - swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - swapChainDesc.Width = backbufferWidth; - swapChainDesc.Height = backbufferHeight; - swapChainDesc.Stereo = FALSE; -+#if !defined(ANGLE_OS_WINPHONE) -+ swapChainDesc.BufferCount = 2; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; -+#else -+ swapChainDesc.BufferCount = 1; -+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; -+#endif - #endif - - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp -index 408b48e..32a407a 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp -@@ -222,14 +222,14 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch - } - - TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) -- : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) -+ : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) - { - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mRenderTarget[i] = NULL; - } - -- DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); -+ DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()); - if (d3d11::IsDepthStencilFormat(convertedFormat)) - { - mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); -@@ -440,7 +440,7 @@ void TextureStorage11_2D::generateMipmap(int level) - } - - TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) -- : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) -+ : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) - { - for (unsigned int i = 0; i < 6; i++) - { -@@ -450,7 +450,7 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLe - } - } - -- DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); -+ DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()); - if (d3d11::IsDepthStencilFormat(convertedFormat)) - { - mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp -index 13800da..0624a61 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp -@@ -329,7 +329,7 @@ DXGI_FORMAT ConvertRenderbufferFormat(GLenum format) - return DXGI_FORMAT_R8G8B8A8_UNORM; - } - --DXGI_FORMAT ConvertTextureFormat(GLenum internalformat) -+DXGI_FORMAT ConvertTextureFormat(GLenum internalformat, D3D_FEATURE_LEVEL featureLevel) - { - switch (internalformat) - { -@@ -342,7 +342,7 @@ DXGI_FORMAT ConvertTextureFormat(GLenum internalformat) - case GL_LUMINANCE8_ALPHA8_EXT: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case GL_ALPHA8_EXT: -- return DXGI_FORMAT_A8_UNORM; -+ return featureLevel >= D3D_FEATURE_LEVEL_10_0 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return DXGI_FORMAT_BC1_UNORM; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h -index 1bc48c1..70ad4fe 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h -@@ -32,7 +32,7 @@ FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset); - FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset); - - DXGI_FORMAT ConvertRenderbufferFormat(GLenum format); --DXGI_FORMAT ConvertTextureFormat(GLenum format); -+DXGI_FORMAT ConvertTextureFormat(GLenum format, D3D_FEATURE_LEVEL featureLevel); - } - - namespace d3d11_gl -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl -index 042ac69..cb132dc 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl -@@ -12,10 +12,12 @@ struct PS_OutputMultiple - float4 color1 : SV_TARGET1; - float4 color2 : SV_TARGET2; - float4 color3 : SV_TARGET3; -+#ifdef SM4 - float4 color4 : SV_TARGET4; - float4 color5 : SV_TARGET5; - float4 color6 : SV_TARGET6; - float4 color7 : SV_TARGET7; -+#endif - }; - - PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) -@@ -25,10 +27,12 @@ PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; -+#ifdef SM4 - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; -+#endif - return outColor; - } - -diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro -index ff2f888..b39ce78 100644 ---- a/src/angle/src/libGLESv2/libGLESv2.pro -+++ b/src/angle/src/libGLESv2/libGLESv2.pro -@@ -190,7 +190,7 @@ for (ps, PIXEL_SHADERS_BLIT) { - QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} - } - for (ps, PIXEL_SHADERS_PASSTHROUGH) { -- fxc_ps_$${ps}.commands = $$FXC /nologo /E PS_$$ps /T ps_4_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} -+ fxc_ps_$${ps}.commands = $$FXC /nologo /E PS_$$ps /T ps_4_0_level_9_1 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_ps_$${ps}.output = $$SHADER_DIR/$${ps}11ps.h - fxc_ps_$${ps}.input = PASSTHROUGH_INPUT - fxc_ps_$${ps}.dependency_type = TYPE_C -@@ -199,7 +199,7 @@ for (ps, PIXEL_SHADERS_PASSTHROUGH) { - QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} - } - for (ps, PIXEL_SHADERS_CLEAR) { -- fxc_ps_$${ps}.commands = $$FXC /nologo /E PS_$$ps /T ps_4_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} -+ fxc_ps_$${ps}.commands = $$FXC /nologo /E PS_$$ps /T ps_4_0_level_9_1 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_ps_$${ps}.output = $$SHADER_DIR/$${ps}11ps.h - fxc_ps_$${ps}.input = CLEAR_INPUT - fxc_ps_$${ps}.dependency_type = TYPE_C -@@ -217,7 +217,7 @@ for (vs, VERTEX_SHADERS_BLIT) { - QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} - } - for (vs, VERTEX_SHADERS_PASSTHROUGH) { -- fxc_vs_$${vs}.commands = $$FXC /nologo /E VS_$$vs /T vs_4_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} -+ fxc_vs_$${vs}.commands = $$FXC /nologo /E VS_$$vs /T vs_4_0_level_9_1 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_vs_$${vs}.output = $$SHADER_DIR/$${vs}11vs.h - fxc_vs_$${vs}.input = PASSTHROUGH_INPUT - fxc_vs_$${vs}.dependency_type = TYPE_C -@@ -226,7 +226,7 @@ for (vs, VERTEX_SHADERS_PASSTHROUGH) { - QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} - } - for (vs, VERTEX_SHADERS_CLEAR) { -- fxc_vs_$${vs}.commands = $$FXC /nologo /E VS_$$vs /T vs_4_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} -+ fxc_vs_$${vs}.commands = $$FXC /nologo /E VS_$$vs /T vs_4_0_level_9_1 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_vs_$${vs}.output = $$SHADER_DIR/$${vs}11vs.h - fxc_vs_$${vs}.input = CLEAR_INPUT - fxc_vs_$${vs}.dependency_type = TYPE_C --- -1.8.4.msysgit.0 - diff --git a/src/angle/patches/0014-ANGLE-D3D11-Always-execute-QueryInterface.patch b/src/angle/patches/0014-ANGLE-D3D11-Always-execute-QueryInterface.patch deleted file mode 100644 index dbe618102e..0000000000 --- a/src/angle/patches/0014-ANGLE-D3D11-Always-execute-QueryInterface.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 4d1906f0b81f2b61adf9640ae6cef9d503c33209 Mon Sep 17 00:00:00 2001 -From: Maurice Kalinowski -Date: Tue, 3 Dec 2013 14:52:18 +0100 -Subject: [PATCH] ANGLE D3D11: Always execute QueryInterface - -ASSERT removes the condition when building for release mode. However, -QueryInterface must be called in any case. Adopt to using ASSERT(false) -like in other occurrences in angle. - -This is a follow-up patch to 331bc16afd23414493b842819e0b747e8f364243 - -Change-Id: I4413bab06b5a529fcbd09bbc20828fcdcf4e4fc6 ---- - src/3rdparty/angle/src/libEGL/Surface.cpp | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp -index ee8d480..99d0c1d 100644 ---- a/src/3rdparty/angle/src/libEGL/Surface.cpp -+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp -@@ -118,7 +118,12 @@ bool Surface::resetSwapChain() - #else - ABI::Windows::Foundation::Rect windowRect; - ABI::Windows::UI::Core::ICoreWindow *window; -- ASSERT(SUCCEEDED(mWindow->QueryInterface(IID_PPV_ARGS(&window)))); -+ HRESULT result = mWindow->QueryInterface(IID_PPV_ARGS(&window)); -+ if (FAILED(result)) -+ { -+ ASSERT(false); -+ return false; -+ } - window->get_Bounds(&windowRect); - width = windowRect.Width; - height = windowRect.Height; -@@ -342,7 +347,12 @@ bool Surface::checkForOutOfDateSwapChain() - #else - ABI::Windows::Foundation::Rect windowRect; - ABI::Windows::UI::Core::ICoreWindow *window; -- ASSERT(SUCCEEDED(mWindow->QueryInterface(IID_PPV_ARGS(&window)))); -+ HRESULT result = mWindow->QueryInterface(IID_PPV_ARGS(&window)); -+ if (FAILED(result)) -+ { -+ ASSERT(false); -+ return false; -+ } - window->get_Bounds(&windowRect); - int clientWidth = windowRect.Width; - int clientHeight = windowRect.Height; --- -1.7.11.msysgit.0 - diff --git a/src/angle/patches/0016-ANGLE-D3D11-Fix-build-on-desktop-Windows.patch b/src/angle/patches/0016-ANGLE-D3D11-Fix-build-on-desktop-Windows.patch deleted file mode 100644 index 99f458bc28..0000000000 --- a/src/angle/patches/0016-ANGLE-D3D11-Fix-build-on-desktop-Windows.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 8229b84ddf0134ac11412262d23515dfb7ddb177 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Sun, 8 Dec 2013 22:50:38 +0200 -Subject: [PATCH] ANGLE D3D11: Fix build on desktop Windows - -This fixes a missing declaration caused by 11a2226c - -Change-Id: I4b8092c6b9592e886353af9193686238105a1512 ---- - src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -index 9770772..2fe15ff 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -@@ -519,7 +519,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap - swapChainDesc.SampleDesc.Quality = 0; - - #if !defined(ANGLE_OS_WINRT) -- result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); -+ HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); - #else - IDXGISwapChain1 *swapChain; - result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); --- -1.8.4.msysgit.0 - diff --git a/src/angle/src/compiler/compiler.pro b/src/angle/src/compiler/compiler.pro index 26b03bfc86..7f3f3e301e 100644 --- a/src/angle/src/compiler/compiler.pro +++ b/src/angle/src/compiler/compiler.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS = preprocessor translator_common.pro translator_hlsl.pro +SUBDIRS = preprocessor translator.pro diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro index 432c8dcf32..74cd97c5a4 100644 --- a/src/angle/src/compiler/preprocessor/preprocessor.pro +++ b/src/angle/src/compiler/preprocessor/preprocessor.pro @@ -21,6 +21,7 @@ HEADERS += \ $$ANGLE_DIR/src/compiler/preprocessor/DirectiveParser.h \ $$ANGLE_DIR/src/compiler/preprocessor/ExpressionParser.h \ $$ANGLE_DIR/src/compiler/preprocessor/Input.h \ + $$ANGLE_DIR/src/compiler/preprocessor/length_limits.h \ $$ANGLE_DIR/src/compiler/preprocessor/Lexer.h \ $$ANGLE_DIR/src/compiler/preprocessor/Macro.h \ $$ANGLE_DIR/src/compiler/preprocessor/MacroExpander.h \ diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro new file mode 100644 index 0000000000..0051486f82 --- /dev/null +++ b/src/angle/src/compiler/translator.pro @@ -0,0 +1,163 @@ +TEMPLATE = lib +CONFIG += static +TARGET = $$qtLibraryTarget(translator) + +include(../config.pri) + +# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here +mingw: CONFIG -= c++11 + +INCLUDEPATH += \ + $$ANGLE_DIR/src \ + $$ANGLE_DIR/include + +DEFINES += _SECURE_SCL=0 _LIB COMPILER_IMPLEMENTATION + +FLEX_SOURCES = $$ANGLE_DIR/src/compiler/translator/glslang.l +BISON_SOURCES = $$ANGLE_DIR/src/compiler/translator/glslang.y + +HEADERS += \ + $$ANGLE_DIR/include/GLSLANG/ResourceLimits.h \ + $$ANGLE_DIR/include/GLSLANG/ShaderLang.h \ + $$ANGLE_DIR/src/compiler/translator/BaseTypes.h \ + $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulator.h \ + $$ANGLE_DIR/src/compiler/translator/Common.h \ + $$ANGLE_DIR/src/compiler/translator/compilerdebug.h \ + $$ANGLE_DIR/src/compiler/translator/ConstantUnion.h \ + $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraph.h \ + $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphBuilder.h \ + $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphOutput.h \ + $$ANGLE_DIR/src/compiler/translator/DetectCallDepth.h \ + $$ANGLE_DIR/src/compiler/translator/DetectDiscontinuity.h \ + $$ANGLE_DIR/src/compiler/translator/Diagnostics.h \ + $$ANGLE_DIR/src/compiler/translator/DirectiveHandler.h \ + $$ANGLE_DIR/src/compiler/translator/ExtensionBehavior.h \ + $$ANGLE_DIR/src/compiler/translator/ForLoopUnroll.h \ + $$ANGLE_DIR/src/compiler/translator/HashNames.h \ + $$ANGLE_DIR/src/compiler/translator/InfoSink.h \ + $$ANGLE_DIR/src/compiler/translator/Initialize.h \ + $$ANGLE_DIR/src/compiler/translator/InitializeDll.h \ + $$ANGLE_DIR/src/compiler/translator/InitializeParseContext.h \ + $$ANGLE_DIR/src/compiler/translator/InitializeVariables.h \ + $$ANGLE_DIR/src/compiler/translator/intermediate.h \ + $$ANGLE_DIR/src/compiler/translator/localintermediate.h \ + $$ANGLE_DIR/src/compiler/translator/MapLongVariableNames.h \ + $$ANGLE_DIR/src/compiler/translator/MMap.h \ + $$ANGLE_DIR/src/compiler/translator/NodeSearch.h \ + $$ANGLE_DIR/src/compiler/translator/osinclude.h \ + $$ANGLE_DIR/src/compiler/translator/OutputESSL.h \ + $$ANGLE_DIR/src/compiler/translator/OutputGLSL.h \ + $$ANGLE_DIR/src/compiler/translator/OutputGLSLBase.h \ + $$ANGLE_DIR/src/compiler/translator/OutputHLSL.h \ + $$ANGLE_DIR/src/compiler/translator/ParseContext.h \ + $$ANGLE_DIR/src/compiler/translator/PoolAlloc.h \ + $$ANGLE_DIR/src/compiler/translator/Pragma.h \ + $$ANGLE_DIR/src/compiler/translator/QualifierAlive.h \ + $$ANGLE_DIR/src/compiler/translator/RemoveTree.h \ + $$ANGLE_DIR/src/compiler/translator/RenameFunction.h \ + $$ANGLE_DIR/src/compiler/translator/RewriteElseBlocks.h \ + $$ANGLE_DIR/src/compiler/translator/SearchSymbol.h \ + $$ANGLE_DIR/src/compiler/translator/ShHandle.h \ + $$ANGLE_DIR/src/compiler/translator/SymbolTable.h \ + $$ANGLE_DIR/src/compiler/translator/timing/RestrictFragmentShaderTiming.h \ + $$ANGLE_DIR/src/compiler/translator/timing/RestrictVertexShaderTiming.h \ + $$ANGLE_DIR/src/compiler/translator/TranslatorESSL.h \ + $$ANGLE_DIR/src/compiler/translator/TranslatorGLSL.h \ + $$ANGLE_DIR/src/compiler/translator/TranslatorHLSL.h \ + $$ANGLE_DIR/src/compiler/translator/Types.h \ + $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuit.h \ + $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuitAST.h \ + $$ANGLE_DIR/src/compiler/translator/Uniform.h \ + $$ANGLE_DIR/src/compiler/translator/util.h \ + $$ANGLE_DIR/src/compiler/translator/ValidateLimitations.h \ + $$ANGLE_DIR/src/compiler/translator/VariableInfo.h \ + $$ANGLE_DIR/src/compiler/translator/VariablePacker.h \ + $$ANGLE_DIR/src/compiler/translator/VersionGLSL.h \ + $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.h + + +SOURCES += \ + $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulator.cpp \ + $$ANGLE_DIR/src/compiler/translator/CodeGen.cpp \ + $$ANGLE_DIR/src/compiler/translator/Compiler.cpp \ + $$ANGLE_DIR/src/compiler/translator/compilerdebug.cpp \ + $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraph.cpp \ + $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp \ + $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphOutput.cpp \ + $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp \ + $$ANGLE_DIR/src/compiler/translator/DetectCallDepth.cpp \ + $$ANGLE_DIR/src/compiler/translator/DetectDiscontinuity.cpp \ + $$ANGLE_DIR/src/compiler/translator/Diagnostics.cpp \ + $$ANGLE_DIR/src/compiler/translator/DirectiveHandler.cpp \ + $$ANGLE_DIR/src/compiler/translator/ForLoopUnroll.cpp \ + $$ANGLE_DIR/src/compiler/translator/InfoSink.cpp \ + $$ANGLE_DIR/src/compiler/translator/Initialize.cpp \ + $$ANGLE_DIR/src/compiler/translator/InitializeDll.cpp \ + $$ANGLE_DIR/src/compiler/translator/InitializeParseContext.cpp \ + $$ANGLE_DIR/src/compiler/translator/InitializeVariables.cpp \ + $$ANGLE_DIR/src/compiler/translator/Intermediate.cpp \ + $$ANGLE_DIR/src/compiler/translator/intermOut.cpp \ + $$ANGLE_DIR/src/compiler/translator/IntermTraverse.cpp \ + $$ANGLE_DIR/src/compiler/translator/MapLongVariableNames.cpp \ + $$ANGLE_DIR/src/compiler/translator/OutputESSL.cpp \ + $$ANGLE_DIR/src/compiler/translator/OutputGLSL.cpp \ + $$ANGLE_DIR/src/compiler/translator/OutputGLSLBase.cpp \ + $$ANGLE_DIR/src/compiler/translator/OutputHLSL.cpp \ + $$ANGLE_DIR/src/compiler/translator/parseConst.cpp \ + $$ANGLE_DIR/src/compiler/translator/ParseContext.cpp \ + $$ANGLE_DIR/src/compiler/translator/PoolAlloc.cpp \ + $$ANGLE_DIR/src/compiler/translator/QualifierAlive.cpp \ + $$ANGLE_DIR/src/compiler/translator/RemoveTree.cpp \ + $$ANGLE_DIR/src/compiler/translator/RewriteElseBlocks.cpp \ + $$ANGLE_DIR/src/compiler/translator/SearchSymbol.cpp \ + $$ANGLE_DIR/src/compiler/translator/ShaderLang.cpp \ + $$ANGLE_DIR/src/compiler/translator/SymbolTable.cpp \ + $$ANGLE_DIR/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp \ + $$ANGLE_DIR/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp \ + $$ANGLE_DIR/src/compiler/translator/TranslatorESSL.cpp \ + $$ANGLE_DIR/src/compiler/translator/TranslatorGLSL.cpp \ + $$ANGLE_DIR/src/compiler/translator/TranslatorHLSL.cpp \ + $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuit.cpp \ + $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuitAST.cpp \ + $$ANGLE_DIR/src/compiler/translator/Uniform.cpp \ + $$ANGLE_DIR/src/compiler/translator/util.cpp \ + $$ANGLE_DIR/src/compiler/translator/ValidateLimitations.cpp \ + $$ANGLE_DIR/src/compiler/translator/VariableInfo.cpp \ + $$ANGLE_DIR/src/compiler/translator/VariablePacker.cpp \ + $$ANGLE_DIR/src/compiler/translator/VersionGLSL.cpp \ + $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp + + +winrt { + SOURCES += $$ANGLE_DIR/src/compiler/translator/ossource_winrt.cpp +} else { + SOURCES += $$ANGLE_DIR/src/compiler/translator/ossource_win.cpp +} + +# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin +flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} +flex.output = ${QMAKE_FILE_BASE}_lex.cpp +flex.input = FLEX_SOURCES +flex.dependency_type = TYPE_C +flex.variable_out = GENERATED_SOURCES +QMAKE_EXTRA_COMPILERS += flex + +bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ + --output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME} +bison.output = ${QMAKE_FILE_BASE}_tab.h +bison.input = BISON_SOURCES +bison.dependency_type = TYPE_C +bison.variable_out = GENERATED_SOURCES +QMAKE_EXTRA_COMPILERS += bison + +# This is a dummy compiler to work around the fact that an extra compiler can only +# have one output file even if the command generates two. +MAKEFILE_NOOP_COMMAND = @echo -n +msvc: MAKEFILE_NOOP_COMMAND = @echo >NUL +bison_impl.output = ${QMAKE_FILE_BASE}_tab.cpp +bison_impl.input = BISON_SOURCES +bison_impl.commands = $$MAKEFILE_NOOP_COMMAND +bison_impl.depends = ${QMAKE_FILE_BASE}_tab.h +bison_impl.output = ${QMAKE_FILE_BASE}_tab.cpp +bison_impl.variable_out = GENERATED_SOURCES +QMAKE_EXTRA_COMPILERS += bison_impl diff --git a/src/angle/src/compiler/translator_common.pro b/src/angle/src/compiler/translator_common.pro deleted file mode 100644 index c8f86d6b10..0000000000 --- a/src/angle/src/compiler/translator_common.pro +++ /dev/null @@ -1,133 +0,0 @@ -TEMPLATE = lib -CONFIG += static -TARGET = $$qtLibraryTarget(translator_common) - -include(../config.pri) - -# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here -mingw: CONFIG -= c++11 - -INCLUDEPATH += \ - $$ANGLE_DIR/src \ - $$ANGLE_DIR/include - -DEFINES += _SECURE_SCL=0 _LIB COMPILER_IMPLEMENTATION - -FLEX_SOURCES = $$ANGLE_DIR/src/compiler/glslang.l -BISON_SOURCES = $$ANGLE_DIR/src/compiler/glslang.y - -HEADERS += \ - $$ANGLE_DIR/src/compiler/BaseTypes.h \ - $$ANGLE_DIR/src/compiler/BuiltInFunctionEmulator.h \ - $$ANGLE_DIR/src/compiler/Common.h \ - $$ANGLE_DIR/src/compiler/ConstantUnion.h \ - $$ANGLE_DIR/src/compiler/debug.h \ - $$ANGLE_DIR/src/compiler/DetectRecursion.h \ - $$ANGLE_DIR/src/compiler/DetectCallDepth.h \ - $$ANGLE_DIR/src/compiler/Diagnostics.h \ - $$ANGLE_DIR/src/compiler/DirectiveHandler.h \ - $$ANGLE_DIR/src/compiler/ForLoopUnroll.h \ - $$ANGLE_DIR/src/compiler/InfoSink.h \ - $$ANGLE_DIR/src/compiler/Initialize.h \ - $$ANGLE_DIR/src/compiler/InitializeDll.h \ - $$ANGLE_DIR/src/compiler/InitializeGlobals.h \ - $$ANGLE_DIR/src/compiler/InitializeGLPosition.h \ - $$ANGLE_DIR/src/compiler/InitializeParseContext.h \ - $$ANGLE_DIR/src/compiler/intermediate.h \ - $$ANGLE_DIR/src/compiler/localintermediate.h \ - $$ANGLE_DIR/src/compiler/MapLongVariableNames.h \ - $$ANGLE_DIR/src/compiler/MMap.h \ - $$ANGLE_DIR/src/compiler/osinclude.h \ - $$ANGLE_DIR/src/compiler/ParseHelper.h \ - $$ANGLE_DIR/src/compiler/PoolAlloc.h \ - $$ANGLE_DIR/src/compiler/QualifierAlive.h \ - $$ANGLE_DIR/src/compiler/RemoveTree.h \ - $$ANGLE_DIR/src/compiler/RenameFunction.h \ - $$ANGLE_DIR/include/GLSLANG/ResourceLimits.h \ - $$ANGLE_DIR/include/GLSLANG/ShaderLang.h \ - $$ANGLE_DIR/src/compiler/ShHandle.h \ - $$ANGLE_DIR/src/compiler/SymbolTable.h \ - $$ANGLE_DIR/src/compiler/Types.h \ - $$ANGLE_DIR/src/compiler/UnfoldShortCircuit.h \ - $$ANGLE_DIR/src/compiler/util.h \ - $$ANGLE_DIR/src/compiler/ValidateLimitations.h \ - $$ANGLE_DIR/src/compiler/VariableInfo.h \ - $$ANGLE_DIR/src/compiler/VariablePacker.h \ - $$ANGLE_DIR/src/compiler/timing/RestrictFragmentShaderTiming.h \ - $$ANGLE_DIR/src/compiler/timing/RestrictVertexShaderTiming.h \ - $$ANGLE_DIR/src/compiler/depgraph/DependencyGraph.h \ - $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphBuilder.h \ - $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphOutput.h \ - $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.h - -SOURCES += \ - $$ANGLE_DIR/src/compiler/BuiltInFunctionEmulator.cpp \ - $$ANGLE_DIR/src/compiler/Compiler.cpp \ - $$ANGLE_DIR/src/compiler/debug.cpp \ - $$ANGLE_DIR/src/compiler/DetectCallDepth.cpp \ - $$ANGLE_DIR/src/compiler/DetectRecursion.cpp \ - $$ANGLE_DIR/src/compiler/Diagnostics.cpp \ - $$ANGLE_DIR/src/compiler/DirectiveHandler.cpp \ - $$ANGLE_DIR/src/compiler/ForLoopUnroll.cpp \ - $$ANGLE_DIR/src/compiler/InfoSink.cpp \ - $$ANGLE_DIR/src/compiler/Initialize.cpp \ - $$ANGLE_DIR/src/compiler/InitializeDll.cpp \ - $$ANGLE_DIR/src/compiler/InitializeGLPosition.cpp \ - $$ANGLE_DIR/src/compiler/InitializeParseContext.cpp \ - $$ANGLE_DIR/src/compiler/Intermediate.cpp \ - $$ANGLE_DIR/src/compiler/intermOut.cpp \ - $$ANGLE_DIR/src/compiler/IntermTraverse.cpp \ - $$ANGLE_DIR/src/compiler/MapLongVariableNames.cpp \ - $$ANGLE_DIR/src/compiler/parseConst.cpp \ - $$ANGLE_DIR/src/compiler/ParseHelper.cpp \ - $$ANGLE_DIR/src/compiler/PoolAlloc.cpp \ - $$ANGLE_DIR/src/compiler/QualifierAlive.cpp \ - $$ANGLE_DIR/src/compiler/RemoveTree.cpp \ - $$ANGLE_DIR/src/compiler/ShaderLang.cpp \ - $$ANGLE_DIR/src/compiler/SymbolTable.cpp \ - $$ANGLE_DIR/src/compiler/util.cpp \ - $$ANGLE_DIR/src/compiler/ValidateLimitations.cpp \ - $$ANGLE_DIR/src/compiler/VariableInfo.cpp \ - $$ANGLE_DIR/src/compiler/VariablePacker.cpp \ - $$ANGLE_DIR/src/compiler/depgraph/DependencyGraph.cpp \ - $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphBuilder.cpp \ - $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphOutput.cpp \ - $$ANGLE_DIR/src/compiler/depgraph/DependencyGraphTraverse.cpp \ - $$ANGLE_DIR/src/compiler/timing/RestrictFragmentShaderTiming.cpp \ - $$ANGLE_DIR/src/compiler/timing/RestrictVertexShaderTiming.cpp \ - $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp - -winrt { - SOURCES += $$ANGLE_DIR/src/compiler/ossource_winrt.cpp -} else { - SOURCES += $$ANGLE_DIR/src/compiler/ossource_win.cpp -} - -# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin -flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} -flex.output = ${QMAKE_FILE_BASE}_lex.cpp -flex.input = FLEX_SOURCES -flex.dependency_type = TYPE_C -flex.variable_out = GENERATED_SOURCES -QMAKE_EXTRA_COMPILERS += flex - -bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ - --output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME} -bison.output = ${QMAKE_FILE_BASE}_tab.h -bison.input = BISON_SOURCES -bison.dependency_type = TYPE_C -bison.variable_out = GENERATED_SOURCES -QMAKE_EXTRA_COMPILERS += bison - -# This is a dummy compiler to work around the fact that an extra compiler can only -# have one output file even if the command generates two. -MAKEFILE_NOOP_COMMAND = @echo -n -msvc: MAKEFILE_NOOP_COMMAND = @echo >NUL -bison_impl.output = ${QMAKE_FILE_BASE}_tab.cpp -bison_impl.input = BISON_SOURCES -bison_impl.commands = $$MAKEFILE_NOOP_COMMAND -bison_impl.depends = ${QMAKE_FILE_BASE}_tab.h -bison_impl.output = ${QMAKE_FILE_BASE}_tab.cpp -bison_impl.variable_out = GENERATED_SOURCES -QMAKE_EXTRA_COMPILERS += bison_impl - diff --git a/src/angle/src/compiler/translator_hlsl.pro b/src/angle/src/compiler/translator_hlsl.pro deleted file mode 100644 index f19d33a530..0000000000 --- a/src/angle/src/compiler/translator_hlsl.pro +++ /dev/null @@ -1,30 +0,0 @@ -TEMPLATE = lib -CONFIG += static -TARGET = $$qtLibraryTarget(translator_hlsl) - -include(../config.pri) - -# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here -mingw: CONFIG -= c++11 - -INCLUDEPATH += $$ANGLE_DIR/src \ - $$ANGLE_DIR/include - -DEFINES += COMPILER_IMPLEMENTATION - -HEADERS += \ - $$ANGLE_DIR/src/compiler/DetectDiscontinuity.h \ - $$ANGLE_DIR/src/compiler/OutputHLSL.h \ - $$ANGLE_DIR/src/compiler/SearchSymbol.h \ - $$ANGLE_DIR/src/compiler/TranslatorHLSL.h \ - $$ANGLE_DIR/src/compiler/UnfoldShortCircuit.h \ - $$ANGLE_DIR/src/compiler/Uniform.h - -SOURCES += \ - $$ANGLE_DIR/src/compiler/CodeGenHLSL.cpp \ - $$ANGLE_DIR/src/compiler/DetectDiscontinuity.cpp \ - $$ANGLE_DIR/src/compiler/OutputHLSL.cpp \ - $$ANGLE_DIR/src/compiler/SearchSymbol.cpp \ - $$ANGLE_DIR/src/compiler/TranslatorHLSL.cpp \ - $$ANGLE_DIR/src/compiler/UnfoldShortCircuit.cpp \ - $$ANGLE_DIR/src/compiler/Uniform.cpp diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri index ed2558117e..c6dbb90ec7 100644 --- a/src/angle/src/config.pri +++ b/src/angle/src/config.pri @@ -38,14 +38,12 @@ DEFINES += _WINDOWS \ WIN32_LEAN_AND_MEAN=1 # Defines specifying the API version (0x0600 = Vista, 0x0602 = Win8)) -winrt: DEFINES += _WIN32_WINNT=0x0602 WINVER=0x0602 -else: DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 - -# ANGLE specific defines -DEFINES += ANGLE_DISABLE_TRACE \ - ANGLE_DISABLE_PERF \ - ANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL0 \ - ANGLE_USE_NEW_PREPROCESSOR=1 +winrt { + DEFINES += _WIN32_WINNT=0x0602 WINVER=0x0602 +} else { + DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 + DEFINES += ANGLE_ENABLE_D3D9 +} angle_d3d11 { DEFINES += ANGLE_ENABLE_D3D11 diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro index f51bc8ee83..4f10583fc0 100644 --- a/src/angle/src/libEGL/libEGL.pro +++ b/src/angle/src/libEGL/libEGL.pro @@ -3,11 +3,11 @@ TARGET = $$qtLibraryTarget(libEGL) include(../common/common.pri) -angle_d3d11 { +angle_d3d11: \ LIBS_PRIVATE += -ld3d11 -} else { +!winrt: \ LIBS_PRIVATE += -ld3d9 -} + LIBS_PRIVATE += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2) HEADERS += \ diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro index 75853e219e..6176016f13 100644 --- a/src/angle/src/libGLESv2/libGLESv2.pro +++ b/src/angle/src/libGLESv2/libGLESv2.pro @@ -7,13 +7,13 @@ include(../common/common.pri) INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libGLESv2 # Remember to adapt tools/configure/configureapp.cpp if the Direct X version changes. -angle_d3d11 { +angle_d3d11: \ LIBS_PRIVATE += -ldxgi -ld3d11 -} else { +!winrt: \ LIBS_PRIVATE += -ld3d9 -} + LIBS_PRIVATE += -ldxguid -STATICLIBS = translator_common translator_hlsl preprocessor +STATICLIBS = translator preprocessor for(libname, STATICLIBS) { # Appends 'd' to the library for debug builds and builds up the fully @@ -93,67 +93,69 @@ SSE2_SOURCES += $$ANGLE_DIR/src/libGLESv2/renderer/ImageSSE2.cpp angle_d3d11 { HEADERS += \ - $$ANGLE_DIR/src/libGLESv2/renderer/BufferStorage11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Fence11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Image11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/IndexBuffer11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/InputLayoutCache.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Query11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Renderer11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/renderer11_utils.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderStateCache.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/SwapChain11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/TextureStorage11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/VertexBuffer11.h + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/BufferStorage11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/Fence11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/Image11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/IndexBuffer11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/InputLayoutCache.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/Query11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/Renderer11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/renderer11_utils.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/RenderTarget11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/RenderStateCache.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/SwapChain11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/TextureStorage11.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/VertexBuffer11.h SOURCES += \ - $$ANGLE_DIR/src/libGLESv2/renderer/BufferStorage11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Fence11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Image11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/IndexBuffer11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/InputLayoutCache.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Query11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Renderer11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/renderer11_utils.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderStateCache.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/SwapChain11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/TextureStorage11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/VertexBuffer11.cpp -} else { + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/Fence11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/Image11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/Query11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/Renderer11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/SwapChain11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp +} + +!winrt { HEADERS += \ - $$ANGLE_DIR/src/libGLESv2/renderer/Blit.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/BufferStorage9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Fence9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Image9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/IndexBuffer9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Query9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Renderer9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/renderer9_utils.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/SwapChain9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/TextureStorage9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/VertexBuffer9.h + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Blit.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/BufferStorage9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Fence9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Image9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/IndexBuffer9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Query9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Renderer9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/renderer9_utils.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/RenderTarget9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/SwapChain9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/TextureStorage9.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/VertexBuffer9.h SOURCES += \ - $$ANGLE_DIR/src/libGLESv2/renderer/Blit.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/BufferStorage9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Fence9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Image9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/IndexBuffer9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Query9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Renderer9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/renderer9_utils.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/SwapChain9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/TextureStorage9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/VertexBuffer9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/VertexDeclarationCache.cpp + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Blit.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Fence9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Image9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Query9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/Renderer9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/SwapChain9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp } !static { @@ -167,10 +169,10 @@ float_converter.commands = python $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.py QMAKE_EXTRA_TARGETS += float_converter # Generate the shader header files. -PS_BLIT_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Blit.ps -VS_BLIT_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Blit.vs -PASSTHROUGH_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Passthrough11.hlsl -CLEAR_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Clear11.hlsl +PS_BLIT_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/shaders/Blit.ps +VS_BLIT_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/d3d9/shaders/Blit.vs +PASSTHROUGH_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl +CLEAR_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl PIXEL_SHADERS_BLIT = passthroughps luminanceps componentmaskps PIXEL_SHADERS_PASSTHROUGH = PassthroughRGBA PassthroughRGB \ PassthroughLum PassthroughLumAlpha @@ -178,61 +180,62 @@ PIXEL_SHADERS_CLEAR = ClearSingle ClearMultiple VERTEX_SHADERS_BLIT = standardvs flipyvs VERTEX_SHADERS_PASSTHROUGH = Passthrough VERTEX_SHADERS_CLEAR = Clear -SHADER_DIR = $$OUT_PWD/renderer/shaders/compiled +SHADER_DIR_9 = $$OUT_PWD/renderer/d3d9/shaders/compiled +SHADER_DIR_11 = $$OUT_PWD/renderer/d3d11/shaders/compiled for (ps, PIXEL_SHADERS_BLIT) { fxc_ps_$${ps}.commands = $$FXC /nologo /E $$ps /T ps_2_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_ps_$${ps}.output = $$SHADER_DIR/$${ps}.h + fxc_ps_$${ps}.output = $$SHADER_DIR_9/$${ps}.h fxc_ps_$${ps}.input = PS_BLIT_INPUT fxc_ps_$${ps}.dependency_type = TYPE_C fxc_ps_$${ps}.variable_out = HEADERS fxc_ps_$${ps}.CONFIG += target_predeps - QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} + !winrt: QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} } for (ps, PIXEL_SHADERS_PASSTHROUGH) { fxc_ps_$${ps}.commands = $$FXC /nologo /E PS_$$ps /T ps_4_0_level_9_1 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_ps_$${ps}.output = $$SHADER_DIR/$${ps}11ps.h + fxc_ps_$${ps}.output = $$SHADER_DIR_11/$${ps}11ps.h fxc_ps_$${ps}.input = PASSTHROUGH_INPUT fxc_ps_$${ps}.dependency_type = TYPE_C fxc_ps_$${ps}.variable_out = HEADERS fxc_ps_$${ps}.CONFIG += target_predeps - QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} + angle_d3d11: QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} } for (ps, PIXEL_SHADERS_CLEAR) { fxc_ps_$${ps}.commands = $$FXC /nologo /E PS_$$ps /T ps_4_0_level_9_1 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_ps_$${ps}.output = $$SHADER_DIR/$${ps}11ps.h + fxc_ps_$${ps}.output = $$SHADER_DIR_11/$${ps}11ps.h fxc_ps_$${ps}.input = CLEAR_INPUT fxc_ps_$${ps}.dependency_type = TYPE_C fxc_ps_$${ps}.variable_out = HEADERS fxc_ps_$${ps}.CONFIG += target_predeps - QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} + angle_d3d11: QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} } for (vs, VERTEX_SHADERS_BLIT) { fxc_vs_$${vs}.commands = $$FXC /nologo /E $$vs /T vs_2_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_vs_$${vs}.output = $$SHADER_DIR/$${vs}.h + fxc_vs_$${vs}.output = $$SHADER_DIR_9/$${vs}.h fxc_vs_$${vs}.input = VS_BLIT_INPUT fxc_vs_$${vs}.dependency_type = TYPE_C fxc_vs_$${vs}.variable_out = HEADERS fxc_vs_$${vs}.CONFIG += target_predeps - QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} + !winrt: QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} } for (vs, VERTEX_SHADERS_PASSTHROUGH) { fxc_vs_$${vs}.commands = $$FXC /nologo /E VS_$$vs /T vs_4_0_level_9_1 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_vs_$${vs}.output = $$SHADER_DIR/$${vs}11vs.h + fxc_vs_$${vs}.output = $$SHADER_DIR_11/$${vs}11vs.h fxc_vs_$${vs}.input = PASSTHROUGH_INPUT fxc_vs_$${vs}.dependency_type = TYPE_C fxc_vs_$${vs}.variable_out = HEADERS fxc_vs_$${vs}.CONFIG += target_predeps - QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} + angle_d3d11: QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} } for (vs, VERTEX_SHADERS_CLEAR) { fxc_vs_$${vs}.commands = $$FXC /nologo /E VS_$$vs /T vs_4_0_level_9_1 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_vs_$${vs}.output = $$SHADER_DIR/$${vs}11vs.h + fxc_vs_$${vs}.output = $$SHADER_DIR_11/$${vs}11vs.h fxc_vs_$${vs}.input = CLEAR_INPUT fxc_vs_$${vs}.dependency_type = TYPE_C fxc_vs_$${vs}.variable_out = HEADERS fxc_vs_$${vs}.CONFIG += target_predeps - QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} + angle_d3d11: QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} } load(qt_installs) From efc79c6e91f6e7c226eabfb1e371840a2df09782 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 24 Feb 2014 11:24:25 +0200 Subject: [PATCH 088/124] ANGLE: Allow for universal program binaries As a safety precaution, ANGLE writes the commit hash, optimization level, and adapter ID to its binary format. However, this hurts portability between systems by making shader pre-compilation/caching artificially system-specific. The shader compiler doesn't take the target adapter into account, and the optimization level information discarded by ANGLE anyway. So, allow ANGLE to bypass these checks on systems where precompilation is required (i.e. WinRT). The default mechanism still applies unless ANGLE_ENABLE_UNIVERSAL_BINARY is passed as a define. Change-Id: Iec6d833fd7010ed163978557238f00e7ac6ae416 Reviewed-by: Oliver Wolff --- .../angle/src/libGLESv2/ProgramBinary.cpp | 11 ++- ...Allow-for-universal-program-binaries.patch | 93 +++++++++++++++++++ src/angle/src/config.pri | 1 + 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/angle/patches/0013-ANGLE-Allow-for-universal-program-binaries.patch diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index a4d21192fa..13c515a594 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -1637,6 +1637,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) return false; } +#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; stream.read(commitString, ANGLE_COMMIT_HASH_SIZE); if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) @@ -1652,6 +1653,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) infoLog.append("Mismatched compilation flags."); return false; } +#endif for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { @@ -1742,6 +1744,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) const char *ptr = (const char*) binary + stream.offset(); +#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) const GUID *binaryIdentifier = (const GUID *) ptr; ptr += sizeof(GUID); @@ -1751,6 +1754,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) infoLog.append("Invalid program binary."); return false; } +#endif const char *pixelShaderFunction = ptr; ptr += pixelShaderSize; @@ -1808,9 +1812,10 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.write(GL_PROGRAM_BINARY_ANGLE); stream.write(ANGLE_MAJOR_VERSION); stream.write(ANGLE_MINOR_VERSION); +#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) stream.write(ANGLE_COMMIT_HASH, ANGLE_COMMIT_HASH_SIZE); stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL); - +#endif for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { stream.write(mLinkedAttribute[i].type); @@ -1866,7 +1871,9 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; stream.write(geometryShaderSize); +#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) GUID identifier = mRenderer->getAdapterIdentifier(); +#endif GLsizei streamLength = stream.length(); const void *streamData = stream.data(); @@ -1889,8 +1896,10 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) memcpy(ptr, streamData, streamLength); ptr += streamLength; +#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) memcpy(ptr, &identifier, sizeof(GUID)); ptr += sizeof(GUID); +#endif memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize); ptr += pixelShaderSize; diff --git a/src/angle/patches/0013-ANGLE-Allow-for-universal-program-binaries.patch b/src/angle/patches/0013-ANGLE-Allow-for-universal-program-binaries.patch new file mode 100644 index 0000000000..11c32880df --- /dev/null +++ b/src/angle/patches/0013-ANGLE-Allow-for-universal-program-binaries.patch @@ -0,0 +1,93 @@ +From 5eeb4a06f182b4fc0e3dcb82f47fcf4286890f94 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Fri, 21 Feb 2014 08:35:01 +0200 +Subject: [PATCH] ANGLE: Allow for universal program binaries + +As a safety precaution, ANGLE writes the commit hash, optimization level, +and adapter ID to its binary format. However, this hurts portability +between systems by making shader pre-compilation/caching artificially +system-specific. + +The shader compiler doesn't take the target adapter into account, and the +optimization level information discarded by ANGLE anyway. So, allow ANGLE +to bypass these checks on systems where precompilation is required (i.e. +WinRT). The default mechanism still applies unless +ANGLE_ENABLE_UNIVERSAL_BINARY is passed as a define. + +Change-Id: Iec6d833fd7010ed163978557238f00e7ac6ae416 +--- + src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +index 8896665..41a83b6 100644 +--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +@@ -1637,6 +1637,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) + return false; + } + ++#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) + unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; + stream.read(commitString, ANGLE_COMMIT_HASH_SIZE); + if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) +@@ -1652,6 +1653,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) + infoLog.append("Mismatched compilation flags."); + return false; + } ++#endif + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) + { +@@ -1742,6 +1744,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) + + const char *ptr = (const char*) binary + stream.offset(); + ++#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) + const GUID *binaryIdentifier = (const GUID *) ptr; + ptr += sizeof(GUID); + +@@ -1751,6 +1754,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) + infoLog.append("Invalid program binary."); + return false; + } ++#endif + + const char *pixelShaderFunction = ptr; + ptr += pixelShaderSize; +@@ -1808,9 +1812,10 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) + stream.write(GL_PROGRAM_BINARY_ANGLE); + stream.write(ANGLE_MAJOR_VERSION); + stream.write(ANGLE_MINOR_VERSION); ++#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) + stream.write(ANGLE_COMMIT_HASH, ANGLE_COMMIT_HASH_SIZE); + stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL); +- ++#endif + for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) + { + stream.write(mLinkedAttribute[i].type); +@@ -1866,7 +1871,9 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) + UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; + stream.write(geometryShaderSize); + ++#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) + GUID identifier = mRenderer->getAdapterIdentifier(); ++#endif + + GLsizei streamLength = stream.length(); + const void *streamData = stream.data(); +@@ -1889,8 +1896,10 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) + memcpy(ptr, streamData, streamLength); + ptr += streamLength; + ++#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) + memcpy(ptr, &identifier, sizeof(GUID)); + ptr += sizeof(GUID); ++#endif + + memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize); + ptr += pixelShaderSize; +-- +1.8.4.msysgit.0 + diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri index c6dbb90ec7..c3cc7e02c1 100644 --- a/src/angle/src/config.pri +++ b/src/angle/src/config.pri @@ -40,6 +40,7 @@ DEFINES += _WINDOWS \ # Defines specifying the API version (0x0600 = Vista, 0x0602 = Win8)) winrt { DEFINES += _WIN32_WINNT=0x0602 WINVER=0x0602 + DEFINES += ANGLE_ENABLE_UNIVERSAL_BINARY } else { DEFINES += _WIN32_WINNT=0x0600 WINVER=0x0600 DEFINES += ANGLE_ENABLE_D3D9 From 7afd2ede79a5e37cfcd5e7453c641fdabfe882e8 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 21 Feb 2014 15:06:18 +0200 Subject: [PATCH 089/124] WinRT: Fix backing store for latest ANGLE Bump the ANGLE version and remove the extra info not required by universal binaries. Change-Id: I59983d28e1936fb42aa2def4ca785219b0c38996 Reviewed-by: Oliver Wolff --- .../platforms/winrt/qwinrtbackingstore.cpp | 30 ++----------------- src/plugins/platforms/winrt/winrt.pro | 2 +- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp index b219548788..10136dbead 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp @@ -49,8 +49,6 @@ #include #include -#include - // Generated shader headers #include "blitps.h" #include "blitvs.h" @@ -60,10 +58,7 @@ namespace { // Utility namespace for writing out an ANGLE-compatible binary blob // Must match packaged ANGLE enum : quint32 { AngleMajorVersion = 1, - AngleMinorVersion = 2, - AngleBuildRevision = 2446, - AngleVersion = ((AngleMajorVersion << 24) | (AngleMinorVersion << 16) | AngleBuildRevision), - AngleOptimizationLevel = (1 << 14) + AngleMinorVersion = 3 }; struct ShaderString @@ -145,8 +140,8 @@ static const QByteArray createAngleBinary( stream.setByteOrder(QDataStream::LittleEndian); stream << quint32(GL_PROGRAM_BINARY_ANGLE) - << quint32(AngleVersion) - << quint32(AngleOptimizationLevel); + << qint32(AngleMajorVersion) + << qint32(AngleMinorVersion); // Vertex attributes for (int i = 0; i < 16; ++i) { @@ -190,25 +185,6 @@ static const QByteArray createAngleBinary( << quint32(vertexShader.size()) << quint32(geometryShader.size()); - // ANGLE requires that we query the adapter for its LUID. Later on, it may be useful - // for checking feature level support, picking the best adapter on the system, etc. - IDXGIFactory1 *dxgiFactory; - if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)))) { - qCritical("QWinRTBackingStore: failed to create DXGI factory."); - return QByteArray(); - } - IDXGIAdapter *dxgiAdapter; - if (FAILED(dxgiFactory->EnumAdapters(0, &dxgiAdapter))) { - qCritical("QWinRTBackingStore:: failed to enumerate adapter."); - dxgiFactory->Release(); - return QByteArray(); - } - DXGI_ADAPTER_DESC desc; - dxgiAdapter->GetDesc(&desc); - dxgiAdapter->Release(); - QByteArray guid(sizeof(GUID), '\0'); - memcpy(guid.data(), &desc.AdapterLuid, sizeof(LUID)); - stream.writeRawData(guid.constData(), guid.size()); stream.writeRawData(pixelShader.constData(), pixelShader.size()); stream.writeRawData(vertexShader.constData(), vertexShader.size()); if (!geometryShader.isEmpty()) diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 3bd688c069..6e3cfb1d20 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -9,7 +9,7 @@ QT += core-private gui-private platformsupport-private DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES -LIBS += $$QMAKE_LIBS_CORE -ldxgi +LIBS += $$QMAKE_LIBS_CORE SOURCES = \ main.cpp \ From 5ddc5df3501675fc4cd2a6994b46b00969b7c02c Mon Sep 17 00:00:00 2001 From: John Layt Date: Sun, 19 Jan 2014 18:43:47 +0100 Subject: [PATCH 090/124] QPrintEngine - Remove Windows use of port and driver The use of the driver name and port name in the DEVNAMES structure is no longer required within the Windows print engine and dialogs. The CreateDC docs clearly state any driver value passed in for a printer is ignored. The PRINTDLGEX docs also state only the name is actually used. The use of the port name is not required as the DeviceCapabilities api works fine with just the printer name and the FILE: port can be manually handled. Change-Id: I7765d73d4a31b1a3c5dab55ee4cfd3580bcf9ad7 Reviewed-by: Lars Knoll --- .../windows/qwindowsprintersupport.cpp | 4 +- src/printsupport/dialogs/qprintdialog_win.cpp | 2 +- src/printsupport/kernel/qprintengine_win.cpp | 47 ++++++------------- src/printsupport/kernel/qprintengine_win_p.h | 4 +- 4 files changed, 17 insertions(+), 40 deletions(-) diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.cpp b/src/plugins/printsupport/windows/qwindowsprintersupport.cpp index 2faebf6f64..b7ba9ef5e7 100644 --- a/src/plugins/printsupport/windows/qwindowsprintersupport.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintersupport.cpp @@ -101,9 +101,7 @@ QList QWindowsPrinterSupport::queryPrinters() return result; PPRINTER_INFO_4 infoList = reinterpret_cast(buffer.data()); QString defaultPrinterName; - QString program; - QString port; - QWin32PrintEngine::queryDefaultPrinter(defaultPrinterName, program, port); + QWin32PrintEngine::queryDefaultPrinter(defaultPrinterName); for (uint i = 0; i < returned; ++i) { const QString printerName(QString::fromWCharArray(infoList[i].pPrinterName)); const bool isDefault = (printerName == defaultPrinterName); diff --git a/src/printsupport/dialogs/qprintdialog_win.cpp b/src/printsupport/dialogs/qprintdialog_win.cpp index b5dc2d016a..9d972ef5c4 100644 --- a/src/printsupport/dialogs/qprintdialog_win.cpp +++ b/src/printsupport/dialogs/qprintdialog_win.cpp @@ -167,7 +167,7 @@ static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPri d->ep->updateCustomPaperSize(); if (d->ep->printToFile && d->ep->fileName.isEmpty()) - d->ep->fileName = d->ep->port; + d->ep->fileName = QLatin1String("FILE:"); else if (!d->ep->printToFile && d->ep->fileName == QLatin1String("FILE:")) d->ep->fileName.clear(); } diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index 74484bfc8c..ce2316d0e0 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -260,10 +260,6 @@ bool QWin32PrintEngine::begin(QPaintDevice *pdev) if (!d->hdc) return false; - // Assign the FILE: to get the query... - if (d->printToFile && d->fileName.isEmpty()) - d->fileName = d->port; - d->devMode->dmCopies = d->num_copies; DOCINFO di; @@ -275,6 +271,8 @@ bool QWin32PrintEngine::begin(QPaintDevice *pdev) di.lpszDocName = reinterpret_cast(d->docName.utf16()); if (d->printToFile && !d->fileName.isEmpty()) di.lpszOutput = reinterpret_cast(d->fileName.utf16()); + if (d->printToFile) + di.lpszOutput = d->fileName.isEmpty() ? L"FILE:" : reinterpret_cast(d->fileName.utf16()); if (ok && StartDoc(d->hdc, &di) == SP_ERROR) { qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed"); ok = false; @@ -1039,7 +1037,7 @@ void QWin32PrintEngine::drawPolygon(const QPointF *points, int pointCount, Polyg void QWin32PrintEnginePrivate::queryDefault() { - QWin32PrintEngine::queryDefaultPrinter(name, program, port); + QWin32PrintEngine::queryDefaultPrinter(name); } QWin32PrintEnginePrivate::~QWin32PrintEnginePrivate() @@ -1088,8 +1086,7 @@ void QWin32PrintEnginePrivate::initialize() } devMode = pInfo->pDevMode; - hdc = CreateDC(reinterpret_cast(program.utf16()), - reinterpret_cast(name.utf16()), 0, devMode); + hdc = CreateDC(NULL, reinterpret_cast(name.utf16()), 0, devMode); Q_ASSERT(hPrinter); Q_ASSERT(pInfo); @@ -1216,15 +1213,13 @@ QList QWin32PrintEnginePrivate::queryResolutions() const // Read the supported resolutions of the printer. QList list; - DWORD numRes = DeviceCapabilities(reinterpret_cast(name.utf16()), - reinterpret_cast(port.utf16()), + DWORD numRes = DeviceCapabilities(reinterpret_cast(name.utf16()), NULL, DC_ENUMRESOLUTIONS, 0, 0); if (numRes == (DWORD)-1) return list; LONG *enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG)); - DWORD errRes = DeviceCapabilities(reinterpret_cast(name.utf16()), - reinterpret_cast(port.utf16()), + DWORD errRes = DeviceCapabilities(reinterpret_cast(name.utf16()), NULL, DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0); if (errRes == (DWORD)-1) { @@ -1675,15 +1670,13 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const case PPK_PaperSources: { - int available = DeviceCapabilities((const wchar_t *)d->name.utf16(), - (const wchar_t *)d->port.utf16(), DC_BINS, 0, d->devMode); + int available = DeviceCapabilities((const wchar_t *)d->name.utf16(), NULL, DC_BINS, 0, d->devMode); if (available <= 0) break; wchar_t *data = new wchar_t[available]; - int count = DeviceCapabilities((const wchar_t *)d->name.utf16(), - (const wchar_t *)d->port.utf16(), DC_BINS, data, d->devMode); + int count = DeviceCapabilities((const wchar_t *)d->name.utf16(), NULL, DC_BINS, data, d->devMode); QList out; for (int i=0; i > QWin32PrintEngine::supportedSizesWithNames(const return paperSizes; } -void QWin32PrintEngine::queryDefaultPrinter(QString &name, QString &program, QString &port) +void QWin32PrintEngine::queryDefaultPrinter(QString &name) { /* Read the default printer name, driver and port with the intuitive function * Strings "windows" and "device" are specified in the MSDN under EnumPrinters() @@ -1802,29 +1795,20 @@ void QWin32PrintEngine::queryDefaultPrinter(QString &name, QString &program, QSt if (infoSize > 0) { if (name.isEmpty()) name = info.at(0); - if (program.isEmpty() && infoSize > 1) - program = info.at(1); - if (port.isEmpty() && infoSize > 2) - port = info.at(2); } } HGLOBAL *QWin32PrintEnginePrivate::createDevNames() { - int size = sizeof(DEVNAMES) - + program.length() * 2 + 2 - + name.length() * 2 + 2 - + port.length() * 2 + 2; + int size = sizeof(DEVNAMES) + name.length() * 2 + 2; HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size); DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal); - dn->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t); - dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1; - dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1; + dn->wDriverOffset = 0; + dn->wDeviceOffset = sizeof(DEVNAMES) / sizeof(wchar_t); + dn->wOutputOffset = 0; - memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2); memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2); - memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2); dn->wDefault = 0; GlobalUnlock(hGlobal); @@ -1850,8 +1834,6 @@ void QWin32PrintEnginePrivate::readDevnames(HGLOBAL globalDevnames) if (globalDevnames) { DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames); name = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset); - port = QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset); - program = QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset); GlobalUnlock(globalDevnames); } } @@ -1863,8 +1845,7 @@ void QWin32PrintEnginePrivate::readDevmode(HGLOBAL globalDevmode) release(); globalDevMode = globalDevmode; devMode = dm; - hdc = CreateDC(reinterpret_cast(program.utf16()), - reinterpret_cast(name.utf16()), 0, dm); + hdc = CreateDC(NULL, reinterpret_cast(name.utf16()), 0, dm); num_copies = devMode->dmCopies; if (!OpenPrinter((wchar_t*)name.utf16(), &hPrinter, 0)) diff --git a/src/printsupport/kernel/qprintengine_win_p.h b/src/printsupport/kernel/qprintengine_win_p.h index 040140d50f..b651487a13 100644 --- a/src/printsupport/kernel/qprintengine_win_p.h +++ b/src/printsupport/kernel/qprintengine_win_p.h @@ -107,7 +107,7 @@ public: static QList supportedPaperSizes(const QPrinterInfo &printerInfo); static QList > supportedSizesWithNames(const QPrinterInfo &printerInfo); - static void queryDefaultPrinter(QString &name, QString &program, QString &port); + static void queryDefaultPrinter(QString &name); private: friend class QPrintDialog; @@ -205,8 +205,6 @@ public: // Printer info QString name; - QString program; - QString port; // Document info QString docName; From f05e48381b309447297a290f699a3389ac41af41 Mon Sep 17 00:00:00 2001 From: John Layt Date: Mon, 20 Jan 2014 15:40:23 +0100 Subject: [PATCH 091/124] QPrintEngine - Improve devMode handling Improve the sharing of the devMode between the QPrintEngine and the print dialogs, in particular start to change the dialogs from directly accessing the QPrintEngine internals. Change-Id: Ieb4649c19b936433c85207297a0b6e59356c3880 Reviewed-by: Lars Knoll --- .../dialogs/qpagesetupdialog_win.cpp | 15 ++--- src/printsupport/dialogs/qprintdialog_win.cpp | 15 +++-- src/printsupport/kernel/qprintengine_win.cpp | 64 +++++++++---------- src/printsupport/kernel/qprintengine_win_p.h | 12 ++-- 4 files changed, 49 insertions(+), 57 deletions(-) diff --git a/src/printsupport/dialogs/qpagesetupdialog_win.cpp b/src/printsupport/dialogs/qpagesetupdialog_win.cpp index 688f4ac314..345e698b82 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_win.cpp +++ b/src/printsupport/dialogs/qpagesetupdialog_win.cpp @@ -82,7 +82,7 @@ int QPageSetupDialog::exec() // we need a temp DEVMODE struct if we don't have a global DEVMODE HGLOBAL hDevMode = 0; int devModeSize = 0; - if (!ep->globalDevMode) { + if (!engine->globalDevMode()) { devModeSize = sizeof(DEVMODE) + ep->devMode->dmDriverExtra; hDevMode = GlobalAlloc(GHND, devModeSize); if (hDevMode) { @@ -92,10 +92,10 @@ int QPageSetupDialog::exec() } psd.hDevMode = hDevMode; } else { - psd.hDevMode = ep->devMode; + psd.hDevMode = engine->globalDevMode(); } - HGLOBAL *tempDevNames = ep->createDevNames(); + HGLOBAL *tempDevNames = engine->createGlobalDevNames(); psd.hDevNames = tempDevNames; QWidget *parent = parentWidget(); @@ -129,8 +129,7 @@ int QPageSetupDialog::exec() bool result = PageSetupDlg(&psd); QDialog::setVisible(false); if (result) { - ep->readDevnames(psd.hDevNames); - ep->readDevmode(psd.hDevMode); + engine->setGlobalDevMode(psd.hDevNames, psd.hDevMode); QRect theseMargins = QRect(psd.rtMargin.left * multiplier, psd.rtMargin.top * multiplier, @@ -144,17 +143,15 @@ int QPageSetupDialog::exec() psd.rtMargin.bottom * multiplier); } - ep->updateCustomPaperSize(); - // copy from our temp DEVMODE struct - if (!ep->globalDevMode && hDevMode) { + if (!engine->globalDevMode() && hDevMode) { void *src = GlobalLock(hDevMode); memcpy(ep->devMode, src, devModeSize); GlobalUnlock(hDevMode); } } - if (!ep->globalDevMode && hDevMode) + if (!engine->globalDevMode() && hDevMode) GlobalFree(hDevMode); GlobalFree(tempDevNames); done(result); diff --git a/src/printsupport/dialogs/qprintdialog_win.cpp b/src/printsupport/dialogs/qprintdialog_win.cpp index 9d972ef5c4..722f0e186f 100644 --- a/src/printsupport/dialogs/qprintdialog_win.cpp +++ b/src/printsupport/dialogs/qprintdialog_win.cpp @@ -68,12 +68,13 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate Q_DECLARE_PUBLIC(QPrintDialog) public: QPrintDialogPrivate() - : ep(0) + : engine(0), ep(0) { } int openWindowsPrintDialogModally(); + QWin32PrintEngine *engine; QWin32PrintEnginePrivate *ep; }; @@ -141,7 +142,7 @@ static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWidget *parent, pd->hwndOwner = parentWindow ? (HWND)QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", parentWindow) : 0; pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage()); pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1; - pd->nCopies = d->ep->num_copies; + pd->nCopies = d->printer->copyCount(); } static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d) @@ -162,9 +163,7 @@ static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPri d->ep->printToFile = (pd->Flags & PD_PRINTTOFILE) != 0; - d->ep->readDevnames(pd->hDevNames); - d->ep->readDevmode(pd->hDevMode); - d->ep->updateCustomPaperSize(); + d->engine->setGlobalDevMode(pd->hDevNames, pd->hDevMode); if (d->ep->printToFile && d->ep->fileName.isEmpty()) d->ep->fileName = QLatin1String("FILE:"); @@ -187,6 +186,7 @@ QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent) Q_D(QPrintDialog); if (!warnIfNotNative(d->printer)) return; + d->engine = static_cast(d->printer->printEngine()); d->ep = static_cast(d->printer->printEngine())->d_func(); setAttribute(Qt::WA_DontShowOnScreen); } @@ -197,6 +197,7 @@ QPrintDialog::QPrintDialog(QWidget *parent) Q_D(QPrintDialog); if (!warnIfNotNative(d->printer)) return; + d->engine = static_cast(d->printer->printEngine()); d->ep = static_cast(d->printer->printEngine())->d_func(); setAttribute(Qt::WA_DontShowOnScreen); } @@ -229,7 +230,7 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally() q->QDialog::setVisible(true); - HGLOBAL *tempDevNames = ep->createDevNames(); + HGLOBAL *tempDevNames = engine->createGlobalDevNames(); bool done; bool result; @@ -278,7 +279,7 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally() { qt_win_read_back_PRINTDLGEX(&pd, q, this); // update printer validity - printer->d_func()->validPrinter = !ep->name.isEmpty(); + printer->d_func()->validPrinter = !printer->printerName().isEmpty(); } // Cleanup... diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index ce2316d0e0..02b5d824f4 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -1798,9 +1798,11 @@ void QWin32PrintEngine::queryDefaultPrinter(QString &name) } } -HGLOBAL *QWin32PrintEnginePrivate::createDevNames() +HGLOBAL *QWin32PrintEngine::createGlobalDevNames() { - int size = sizeof(DEVNAMES) + name.length() * 2 + 2; + Q_D(QWin32PrintEngine); + + int size = sizeof(DEVNAMES) + d->name.length() * 2 + 2; HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size); DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal); @@ -1808,52 +1810,44 @@ HGLOBAL *QWin32PrintEnginePrivate::createDevNames() dn->wDeviceOffset = sizeof(DEVNAMES) / sizeof(wchar_t); dn->wOutputOffset = 0; - memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2); + memcpy((ushort*)dn + dn->wDeviceOffset, d->name.utf16(), d->name.length() * 2 + 2); dn->wDefault = 0; GlobalUnlock(hGlobal); - -// printf("QPrintDialogWinPrivate::createDevNames()\n" -// " -> wDriverOffset: %d\n" -// " -> wDeviceOffset: %d\n" -// " -> wOutputOffset: %d\n", -// dn->wDriverOffset, -// dn->wDeviceOffset, -// dn->wOutputOffset); - -// printf("QPrintDialogWinPrivate::createDevNames(): %s, %s, %s\n", -// QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset).latin1(), -// QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset).latin1(), -// QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset).latin1()); - return hGlobal; } -void QWin32PrintEnginePrivate::readDevnames(HGLOBAL globalDevnames) +void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalDevMode) { - if (globalDevnames) { - DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames); - name = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset); - GlobalUnlock(globalDevnames); + Q_D(QWin32PrintEngine); + if (globalDevNames) { + DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevNames); + d->name = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset); + GlobalUnlock(globalDevNames); } -} -void QWin32PrintEnginePrivate::readDevmode(HGLOBAL globalDevmode) -{ - if (globalDevmode) { - DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode); - release(); - globalDevMode = globalDevmode; - devMode = dm; - hdc = CreateDC(NULL, reinterpret_cast(name.utf16()), 0, dm); + if (globalDevMode) { + DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevMode); + d->release(); + d->globalDevMode = globalDevMode; + d->devMode = dm; + d->hdc = CreateDC(NULL, reinterpret_cast(d->name.utf16()), 0, dm); - num_copies = devMode->dmCopies; - if (!OpenPrinter((wchar_t*)name.utf16(), &hPrinter, 0)) + d->num_copies = d->devMode->dmCopies; + d->updateCustomPaperSize(); + + if (!OpenPrinter((wchar_t*)d->name.utf16(), &d->hPrinter, 0)) qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); } - if (hdc) - initHDC(); + if (d->hdc) + d->initHDC(); +} + +HGLOBAL QWin32PrintEngine::globalDevMode() +{ + Q_D(QWin32PrintEngine); + return d->globalDevMode; } static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc, diff --git a/src/printsupport/kernel/qprintengine_win_p.h b/src/printsupport/kernel/qprintengine_win_p.h index b651487a13..d720561c2a 100644 --- a/src/printsupport/kernel/qprintengine_win_p.h +++ b/src/printsupport/kernel/qprintengine_win_p.h @@ -107,6 +107,12 @@ public: static QList supportedPaperSizes(const QPrinterInfo &printerInfo); static QList > supportedSizesWithNames(const QPrinterInfo &printerInfo); + + /* Used by print/page setup dialogs */ + void setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalDevMode); + HGLOBAL *createGlobalDevNames(); + HGLOBAL globalDevMode(); + static void queryDefaultPrinter(QString &name); private: @@ -166,12 +172,6 @@ public: is handled in the next begin or newpage. */ void doReinit(); - /* Used by print/page setup dialogs */ - HGLOBAL *createDevNames(); - - void readDevmode(HGLOBAL globalDevmode); - void readDevnames(HGLOBAL globalDevnames); - inline bool resetDC() { hdc = ResetDC(hdc, devMode); return hdc != 0; From aab29d546c006bf9be3fccd484e88ecc840bc0e3 Mon Sep 17 00:00:00 2001 From: John Layt Date: Wed, 19 Feb 2014 15:07:10 +0100 Subject: [PATCH 092/124] QPrinter - Add more tests Add more missing tests. Change-Id: I801c5c67731075ccb3e62377c0eccc420e708365 Reviewed-by: Andy Shaw --- .../kernel/qprinter/tst_qprinter.cpp | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp index 9571cb4110..b138f34967 100644 --- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp +++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp @@ -1259,6 +1259,8 @@ void tst_QPrinter::fullPage() QCOMPARE(pdf.fullPage(), false); pdf.setFullPage(true); QCOMPARE(pdf.fullPage(), true); + pdf.setFullPage(false); + QCOMPARE(pdf.fullPage(), false); QPrinter native; if (native.outputFormat() == QPrinter::NativeFormat) { @@ -1275,6 +1277,17 @@ void tst_QPrinter::fullPage() QCOMPARE(native.fullPage(), expected); native.setOutputFormat(QPrinter::NativeFormat); QCOMPARE(native.fullPage(), expected); + + // Test set/get + expected = false; + native.setFullPage(expected); + QCOMPARE(native.fullPage(), expected); + + // Test value preservation + native.setOutputFormat(QPrinter::PdfFormat); + QCOMPARE(native.fullPage(), expected); + native.setOutputFormat(QPrinter::NativeFormat); + QCOMPARE(native.fullPage(), expected); } else { QSKIP("No printers installed, cannot test NativeFormat, please install printers to test"); } @@ -1310,6 +1323,17 @@ void tst_QPrinter::orientation() QCOMPARE(native.orientation(), expected); native.setOutputFormat(QPrinter::NativeFormat); QCOMPARE(native.orientation(), expected); + + // Test set/get + expected = QPrinter::Portrait; + native.setOrientation(expected); + QCOMPARE(native.orientation(), expected); + + // Test value preservation + native.setOutputFormat(QPrinter::PdfFormat); + QCOMPARE(native.orientation(), expected); + native.setOutputFormat(QPrinter::NativeFormat); + QCOMPARE(native.orientation(), expected); } else { QSKIP("No printers installed, cannot test NativeFormat, please install printers to test"); } @@ -1710,13 +1734,8 @@ void tst_QPrinter::resolution() // Test set/get int expected = 333; #ifdef Q_OS_MAC + // Set resolution does nothing on OSX, see QTBUG-7000 expected = native.resolution(); - foreach (int supported, native.supportedResolutions()) { - if (supported != expected) { - expected = supported; - break; - } - } #endif // Q_OS_MAC native.setResolution(expected); QCOMPARE(native.resolution(), expected); From 24f10256631cd1e0f461430a50be36b74f19e01e Mon Sep 17 00:00:00 2001 From: Jorgen Lind Date: Tue, 25 Feb 2014 14:46:56 +0100 Subject: [PATCH 093/124] Remove the option to force no JIT in javascript core Change-Id: I81a9968b360cf889f92e690cdf4028692b904a0c Reviewed-by: Simon Hausmann --- configure | 30 ------------------------------ tools/configure/configureapp.cpp | 7 ------- 2 files changed, 37 deletions(-) diff --git a/configure b/configure index 7e84123882..88ec0256cc 100755 --- a/configure +++ b/configure @@ -627,7 +627,6 @@ CFG_COMPILE_EXAMPLES=yes CFG_RELEASE_QMAKE=no CFG_AUDIO_BACKEND=auto CFG_QML_DEBUG=yes -CFG_JAVASCRIPTCORE_JIT=auto CFG_PKGCONFIG=auto CFG_STACK_PROTECTOR_STRONG=auto CFG_SLOG2=auto @@ -1897,13 +1896,6 @@ while [ "$#" -gt 0 ]; do fi fi ;; - javascript-jit) - if [ "$VAL" = "yes" ] || [ "$VAL" = "auto" ] || [ "$VAL" = "no" ]; then - CFG_JAVASCRIPTCORE_JIT="$VAL" - else - UNKNOWN_OPT=yes - fi - ;; confirm-license) if [ "$VAL" = "yes" ]; then OPT_CONFIRM_LICENSE="$VAL" @@ -5737,27 +5729,6 @@ if [ "$CFG_ALSA" = "auto" ]; then fi fi -if [ "$CFG_JAVASCRIPTCORE_JIT" = "yes" ] || [ "$CFG_JAVASCRIPTCORE_JIT" = "auto" ]; then - if [ "$CFG_ARCH" = "arm" ]; then - compileTest unix/javascriptcore-jit "javascriptcore-jit" - if [ $? != "0" ]; then - CFG_JAVASCRIPTCORE_JIT=no - fi - else - case "$XPLATFORM" in - linux-icc*) - CFG_JAVASCRIPTCORE_JIT=no - ;; - esac - fi -fi - -if [ "$CFG_JAVASCRIPTCORE_JIT" = "yes" ]; then - QMakeVar set JAVASCRIPTCORE_JIT yes -elif [ "$CFG_JAVASCRIPTCORE_JIT" = "no" ]; then - QMakeVar set JAVASCRIPTCORE_JIT no -fi - if [ "$CFG_AUDIO_BACKEND" = "auto" ]; then CFG_AUDIO_BACKEND=yes fi @@ -6787,7 +6758,6 @@ report_support " Qt Concurrent .........." "$CFG_CONCURRENT" report_support " Qt GUI ................." "$CFG_GUI" report_support " Qt Widgets ............." "$CFG_WIDGETS" report_support " Large File ............." "$CFG_LARGEFILE" -report_support " JavaScriptCore JIT ....." "$CFG_JAVASCRIPTCORE_JIT" auto "To be decided by JavaScriptCore" report_support " QML debugging .........." "$CFG_QML_DEBUG" report_support " Use system proxies ....." "$CFG_SYSTEM_PROXIES" diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index ed854a343b..ac794d4c43 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1691,7 +1691,6 @@ void Configure::applySpecSpecifics() dictionary[ "REDUCE_RELOCATIONS" ] = "yes"; dictionary[ "QT_GETIFADDRS" ] = "no"; dictionary[ "QT_XKBCOMMON" ] = "no"; - dictionary[ "JAVASCRIPTCORE_JIT" ] = "no"; } } @@ -2744,12 +2743,6 @@ void Configure::generateOutputVars() if (!dictionary["QT_LFLAGS_SQLITE"].isEmpty()) qmakeVars += "QT_LFLAGS_SQLITE += " + dictionary["QT_LFLAGS_SQLITE"]; - if (dictionary["JAVASCRIPTCORE_JIT"] == "no") - qmakeVars += "JAVASCRIPTCORE_JIT = no"; - else if (dictionary["JAVASCRIPTCORE_JIT"] == "yes") - qmakeVars += "JAVASCRIPTCORE_JIT = yes"; - // else let JavaScriptCore decide - if (dictionary[ "OPENGL" ] == "yes") qtConfig += "opengl"; From 5ce87f07821257891ee66d4d3232f1e010f8c171 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 26 Feb 2014 08:50:40 +0100 Subject: [PATCH 094/124] Fix compile error when enabling the QHOSTINFO_DEBUG define Change-Id: Id82b3aad3b2951e6d0dee57ac993535930db31fc Reviewed-by: Oliver Wolff --- src/network/kernel/qhostinfo_win.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index 570d1a82ea..cbaa9bec6a 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -134,8 +134,8 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QHostInfo results; #if defined(QHOSTINFO_DEBUG) - qDebug("QHostInfoAgent::fromName(%p): looking up \"%s\" (IPv6 support is %s)", - this, hostName.toLatin1().constData(), + qDebug("QHostInfoAgent::fromName(): looking up \"%s\" (IPv6 support is %s)", + hostName.toLatin1().constData(), (local_getaddrinfo && local_freeaddrinfo) ? "enabled" : "disabled"); #endif @@ -248,8 +248,8 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) #if defined(QHOSTINFO_DEBUG) if (results.error() != QHostInfo::NoError) { - qDebug("QHostInfoAgent::run(%p): error (%s)", - this, results.errorString().toLatin1().constData()); + qDebug("QHostInfoAgent::run(): error (%s)", + results.errorString().toLatin1().constData()); } else { QString tmp; QList addresses = results.addresses(); @@ -257,8 +257,8 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) if (i != 0) tmp += ", "; tmp += addresses.at(i).toString(); } - qDebug("QHostInfoAgent::run(%p): found %i entries: {%s}", - this, addresses.count(), tmp.toLatin1().constData()); + qDebug("QHostInfoAgent::run(): found %i entries: {%s}", + addresses.count(), tmp.toLatin1().constData()); } #endif return results; From f3ed93e4862a1384cf176b17675cfa78cbbeef74 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 24 Feb 2014 14:20:44 +0100 Subject: [PATCH 095/124] Logging: Change 'rules' section name to 'Rules' This is more consistent with e.g. qt.conf, where section names also start with an upper case character. Change-Id: I9ddaf72baeb9334d081807412512242d5d46cbbf Reviewed-by: Friedemann Kleint Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qloggingcategory.cpp | 2 +- src/corelib/io/qloggingregistry.cpp | 4 ++-- tests/auto/corelib/io/qloggingregistry/qtlogging.ini | 2 +- .../io/qloggingregistry/tst_qloggingregistry.cpp | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index f37b9575aa..eb8aeaca50 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -109,7 +109,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory, apply to a category/type, the rule that comes later is applied. Rules can be set via \l setFilterRules(). Since Qt 5.3 logging rules - are also automatically loaded from the \c [rules] section of a logging + are also automatically loaded from the \c [Rules] section of a logging configuration file. Such configuration files are looked up in the QtProject configuration directory, or explicitly set in a \c QT_LOGGING_CONF environment variable. diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index b8fef16c0e..2619743ff4 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -203,7 +203,7 @@ void QLoggingSettingsParser::setContent(QTextStream &stream) continue; } - if (_section == QLatin1String("rules")) { + if (_section == QLatin1String("Rules")) { int equalPos = line.indexOf(QLatin1Char('=')); if ((equalPos != -1) && (line.lastIndexOf(QLatin1Char('=')) == equalPos)) { @@ -298,7 +298,7 @@ void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat) void QLoggingRegistry::setApiRules(const QString &content) { QLoggingSettingsParser parser; - parser.setSection(QStringLiteral("rules")); + parser.setSection(QStringLiteral("Rules")); parser.setContent(content); QMutexLocker locker(®istryMutex); diff --git a/tests/auto/corelib/io/qloggingregistry/qtlogging.ini b/tests/auto/corelib/io/qloggingregistry/qtlogging.ini index 63b384e36a..fd7a4f8c54 100644 --- a/tests/auto/corelib/io/qloggingregistry/qtlogging.ini +++ b/tests/auto/corelib/io/qloggingregistry/qtlogging.ini @@ -1,2 +1,2 @@ -[rules] +[Rules] *=true diff --git a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp index b538525161..dc6f16828b 100644 --- a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp +++ b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp @@ -63,16 +63,16 @@ private slots: { // // Logging configuration can be described - // in an .ini file. [rules] is the + // in an .ini file. [Rules] is the // default category, and optional ... // QLoggingSettingsParser parser; - parser.setContent("[rules]\n" + parser.setContent("[Rules]\n" "default=false\n" "default=true"); QCOMPARE(parser.rules().size(), 2); - parser.setContent("[rules]\n" + parser.setContent("[Rules]\n" "default=false"); QCOMPARE(parser.rules().size(), 1); @@ -115,7 +115,7 @@ private slots: QFile file(dir.absoluteFilePath("qtlogging.ini")); QVERIFY(file.open(QFile::WriteOnly | QFile::Text)); QTextStream out(&file); - out << "[rules]\n"; + out << "[Rules]\n"; out << "Digia.*=false\n"; file.close(); @@ -153,7 +153,7 @@ private slots: // set Config rule QLoggingSettingsParser parser; - parser.setContent("[rules]\nDigia.*=false"); + parser.setContent("[Rules]\nDigia.*=false"); registry->configRules=parser.rules(); registry->updateRules(); From b79e73476771c068098270ebc26fb1e015f0e149 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Jan 2014 14:25:42 +0100 Subject: [PATCH 096/124] Android: Support pregenerated cache in assets file engine This provides a way for androiddeployqt to pregenerate the entry list cache for the assets file engine, greatly improving performance the first time a directory is read. If the file is not present, the cache will operate as before. Some numbers from testing on Samsung Galaxy 2, doing QDir::entryList() on a directory inside the assets folder: 10 files -------- Before: 280 ms for first read, 5 ms for subsequent reads After: 2 ms for reading pregenerated cache 5 ms for first read 5 ms for subsequent reads 2000 files ---------- Before: 1000 ms for first read, 150 ms for subsequent reads After: 5 ms for reading pregenerated cache 150 ms for first read 150 ms for subsequent reads 4000 files ---------- Before: 3000 ms for first read 300 ms for subsequent reads After: 8 ms for reading pregenerated cache 300 ms for first read 300 ms for subsequent reads [ChangeLog][Android] Speed up first time directory listing in assets by using pregenerated entry list. Task-number: QTBUG-33704 Change-Id: I3973a1d823b8b38e88a2cc7843326cbe885f8bc2 Reviewed-by: Christian Stromme --- .../qandroidassetsfileenginehandler.cpp | 128 ++++++++++++++---- .../android/qandroidassetsfileenginehandler.h | 3 + 2 files changed, 107 insertions(+), 24 deletions(-) diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index 5f77d1645a..b112e265a5 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -51,10 +51,12 @@ struct AndroidAssetDir { AndroidAssetDir(AAssetDir* ad) { - const char *fileName; - while ((fileName = AAssetDir_getNextFileName(ad))) - m_items.push_back(QString::fromUtf8(fileName)); - AAssetDir_close(ad); + if (ad) { + const char *fileName; + while ((fileName = AAssetDir_getNextFileName(ad))) + m_items.push_back(QString::fromUtf8(fileName)); + AAssetDir_close(ad); + } } FilesList m_items; }; @@ -82,7 +84,10 @@ public: { if (m_index < 0 || m_index >= m_items.size()) return QString(); - return m_items[m_index]; + QString fileName = m_items[m_index]; + if (fileName.endsWith(QLatin1Char('/'))) + fileName.chop(1); + return fileName; } virtual QString currentFilePath() const @@ -254,33 +259,106 @@ private: }; -AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler():m_assetsCache(std::max(5, qgetenv("QT_ANDROID_MAX_ASSETS_CACHE_SIZE").toInt())) +AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler() + : m_assetsCache(std::max(5, qgetenv("QT_ANDROID_MAX_ASSETS_CACHE_SIZE").toInt())) + , m_hasPrepopulatedCache(false) { m_assetManager = QtAndroid::assetManager(); + prepopulateCache(); } AndroidAssetsFileEngineHandler::~AndroidAssetsFileEngineHandler() { } +void AndroidAssetsFileEngineHandler::prepopulateCache() +{ + QMutexLocker locker(&m_assetsCacheMutext); + Q_ASSERT(m_assetsCache.isEmpty()); + + // Failsafe: Don't read cache files that are larger than 1MB + static qint64 maxPrepopulatedCacheSize = qMax(1024LL * 1024LL, + qgetenv("QT_ANDROID_MAX_PREPOPULATED_ASSETS_CACHE_SIZE").toLongLong()); + + const char *fileName = "--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list"; + AAsset *asset = AAssetManager_open(m_assetManager, fileName, AASSET_MODE_BUFFER); + if (asset) { + m_hasPrepopulatedCache = true; + AndroidAbstractFileEngine fileEngine(asset, QString::fromLatin1(fileName)); + if (fileEngine.open(QIODevice::ReadOnly)) { + qint64 size = fileEngine.size(); + + if (size <= maxPrepopulatedCacheSize) { + QByteArray bytes(size, Qt::Uninitialized); + qint64 read = fileEngine.read(bytes.data(), size); + if (read != size) { + qWarning("Failed to read prepopulated cache"); + return; + } + + QDataStream stream(&bytes, QIODevice::ReadOnly); + stream.setVersion(QDataStream::Qt_5_3); + if (stream.status() != QDataStream::Ok) { + qWarning("Failed to read prepopulated cache"); + return; + } + + while (!stream.atEnd()) { + QString directoryName; + stream >> directoryName; + + int fileCount; + stream >> fileCount; + + QVector fileList; + fileList.reserve(fileCount); + while (fileCount--) { + QString fileName; + stream >> fileName; + fileList.append(fileName); + } + + QSharedPointer *aad = new QSharedPointer(new AndroidAssetDir(0)); + (*aad)->m_items = fileList; + + // Cost = 0, because we should always cache everything if there's a prepopulated cache + QByteArray key = directoryName != QLatin1String("/") + ? QByteArray("assets:/") + directoryName.toUtf8() + : QByteArray("assets:"); + + bool ok = m_assetsCache.insert(key, aad, 0); + if (!ok) + qWarning("Failed to insert in cache: %s", qPrintable(directoryName)); + } + } else { + qWarning("Prepopulated cache is too large to read.\n" + "Use environment variable QT_ANDROID_MAX_PREPOPULATED_ASSETS_CACHE_SIZE to adjust size."); + } + } + } +} + QAbstractFileEngine * AndroidAssetsFileEngineHandler::create(const QString &fileName) const { if (fileName.isEmpty()) return 0; - if (!fileName.startsWith(QLatin1String("assets:/"))) + static QLatin1String assetsPrefix("assets:"); + if (!fileName.startsWith(assetsPrefix)) return 0; - int prefixSize=8; + static int prefixSize = assetsPrefix.size() + 1; QByteArray path; if (!fileName.endsWith(QLatin1Char('/'))) { path = fileName.toUtf8(); - AAsset *asset = AAssetManager_open(m_assetManager, - path.constData() + prefixSize, - AASSET_MODE_BUFFER); - if (asset) - return new AndroidAbstractFileEngine(asset, fileName); + if (path.size() > prefixSize) { + AAsset *asset = AAssetManager_open(m_assetManager, + path.constData() + prefixSize, + AASSET_MODE_BUFFER); + if (asset) + return new AndroidAbstractFileEngine(asset, fileName); + } } if (!path.size()) @@ -290,17 +368,19 @@ QAbstractFileEngine * AndroidAssetsFileEngineHandler::create(const QString &file QSharedPointer *aad = m_assetsCache.object(path); m_assetsCacheMutext.unlock(); if (!aad) { - AAssetDir *assetDir = AAssetManager_openDir(m_assetManager, path.constData() + prefixSize); - if (assetDir) { - if (AAssetDir_getNextFileName(assetDir)) { - AAssetDir_rewind(assetDir); - aad = new QSharedPointer(new AndroidAssetDir(assetDir)); - m_assetsCacheMutext.lock(); - m_assetsCache.insert(path, aad); - m_assetsCacheMutext.unlock(); - return new AndroidAbstractFileEngine(*aad, fileName); - } else { - AAssetDir_close(assetDir); + if (!m_hasPrepopulatedCache && path.size() > prefixSize) { + AAssetDir *assetDir = AAssetManager_openDir(m_assetManager, path.constData() + prefixSize); + if (assetDir) { + if (AAssetDir_getNextFileName(assetDir)) { + AAssetDir_rewind(assetDir); + aad = new QSharedPointer(new AndroidAssetDir(assetDir)); + m_assetsCacheMutext.lock(); + m_assetsCache.insert(path, aad); + m_assetsCacheMutext.unlock(); + return new AndroidAbstractFileEngine(*aad, fileName); + } else { + AAssetDir_close(assetDir); + } } } } else { diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h index 7bd560886c..d56367d4d8 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h @@ -58,9 +58,12 @@ public: QAbstractFileEngine *create(const QString &fileName) const; private: + void prepopulateCache(); + AAssetManager *m_assetManager; mutable QCache> m_assetsCache; mutable QMutex m_assetsCacheMutext; + bool m_hasPrepopulatedCache; }; #endif // QANDROIDASSETSFILEENGINEHANDLER_H From a2f79b0d0f2373179998dd226bc5a86ad31f4e7e Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 21 Feb 2014 14:21:58 +0100 Subject: [PATCH 097/124] Android: Make default permissions less confusing Add comments to explain the magic placeholders for default permissions and features, and move the INTERNET and WRITE_EXTERNAL_STORAGE permissions from the manifest so that we use the same mechanism for all default permissions. Change-Id: Ia62dd4314c1c10eb201b5203772ffe88b1ce7a04 Reviewed-by: Paul Olav Tvete --- src/android/java/AndroidManifest.xml | 9 +++++++-- src/corelib/corelib.pro | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/android/java/AndroidManifest.xml b/src/android/java/AndroidManifest.xml index 3a2a52b874..3209ab58ac 100644 --- a/src/android/java/AndroidManifest.xml +++ b/src/android/java/AndroidManifest.xml @@ -39,8 +39,13 @@ + + - - + + + diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 373b3f148d..79c90e0664 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -24,6 +24,9 @@ ANDROID_LIB_DEPENDENCIES = \ ANDROID_BUNDLED_JAR_DEPENDENCIES = \ jar/QtAndroid-bundled.jar \ jar/QtAndroidAccessibility-bundled.jar +ANDROID_PERMISSIONS = \ + android.permission.INTERNET \ + android.permission.WRITE_EXTERNAL_STORAGE load(qt_module) From 357363dd51e885447202fc753792a49b5812539a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 24 Feb 2014 16:40:00 +0100 Subject: [PATCH 098/124] Texture glyph cache: Use a vbo It is not going to work with core profile otherwise. This fixes one of the several problems that make native text rendering in Quick impossible with OpenGL core profile. The GL2 paint engine path is not changed, that continues to use client side pointers. Task-number: QTBUG-36993 Change-Id: Icfbd6efc894a79a3a84568fb792c1cb6692469cb Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopengltextureglyphcache.cpp | 20 +++++++++++++++++--- src/gui/opengl/qopengltextureglyphcache_p.h | 3 +++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp index ba1fa8f486..f1bf944d7b 100644 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ b/src/gui/opengl/qopengltextureglyphcache.cpp @@ -58,6 +58,7 @@ QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat form , m_blitProgram(0) , m_filterMode(Nearest) , m_serialNumber(qopengltextureglyphcache_serial_number.fetchAndAddRelaxed(1)) + , m_buffer(QOpenGLBuffer::VertexBuffer) { #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG qDebug(" -> QOpenGLTextureGlyphCache() %p for context %p.", this, QOpenGLContext::currentContext()); @@ -139,6 +140,18 @@ void QOpenGLTextureGlyphCache::createTextureData(int width, int height) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); m_filterMode = Nearest; + + if (!m_buffer.isCreated()) { + m_buffer.create(); + m_buffer.bind(); + static GLfloat buf[sizeof(m_vertexCoordinateArray) + sizeof(m_textureCoordinateArray)]; + memcpy(buf, m_vertexCoordinateArray, sizeof(m_vertexCoordinateArray)); + memcpy(buf + (sizeof(m_vertexCoordinateArray) / sizeof(GLfloat)), + m_textureCoordinateArray, + sizeof(m_textureCoordinateArray)); + m_buffer.allocate(buf, sizeof(buf)); + m_buffer.release(); + } } void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) @@ -239,10 +252,10 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) m_blitProgram->link(); } - funcs.glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_vertexCoordinateArray); - funcs.glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_textureCoordinateArray); - + m_buffer.bind(); m_blitProgram->bind(); + m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), GL_FLOAT, 0, 2); + m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), GL_FLOAT, sizeof(m_vertexCoordinateArray), 2); m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR)); @@ -278,6 +291,7 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) } else { m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); + m_buffer.release(); } } diff --git a/src/gui/opengl/qopengltextureglyphcache_p.h b/src/gui/opengl/qopengltextureglyphcache_p.h index a361a79de2..394c28f7ff 100644 --- a/src/gui/opengl/qopengltextureglyphcache_p.h +++ b/src/gui/opengl/qopengltextureglyphcache_p.h @@ -57,6 +57,7 @@ #include #include #include +#include // #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG @@ -162,6 +163,8 @@ private: GLfloat m_textureCoordinateArray[8]; int m_serialNumber; + + QOpenGLBuffer m_buffer; }; QT_END_NAMESPACE From f7f70c4a7ab343f22e695a3dd4a0803b4b32c7fd Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 24 Feb 2014 17:37:09 +0100 Subject: [PATCH 099/124] Fix glyph texture format on core profile Native text rendering is now functional on core profile too, as long as the driver allows compiling GL2-style shaders. Task-number: QTBUG-36993 Change-Id: I83f3cafae714427dda807921ee79e5a64e55cc64 Reviewed-by: Gunnar Sletta --- src/gui/opengl/qopengltextureglyphcache.cpp | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp index f1bf944d7b..c3c04000a9 100644 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ b/src/gui/opengl/qopengltextureglyphcache.cpp @@ -89,6 +89,11 @@ QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache() #endif } +static inline bool isCoreProfile() +{ + return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile; +} + void QOpenGLTextureGlyphCache::createTextureData(int width, int height) { QOpenGLContext *ctx = const_cast(QOpenGLContext::currentContext()); @@ -132,7 +137,14 @@ void QOpenGLTextureGlyphCache::createTextureData(int width, int height) QVarLengthArray data(width * height); for (int i = 0; i < data.size(); ++i) data[i] = 0; - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]); +#if !defined(QT_OPENGL_ES_2) + const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA; + const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA; +#else + const GLint internalFormat = GL_ALPHA; + const GLenum format = GL_ALPHA; +#endif + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, &data[0]); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -409,7 +421,14 @@ void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i)); } else { #endif - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits()); + +#if !defined(QT_OPENGL_ES_2) + const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA; +#else + const GLenum format = GL_ALPHA; +#endif + glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits()); + #if 0 } #endif From f645dad757b23a21cbaf4449be96c75304d9f154 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 25 Feb 2014 11:03:31 +0100 Subject: [PATCH 100/124] Use a VAO in the texture glyph cache Task-number: QTBUG-36993 Change-Id: Icc77035b582c804ed809ea3cd99c0048b34d41d2 Reviewed-by: Gunnar Sletta Reviewed-by: Sean Harmer --- src/gui/opengl/qopengltextureglyphcache.cpp | 39 +++++++++++++++------ src/gui/opengl/qopengltextureglyphcache_p.h | 4 +++ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp index c3c04000a9..3524c1cb1a 100644 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ b/src/gui/opengl/qopengltextureglyphcache.cpp @@ -164,6 +164,19 @@ void QOpenGLTextureGlyphCache::createTextureData(int width, int height) m_buffer.allocate(buf, sizeof(buf)); m_buffer.release(); } + + if (!m_vao.isCreated()) + m_vao.create(); +} + +void QOpenGLTextureGlyphCache::setupVertexAttribs() +{ + m_buffer.bind(); + m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), GL_FLOAT, 0, 2); + m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), GL_FLOAT, sizeof(m_vertexCoordinateArray), 2); + m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); + m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); + m_buffer.release(); } void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) @@ -262,16 +275,19 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); m_blitProgram->link(); + + if (m_vao.isCreated()) { + m_vao.bind(); + setupVertexAttribs(); + } } - m_buffer.bind(); - m_blitProgram->bind(); - m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), GL_FLOAT, 0, 2); - m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), GL_FLOAT, sizeof(m_vertexCoordinateArray), 2); - m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); - m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); - m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR)); + if (m_vao.isCreated()) + m_vao.bind(); + else + setupVertexAttribs(); + m_blitProgram->bind(); blitProgram = m_blitProgram; } else { @@ -301,9 +317,12 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) glViewport(0, 0, pex->width, pex->height); pex->updateClipScissorTest(); } else { - m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); - m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); - m_buffer.release(); + if (m_vao.isCreated()) { + m_vao.release(); + } else { + m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); + m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); + } } } diff --git a/src/gui/opengl/qopengltextureglyphcache_p.h b/src/gui/opengl/qopengltextureglyphcache_p.h index 394c28f7ff..1e2c031018 100644 --- a/src/gui/opengl/qopengltextureglyphcache_p.h +++ b/src/gui/opengl/qopengltextureglyphcache_p.h @@ -58,6 +58,7 @@ #include #include #include +#include // #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG @@ -153,6 +154,8 @@ public: void clear(); private: + void setupVertexAttribs(); + QOpenGLGlyphTexture *m_textureResource; QOpenGL2PaintEngineExPrivate *pex; @@ -165,6 +168,7 @@ private: int m_serialNumber; QOpenGLBuffer m_buffer; + QOpenGLVertexArrayObject m_vao; }; QT_END_NAMESPACE From 39346df12cf5f755dc45a99680576e392945307c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 25 Feb 2014 13:36:26 +0100 Subject: [PATCH 101/124] Use Qt's RTTI setting when building ANGLE statically. Prevent errors when building Qt statically with RTTI enabled: warning C4743: 'const std::ios_base::failure::`vftable'' has different size in 'qtbase\src\3rdparty\angle\src\libGLESv2\Context.cpp' and '(...)': 16 and 12 bytes Task-number: QTBUG-36951 Change-Id: Ie0501b986be8610c8293cd5c1aa42b502d7c27a1 Reviewed-by: Andrew Knight Reviewed-by: Laszlo Agocs --- src/angle/src/config.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri index c3cc7e02c1..8e0f6b7f42 100644 --- a/src/angle/src/config.pri +++ b/src/angle/src/config.pri @@ -54,7 +54,7 @@ angle_d3d11 { CONFIG(debug, debug|release) { DEFINES += _DEBUG } else { - CONFIG += rtti_off + !static: CONFIG += rtti_off DEFINES += NDEBUG } From eeb1fcd55cd2139773e0e2072f25001d18e5c103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 13 Feb 2014 11:40:21 +0100 Subject: [PATCH 102/124] Cocoa: Don't crash at toolbar cleanup time. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing iterator increment. Change-Id: Id663c38859b89c29009f67205da0fdd404a455c0 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 0c1ddf9ad8..dff7c9bd50 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -487,6 +487,7 @@ void QCocoaIntegration::clearToolbars() QHash::const_iterator it = mToolbars.constBegin(); while (it != mToolbars.constEnd()) { [it.value() release]; + ++it; } mToolbars.clear(); } From 98405c41c2d824a981fd9afd9d53a74c4b9ac562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 4 Feb 2014 13:24:07 +0100 Subject: [PATCH 103/124] Cocoa: Remove tablet event warnings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt warns on all touchpad evens when running in a VM. This appears to be harmless. Remove the warning. Also, qWarnings are ideally messages to the application developer about incorrect use of Qt API. In this case there is nothing the application developer can do and a qWarning is not really appropriate. Task-number: QTBUG-36484 Change-Id: I8a50f5a15010f1f064509b83ef4f239b008e0f2b Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index e246775406..fcca96a8a8 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -859,14 +859,9 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash) uint deviceId = [theEvent deviceID]; if (!tabletDeviceDataHash->contains(deviceId)) { - // 10.6 sends tablet events for trackpad interaction, but - // not proximity events. Silence the warning to prevent - // flooding the console. - if (QSysInfo::QSysInfo::MacintoshVersion == QSysInfo::MV_10_6) - return; - - qWarning("QNSView handleTabletEvent: This tablet device is unknown" - " (received no proximity event for it). Discarding event."); + // Error: Unknown tablet device. Qt also gets into this state + // when running on a VM. This appears to be harmless; don't + // print a warning. return; } const QCocoaTabletDeviceData &deviceData = tabletDeviceDataHash->value(deviceId); From cea3f4d5357ae4417ff3624ecca32f9cd5d4c260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 23 Jan 2014 13:38:39 +0100 Subject: [PATCH 104/124] Cocoa: Set geometry for foreign views. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure QPlatformWindow::setGeometry is called for the QWindow::fromWinId() case where there is no QNSView. Change-Id: I72dd11a0eb0f3cfbd09b87ffeac86f2a826e0192 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 07b4100d4a..9321c1a48b 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -398,6 +398,9 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) [m_contentView setFrame : NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; } + if (!m_qtView) + QPlatformWindow::setGeometry(rect); + // will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) } From 66e5f8e9dcd11d136b707d13c7597019c99c54b8 Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Tue, 25 Feb 2014 23:37:06 +1100 Subject: [PATCH 105/124] eglfs: Improve cursors and hotspots Improvements * Cursor atlas has been recreated using 32x32 cursors which avoids artifacts introduced from downscaling of the busy cursor * A white outline has been added to the cursors to improve visibility on black backgrounds * Hot spot positions have been tweaked; in particular, Qt::PointingHandCursor now has a correct hot spot at the tip of the index finger instead of the center The assert which checks that the number of hot spots equals the number of cursors had an off-by-one error as the first cursor is Qt::ArrowCursor which has an enum value of 0. To determine the number of cursors, 1 needs to be added to Qt::LastCursor. Change-Id: I266b6d4cc47d42219854aa5b7e2d8344eb3a920a Reviewed-by: Laszlo Agocs --- .../eglconvenience/qeglplatformcursor.cpp | 4 +- src/plugins/platforms/eglfs/cursor-atlas.png | Bin 2735 -> 2928 bytes src/plugins/platforms/eglfs/cursor.json | 42 +++++++++--------- 3 files changed, 23 insertions(+), 23 deletions(-) mode change 100644 => 100755 src/plugins/platforms/eglfs/cursor-atlas.png diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp index 1c87e1d27d..70e7c4e4db 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp @@ -210,7 +210,7 @@ void QEGLPlatformCursor::initCursorAtlas() m_cursorAtlas.cursorsPerRow = cursorsPerRow; const QJsonArray hotSpots = object.value(QLatin1String("hotSpots")).toArray(); - Q_ASSERT(hotSpots.count() == Qt::LastCursor); + Q_ASSERT(hotSpots.count() == Qt::LastCursor + 1); for (int i = 0; i < hotSpots.count(); i++) { QPoint hotSpot(hotSpots[i].toArray()[0].toDouble(), hotSpots[i].toArray()[1].toDouble()); m_cursorAtlas.hotSpots << hotSpot; @@ -218,7 +218,7 @@ void QEGLPlatformCursor::initCursorAtlas() QImage image = QImage(atlas).convertToFormat(QImage::Format_ARGB32_Premultiplied); m_cursorAtlas.cursorWidth = image.width() / m_cursorAtlas.cursorsPerRow; - m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow - 1) / cursorsPerRow); + m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow) / cursorsPerRow); m_cursorAtlas.width = image.width(); m_cursorAtlas.height = image.height(); m_cursorAtlas.image = image; diff --git a/src/plugins/platforms/eglfs/cursor-atlas.png b/src/plugins/platforms/eglfs/cursor-atlas.png old mode 100644 new mode 100755 index 8d89a7ab863fbffd64e53539753ca7aedb2b63e1..4ddb7708e19cda8df7ca7783dd31ada14351c02b GIT binary patch literal 2928 zcmeHJ`#;lr82@}{a~aF^a7eX^n%f$OxwE-Txpq)4O{z^HvfL`Zl&0iQno}b>Y=l#5%i=OVz7_f|fEqg=`a@WBZ+9QD5dO;sd{(5i#Va5a z<+49Ud~;s^aL9VtpDzYA=#Kt$pA$#vaUmy<0MC%HNIKr#aUVAJ7rY7H(9l_6X9|F1 zgR291UwrUFX@(uoLe61QWLx(7a&OkbJbT#{Vl6|-c8O&i_O@+}e=6n@sMJWlIH0Zi-9(H1@$toTy!UZul3MliOEMPLOt^f3@^9cY%4V`4G0n;8(u`Kim+I;M??Pv@ z3dj-_l@v@aPpvNeL+@F)b#g`|xtOOwsevmieRB?zl5)+pwad+tGrZ~b#)v6&0k^TY z(R6XVuY71~o8C!hMK3oFn&kyn*!TnZ5oy>@U20+P6rw=TqS5|4BI1%eTx*u2N~^tR z*m>}dY4gCAx0b*Db-F+{XCKu{8(xXLe>eY{o84(YQ};po1EX-HOQH)}VL#zeX)>?o zQ(oUVb=tK|zT`>x*&;7ENV#ko*UHSqjwIzRMJFka40;<(aCf(DI6!C}c7+{M8c14_ z#Mj}|7iO?2BPH8Un|If(#8`7b<_}wZ$CT8_KR{TkwuKT?DO1^b8}FL5jxIYaK4zlZ z9pm-jb#JMOvbSnKGZmjn5N*ovGV?A^J5YYN&84T>h7B^o(oel@HI<^R|h>d)ddo~NSXXEPP< z)TI7N`$VK>`ykkt5iJ@O%CJbz1`n8oA*Eqlthx>)tT_{WFt{prd00q0u}!Uto?FDa zmfnswK$!WC)u1$@Y1i4VU3tPL_V#tbw0&#jsw>na%=Fy4$e-jHL_9Rgs4TCLUo~Dg zmxMMi8ZuV8tL{M)qB=pS6BPM40A#jL8^FDzf2opq5ec$Y{J#^H42E{hry)s<=;Br8 zQpr>cX7vK#caF5wPRSgj`$fL3s2iv_| z_IwwE#*&r3mjhp`S^KQ<8!}TeOUDBPLH2X`9JlxRJel`VMQRq|NZfQvw*xX!D=_?( zCk>S@@GE|&Q==u#dmf@kQkh?$TV9S-fzj+(xilvj*O{W(m_-vXv1HZ$rI4RgU=*!p znlP!b=LjJX;7GCqt8L&iL+w_!Zq>sg+`TN$QCU<;hw^Wgk}H!$a)BQ9A;ngpL~3xJ z)i7`3Bj97uZJCz%Lz*d%U=({M`$@m`D-Q`jhOC{mbK@G)5uAT6rEI!2t%=x2mqhl{ z)pPEuOe(7*V=1pfLyk5C&E`qM3Jm7G!5q+LT8bvf>8~SHC!Lr*9&LIZ+*(^;&1rZX zZs|UV6JfK4DN$c4S z)0#6e*!zA@pU}Yu>z^0QQUcPcdA;Yx(?4$JjbRg^k{cMc%l4-nm{dNN)4DaFXL!#* zi<(qxwNFCu{?fO~!Fp0J?cwX4F$k4&&8#cu>UPdHf5s*2!tIZObXhLmDpmE%H<#1FYAg(fuhCX+;7GeR#~Q&FQhfSp<~g} zxgj5d;nd+xjd`h06(XuU$HP1>6Y)rP1=n}d^mA;f+ z$W5xn&ty0v(Or!vDqmv|3Izj0ubmr7BUK{%lXt#5LnHN~j_L?h47W z=2ec@2V({;yK0hjW>>Pt*5u;?ni3dsOB3ihe7^0Q*)lJ1|9Ni^%Ix<#FlcI*TtbG| j`2U`bwjcERba#J;WCyD>vAY@BKRzB;M|X!NJ4)(5GYn{R literal 2735 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 pfdoMykRS*I5(I%jf*=qL#sBDY`d* Date: Tue, 18 Feb 2014 14:32:33 +0100 Subject: [PATCH 106/124] Cocoa: Fix popup window positioning. Popup window positions where offset on retina MacBooks with an connected external monitor. Fix this by cleaning up the coordinate conversion functions: Remove the qt_mac_flipRect overload which tries to position the window according screen size. This functionality does not belong inside a coordinate/ type conversion function. Also, it was using the windows's screen instead of the main screen which is incorrect. "Y flipping": Use the height of the first screen in [NSScreen screens], which is documented to always be the screen that contains the coordinate system origin. Remove the usages of QApplication::primaryScreen() ("Don't use Qt to implement Qt"). Task-number: QTBUG-36672 Change-Id: I2354d31361f5a4c2c80035cf4c7def939218406f Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoahelpers.h | 20 ++---- src/plugins/platforms/cocoa/qcocoahelpers.mm | 68 ++++++++++---------- src/plugins/platforms/cocoa/qcocoawindow.mm | 6 +- 3 files changed, 41 insertions(+), 53 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 893aa4408a..3b72184d83 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -103,23 +103,13 @@ CGColorSpaceRef qt_mac_displayColorSpace(const QWidget *widget); CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice); QString qt_mac_applicationName(); -inline int qt_mac_flipYCoordinate(int y) -{ return QGuiApplication::primaryScreen()->geometry().height() - y; } - -inline qreal qt_mac_flipYCoordinate(qreal y) -{ return QGuiApplication::primaryScreen()->geometry().height() - y; } - -inline QPointF qt_mac_flipPoint(const NSPoint &p) -{ return QPointF(p.x, qt_mac_flipYCoordinate(p.y)); } - -inline NSPoint qt_mac_flipPoint(const QPoint &p) -{ return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y())); } - -inline NSPoint qt_mac_flipPoint(const QPointF &p) -{ return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y())); } +int qt_mac_flipYCoordinate(int y); +qreal qt_mac_flipYCoordinate(qreal y); +QPointF qt_mac_flipPoint(const NSPoint &p); +NSPoint qt_mac_flipPoint(const QPoint &p); +NSPoint qt_mac_flipPoint(const QPointF &p); NSRect qt_mac_flipRect(const QRect &rect); -NSRect qt_mac_flipRect(const QRect &rect, QWindow *window); Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 9b3198224e..8975605e5c 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -595,47 +595,45 @@ QString qt_mac_applicationName() return appName; } +int qt_mac_mainScreenHeight() +{ + // The first screen in the screens array is documented + // to have the (0,0) origin. + NSRect screenFrame = [[[NSScreen screens] firstObject] frame]; + return screenFrame.size.height; +} + +int qt_mac_flipYCoordinate(int y) +{ + return qt_mac_mainScreenHeight() - y; +} + +qreal qt_mac_flipYCoordinate(qreal y) +{ + return qt_mac_mainScreenHeight() - y; +} + +QPointF qt_mac_flipPoint(const NSPoint &p) +{ + return QPointF(p.x, qt_mac_flipYCoordinate(p.y)); +} + +NSPoint qt_mac_flipPoint(const QPoint &p) +{ + return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y())); +} + +NSPoint qt_mac_flipPoint(const QPointF &p) +{ + return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y())); +} + NSRect qt_mac_flipRect(const QRect &rect) { int flippedY = qt_mac_flipYCoordinate(rect.y() + rect.height()); return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height()); } -/* - Mac window coordinates are in the first quadrant: 0, 0 is at the lower-left - corner of the primary screen. This function converts the given rect to an - NSRect for the window geometry, flipping from 4th quadrant to 1st quadrant - and simultaneously ensuring that as much of the window as possible will be - onscreen. If the rect is too tall for the screen, the OS will reduce the - window's height anyway; but by moving the window upwards we can have more - of it onscreen. But the application can still control the y coordinate - in case it really wants the window to be positioned partially offscreen. -*/ -NSRect qt_mac_flipRect(const QRect &rect, QWindow *window) -{ - QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window); - int flippedY = onScreen->geometry().height() - (rect.y() + rect.height()); - QList screens = QGuiApplication::screens(); - if (screens.size() > 1) { - int height = 0; - foreach (QScreen *scr, screens) - height = qMax(height, scr->size().height()); - int difference = height - onScreen->geometry().height(); - if (difference > 0) - flippedY += difference; - else - flippedY -= difference; - } - // In case of automatic positioning, try to put as much of the window onscreen as possible. - if (window->isTopLevel() && qt_window_private(const_cast(window))->positionAutomatic && flippedY < 0) - flippedY = onScreen->geometry().height() - onScreen->availableGeometry().height() - onScreen->availableGeometry().y(); -#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << Q_FUNC_INFO << rect << "flippedY" << flippedY << - "screen" << onScreen->geometry() << "available" << onScreen->availableGeometry(); -#endif - return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height()); -} - OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage) { // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 9321c1a48b..bf41270d12 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -392,7 +392,7 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) QWindowSystemInterface::handleGeometryChange(window(), rect); QWindowSystemInterface::handleExposeEvent(window(), rect); } else if (m_nsWindow) { - NSRect bounds = qt_mac_flipRect(rect, window()); + NSRect bounds = qt_mac_flipRect(rect); [m_nsWindow setFrame:[m_nsWindow frameRectForContentRect:bounds] display:YES animate:NO]; } else { [m_contentView setFrame : NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; @@ -418,7 +418,7 @@ void QCocoaWindow::clipWindow(const NSRect &clipRect) NSRect clippedWindowRect = NSZeroRect; if (!NSIsEmptyRect(clipRect)) { - NSRect windowFrame = qt_mac_flipRect(QRect(window()->mapToGlobal(QPoint(0, 0)), geometry().size()), window()); + NSRect windowFrame = qt_mac_flipRect(QRect(window()->mapToGlobal(QPoint(0, 0)), geometry().size())); clippedWindowRect = NSIntersectionRect(windowFrame, clipRect); // Clipping top/left offsets the content. Move it back. NSPoint contentViewOffset = NSMakePoint(qMax(CGFloat(0), NSMinX(clippedWindowRect) - NSMinX(windowFrame)), @@ -1208,7 +1208,7 @@ NSWindow * QCocoaWindow::createNSWindow() QCocoaAutoReleasePool pool; QRect rect = initialGeometry(window(), window()->geometry(), defaultWindowWidth, defaultWindowHeight); - NSRect frame = qt_mac_flipRect(rect, window()); + NSRect frame = qt_mac_flipRect(rect); Qt::WindowType type = window()->type(); Qt::WindowFlags flags = window()->flags(); From 1a6a763254b1844cb3f951e724d58a0fd29f62b5 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 26 Feb 2014 18:09:34 +0100 Subject: [PATCH 107/124] Handle multiple header values in SPDY SPDY sends multiple header values for the same header key by null-byte separating them. This patch maps the multiple values the same way qnetworkreplyhttpimpl.cpp does. With this patch applied we can now log on to GMail using SPDY. Change-Id: I03656ad1695d13b5c3ed252794dc6c89c67c7b97 Reviewed-by: Peter Hartmann --- src/network/access/qspdyprotocolhandler.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/network/access/qspdyprotocolhandler.cpp b/src/network/access/qspdyprotocolhandler.cpp index f12b9535fe..d9d861f9b4 100644 --- a/src/network/access/qspdyprotocolhandler.cpp +++ b/src/network/access/qspdyprotocolhandler.cpp @@ -912,6 +912,19 @@ void QSpdyProtocolHandler::parseHttpHeaders(char flags, const QByteArray &frameD } else if (name == "content-length") { httpReply->setContentLength(value.toLongLong()); } else { + if (value.contains('\0')) { + QList values = value.split('\0'); + QByteArray binder(", "); + if (name == "set-cookie") + binder = "\n"; + value.clear(); + Q_FOREACH (const QByteArray& ivalue, values) { + if (value.isEmpty()) + value = ivalue; + else + value += binder + ivalue; + } + } httpReply->setHeaderField(name, value); } } From bbc4cc4a47bb96c8cb85b6f0dd607020e74f3e2c Mon Sep 17 00:00:00 2001 From: Jorgen Lind Date: Wed, 26 Feb 2014 14:41:55 +0100 Subject: [PATCH 108/124] XCB: update the platformwindows version of Qt::WindowState when the event comes from the windowing system Task-number: QTBUG-31117 Change-Id: Id136ad8c39c9284cbd6ad126ee71ac655f8f91ef Reviewed-by: Friedemann Kleint --- src/plugins/platforms/xcb/qxcbwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index d0106984a2..29f71e6972 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1859,6 +1859,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev if (m_lastWindowStateEvent != newState) { QWindowSystemInterface::handleWindowStateChanged(window(), newState); m_lastWindowStateEvent = newState; + m_windowState = newState; } return; } From cebdd91f8bbebf43fd2ec3c4dd2f49f46172d47e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 26 Feb 2014 15:02:30 +0100 Subject: [PATCH 109/124] Windows: Add platform plugin parameter for tablet absolute range. Make the range for detecting relative (mouse mode) configureable using -platform windows:tabletabsoluterange=50 Task-number: QTBUG-36937 Change-Id: I44f928e53cb41b246c44554ec7f71bfbdf03c147 Reviewed-by: Arthur Krebsbach Reviewed-by: Laszlo Agocs Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowscontext.cpp | 10 ++++++++++ src/plugins/platforms/windows/qwindowscontext.h | 2 ++ .../platforms/windows/qwindowsintegration.cpp | 13 ++++++++++--- .../platforms/windows/qwindowstabletsupport.cpp | 4 ++-- .../platforms/windows/qwindowstabletsupport.h | 4 ++++ 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 08f3ab4dbd..f67fb9bc19 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -341,6 +341,16 @@ QWindowsContext::~QWindowsContext() m_instance = 0; } +void QWindowsContext::setTabletAbsoluteRange(int a) +{ +#if !defined(QT_NO_TABLETEVENT) && !defined(Q_OS_WINCE) + if (!d->m_tabletSupport.isNull()) + d->m_tabletSupport->setAbsoluteRange(a); +#else + Q_UNUSED(a) +#endif +} + QWindowsContext *QWindowsContext::instance() { return m_instance; diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 1fea059ed9..f5dbd072c7 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -183,6 +183,8 @@ public: void setWindowCreationContext(const QSharedPointer &ctx); + void setTabletAbsoluteRange(int a); + // Returns a combination of SystemInfoFlags unsigned systemInfo() const; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index e5d9444966..3735865845 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -143,7 +143,7 @@ struct QWindowsIntegrationPrivate explicit QWindowsIntegrationPrivate(const QStringList ¶mList); ~QWindowsIntegrationPrivate(); - const unsigned m_options; + unsigned m_options; QWindowsContext m_context; QPlatformFontDatabase *m_fontDatabase; #ifndef QT_NO_CLIPBOARD @@ -165,7 +165,8 @@ struct QWindowsIntegrationPrivate QWindowsServices m_services; }; -static inline unsigned parseOptions(const QStringList ¶mList) +static inline unsigned parseOptions(const QStringList ¶mList, + int *tabletAbsoluteRange) { unsigned options = 0; foreach (const QString ¶m, paramList) { @@ -187,15 +188,21 @@ static inline unsigned parseOptions(const QStringList ¶mList) options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch; } else if (param.startsWith(QLatin1String("verbose="))) { QWindowsContext::verbose = param.right(param.size() - 8).toInt(); + } else if (param.startsWith(QLatin1String("tabletabsoluterange="))) { + *tabletAbsoluteRange = param.rightRef(param.size() - 20).toInt(); } } return options; } QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList ¶mList) - : m_options(parseOptions(paramList)) + : m_options(0) , m_fontDatabase(0) { + int tabletAbsoluteRange = -1; + m_options = parseOptions(paramList, &tabletAbsoluteRange); + if (tabletAbsoluteRange >= 0) + m_context.setTabletAbsoluteRange(tabletAbsoluteRange); } QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate() diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index 8b863ec43d..484ed9cb05 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -159,6 +159,7 @@ bool QWindowsWinTab32DLL::init() QWindowsTabletSupport::QWindowsTabletSupport(HWND window, HCTX context) : m_window(window) , m_context(context) + , m_absoluteRange(20) , m_tiltSupport(false) , m_currentDevice(-1) { @@ -402,7 +403,6 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() // in which case we snap the position to the mouse position. // It seems there is no way to find out the mode programmatically, the LOGCONTEXT orgX/Y/Ext // area is always the virtual desktop. - enum { absoluteRange = 20 }; const QRect virtualDesktopArea = QGuiApplication::primaryScreen()->virtualGeometry(); qCDebug(lcQpaTablet) << __FUNCTION__ << "processing " << packetCount @@ -427,7 +427,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() // Positions should be almost the same if we are in absolute // mode. If they are not, use the mouse location. - if ((mouseLocation - globalPos).manhattanLength() > absoluteRange) { + if ((mouseLocation - globalPos).manhattanLength() > m_absoluteRange) { globalPos = mouseLocation; globalPosF = globalPos; } diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h index 5e29cd9554..527d9dbf37 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.h +++ b/src/plugins/platforms/windows/qwindowstabletsupport.h @@ -124,6 +124,9 @@ public: bool translateTabletProximityEvent(WPARAM wParam, LPARAM lParam); bool translateTabletPacketEvent(); + int absoluteRange() const { return m_absoluteRange; } + void setAbsoluteRange(int a) { m_absoluteRange = a; } + private: unsigned options() const; QWindowsTabletDeviceData tabletInit(const quint64 uniqueId, const UINT cursorType) const; @@ -131,6 +134,7 @@ private: static QWindowsWinTab32DLL m_winTab32DLL; const HWND m_window; const HCTX m_context; + int m_absoluteRange; bool m_tiltSupport; QVector m_devices; int m_currentDevice; From b3aed29c434994f2e980a8ca371ab83b48e5d98b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 26 Feb 2014 16:24:58 +0100 Subject: [PATCH 110/124] Windows: Set source of synthesized mouse events correctly. The source was never set for OS-synthesized events, causing duplicated touch clicks to occur in Quick 2 applications. Task-number: QTBUG-31386 Change-Id: Ib6d1405815dfb8e57d6446c72a7d6e2a044281ea Reviewed-by: Laszlo Agocs Reviewed-by: Oliver Wolff --- .../platforms/windows/qwindowsmousehandler.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index d8c0a9e426..dfa400285a 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -173,15 +173,15 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, // Check for events synthesized from touch. Lower byte is touch index, 0 means pen. static const bool passSynthesizedMouseEvents = !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch); - if (!passSynthesizedMouseEvents) { - // Check for events synthesized from touch. Lower 7 bits are touch/pen index, bit 8 indicates touch. - // However, when tablet support is active, extraInfo is a packet serial number. This is not a problem - // since we do not want to ignore mouse events coming from a tablet. - const quint64 extraInfo = GetMessageExtraInfo(); - const bool fromTouch = (extraInfo & signatureMask) == miWpSignature && (extraInfo & 0x80); - if (fromTouch) - return false; + // Check for events synthesized from touch. Lower 7 bits are touch/pen index, bit 8 indicates touch. + // However, when tablet support is active, extraInfo is a packet serial number. This is not a problem + // since we do not want to ignore mouse events coming from a tablet. + const quint64 extraInfo = GetMessageExtraInfo(); + if ((extraInfo & signatureMask) == miWpSignature) { source = Qt::MouseEventSynthesizedBySystem; + const bool fromTouch = extraInfo & 0x80; // (else: Tablet PC) + if (fromTouch && !passSynthesizedMouseEvents) + return false; } #endif // !Q_OS_WINCE From 81698e5484bf5b6d0b6d948fb935a7b3218812b8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 26 Feb 2014 16:25:46 +0100 Subject: [PATCH 111/124] Widgets: Pass on mouse event source when translating mouse events. Change-Id: I70dacc2f96552e08dd71d5cbd63fb4cf9916c11f Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qwidgetwindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 0e40dd866f..3cc48b442d 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -407,6 +407,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) widgetPos = receiver->mapFromGlobal(event->globalPos()); QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos())); QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); + QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event)); e.setTimestamp(event->timestamp()); QApplicationPrivate::sendMouseEvent(receiver, &e, alien, m_widget, &qt_button_down, qt_last_mouse_receiver); } else { @@ -442,6 +443,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) if (win && win->geometry().contains(event->globalPos())) { const QPoint localPos = win->mapFromGlobal(event->globalPos()); QMouseEvent e(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers()); + QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event)); e.setTimestamp(event->timestamp()); QApplication::sendSpontaneousEvent(win, &e); } @@ -498,6 +500,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) // creation of a MouseButtonDblClick event. QTBUG-25831 QMouseEvent translated(event->type(), mapped, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); + QGuiApplicationPrivate::setMouseEventSource(&translated, QGuiApplicationPrivate::mouseEventSource(event)); translated.setTimestamp(event->timestamp()); QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget, &qt_button_down, qt_last_mouse_receiver); From d2cb81f8d9469e72d9c682c5f8832fbef31bed13 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 27 Feb 2014 14:12:39 +0100 Subject: [PATCH 112/124] Add missing notify signal for the QWindow::title property Similary to QWidget's windowTitleChanged, QWindow should also have a windowTitleChanges signal that's emitted when the title changed and declared as notify signal for the title property, so that QML bindings can be written against it. Change-Id: I6f107c6f0b43d6a959bc2ef96492e1f3e4c28bfe Reviewed-by: Paul Olav Tvete --- src/gui/kernel/qwindow.cpp | 8 +++++++- src/gui/kernel/qwindow.h | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 51548aa371..04a2615c81 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -727,9 +727,15 @@ Qt::WindowType QWindow::type() const void QWindow::setTitle(const QString &title) { Q_D(QWindow); - d->windowTitle = title; + bool changed = false; + if (d->windowTitle != title) { + d->windowTitle = title; + changed = true; + } if (d->platformWindow) d->platformWindow->setWindowTitle(title); + if (changed) + emit windowTitleChanged(title); } QString QWindow::title() const diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h index ca261ff7ce..3278b7233c 100644 --- a/src/gui/kernel/qwindow.h +++ b/src/gui/kernel/qwindow.h @@ -103,7 +103,7 @@ class Q_GUI_EXPORT QWindow : public QObject, public QSurface // C++ properties in qwindow.cpp AND as QML properties in qquickwindow.cpp. // http://qt-project.org/doc/qt-5.0/qtqml/qtqml-cppintegration-definetypes.html#type-revisions-and-versions - Q_PROPERTY(QString title READ title WRITE setTitle) + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY windowTitleChanged) Q_PROPERTY(Qt::WindowModality modality READ modality WRITE setModality NOTIFY modalityChanged) Q_PROPERTY(Qt::WindowFlags flags READ flags WRITE setFlags) Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged) @@ -297,6 +297,7 @@ Q_SIGNALS: void screenChanged(QScreen *screen); void modalityChanged(Qt::WindowModality modality); void windowStateChanged(Qt::WindowState windowState); + void windowTitleChanged(const QString &title); void xChanged(int arg); void yChanged(int arg); From c8cde619a5f53521c86114cec64b9dbe73e6fa55 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 24 Feb 2014 16:21:02 -0800 Subject: [PATCH 113/124] Fix ARM atomics for 8- and 16-bit types This has apparently never worked for any negative value. That's because the compiler sign-extends the incoming expectedValue to fill the 32-bit register, instead of zero-extending it, and it also expects any returned values to also be sign-extended. Task-number: QTBUG-37031 Change-Id: I836eddba7b1acc56bb0ac1d41de7001d06255b9b Reviewed-by: Sergio Ahumada --- src/corelib/arch/qatomic_armv6.h | 54 ++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h index 4f1c758ded..31a06541ed 100644 --- a/src/corelib/arch/qatomic_armv6.h +++ b/src/corelib/arch/qatomic_armv6.h @@ -90,6 +90,10 @@ template struct QBasicAtomicOps: QGenericAtomicOps static T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW; + +private: + template static inline T shrinkFrom32Bit(T value); + template static inline T extendTo32Bit(T value); }; template struct QAtomicOps : QBasicAtomicOps @@ -257,6 +261,36 @@ template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +// note: if T is signed, parameters are passed sign-extended in the +// registers. However, our 8- and 16-bit operations don't do sign +// extension. So we need to clear out the input on entry and sign-extend again +// on exit. +template template +T QBasicAtomicOps::shrinkFrom32Bit(T value) +{ + Q_STATIC_ASSERT(Size == 1 || Size == 2); + if (T(-1) > T(0)) + return value; // unsigned, ABI will zero extend + if (Size == 1) + asm volatile("and %0, %0, %1" : "+r" (value) : "I" (0xff)); + else + asm volatile("and %0, %0, %1" : "+r" (value) : "r" (0xffff)); + return value; +} + +template template +T QBasicAtomicOps::extendTo32Bit(T value) +{ + Q_STATIC_ASSERT(Size == 1 || Size == 2); + if (T(-1) > T(0)) + return value; // unsigned, ABI will zero extend + if (Size == 1) + asm volatile("sxtb %0, %0" : "+r" (value)); + else + asm volatile("sxth %0, %0" : "+r" (value)); + return value; +} + template<> template inline bool QBasicAtomicOps<1>::ref(T &_q_value) Q_DECL_NOTHROW { @@ -308,7 +342,7 @@ bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa "beq 0b\n" : [result] "=&r" (result), "+m" (_q_value) - : [expectedValue] "r" (expectedValue), + : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); @@ -330,11 +364,11 @@ bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa : [result] "=&r" (result), [tempValue] "=&r" (tempValue), "+m" (_q_value) - : [expectedValue] "r" (expectedValue), + : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); - *currentValue = tempValue; + *currentValue = extendTo32Bit(tempValue); return result == 0; } @@ -354,7 +388,7 @@ T QBasicAtomicOps<1>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHR : [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); - return originalValue; + return extendTo32Bit(originalValue); } template<> template inline @@ -376,7 +410,7 @@ T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType::AddScale), [_q_value] "r" (&_q_value) : "cc"); - return originalValue; + return extendTo32Bit(originalValue); } template<> template inline @@ -430,7 +464,7 @@ bool QBasicAtomicOps<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa "beq 0b\n" : [result] "=&r" (result), "+m" (_q_value) - : [expectedValue] "r" (expectedValue), + : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); @@ -452,11 +486,11 @@ bool QBasicAtomicOps<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newVa : [result] "=&r" (result), [tempValue] "=&r" (tempValue), "+m" (_q_value) - : [expectedValue] "r" (expectedValue), + : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); - *currentValue = tempValue; + *currentValue = extendTo32Bit(tempValue); return result == 0; } @@ -476,7 +510,7 @@ T QBasicAtomicOps<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHR : [newValue] "r" (newValue), [_q_value] "r" (&_q_value) : "cc"); - return originalValue; + return extendTo32Bit(originalValue); } template<> template inline @@ -498,7 +532,7 @@ T QBasicAtomicOps<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveTy : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType::AddScale), [_q_value] "r" (&_q_value) : "cc"); - return originalValue; + return extendTo32Bit(originalValue); } // Explanation from GCC's source code (config/arm/arm.c) on the modifiers below: From 3d50a0964587776c0915111947dc3401b21c158e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jan 2014 18:53:44 +0100 Subject: [PATCH 114/124] remove vestiges of uic class map code amends ad52be1ac. Change-Id: I2bfb10908217708c4f046d0d315dadd1b626da12 Reviewed-by: Joerg Bornemann --- bin/syncqt.pl | 2 -- 1 file changed, 2 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 8c1e04e0d0..8b7ea3b459 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -777,7 +777,6 @@ while ( @ARGV ) { # if we have no $basedir we cannot be sure which sources you want, so die die "Could not find any sync.profile for your module!\nPass to syncqt to sync your header files.\nsyncqt failed" if (!$basedir); -my $class_lib_map_contents = ""; our @ignore_headers = (); our @ignore_for_master_contents = (); our @ignore_for_include_check = (); @@ -940,7 +939,6 @@ foreach my $lib (@modules_to_sync) { if (defined $explicitheaders{$lib}{$class}) { $header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$explicitheaders{$lib}{$class}", 0, $ts)); } else { - $class_lib_map_contents .= "QT_CLASS_LIB($full_class, $lib, $header_base)\n"; $header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts)); } } From 6571aaf1c45885407038e03b0e9ed5952a06baeb Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jan 2014 19:34:49 +0100 Subject: [PATCH 115/124] merge %explicitheaders into %classnames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no need to have two mechanisms for the same thing. the values of %classnames can be comma-separated lists now, so one header can have multiple classes assigned. conversely, if an extracted class name reverse-maps to a different file name, it is omitted. Change-Id: Ia0a35d64764b6376f33b77bbfe59e1df70a3cf1a Reviewed-by: JÄ™drzej Nowacki Reviewed-by: Joerg Bornemann --- bin/syncqt.pl | 35 +++++++++++++++++------------------ sync.profile | 8 +------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 8b7ea3b459..2a1523bbbd 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -84,9 +84,12 @@ our $quoted_basedir; $INPUT_RECORD_SEPARATOR = "\r\n" if ($^O eq "msys"); # will be defined based on the modules sync.profile -our (%modules, %moduleheaders, @allmoduleheadersprivate, %classnames, %explicitheaders, %deprecatedheaders); +our (%modules, %moduleheaders, @allmoduleheadersprivate, %classnames, %deprecatedheaders); our @qpa_headers = (); +# will be derived from sync.profile +our %reverse_classnames = (); + # global variables (modified by options) my $isunix = 0; my $module = 0; @@ -206,8 +209,9 @@ sub classNames { my @ret; my ($iheader) = @_; - my $classname = $classnames{basename($iheader)}; - push @ret, $classname if ($classname); + my $ihdrbase = basename($iheader); + my $classname = $classnames{$ihdrbase}; + push @ret, split(/,/, $classname) if ($classname); my $parsable = ""; if(open(F, "<$iheader")) { @@ -306,6 +310,8 @@ sub classNames { foreach my $symbol (@symbols) { $symbol = (join("::", @namespaces) . "::" . $symbol) if (scalar @namespaces); + my $revhdr = $reverse_classnames{$symbol}; + next if (defined($revhdr) and $revhdr ne $ihdrbase); if ($symbol =~ /^Q[^:]*$/) { # no-namespace, starting with Q push @ret, $symbol; } elsif (defined($publicclassregexp)) { @@ -580,6 +586,13 @@ sub loadSyncProfile { die "syncqt couldn't parse $syncprofile: $@" if $@; die "syncqt couldn't execute $syncprofile: $!" unless defined $result; } + + for my $fn (keys %classnames) { + for my $cn (split(/,/, $classnames{$fn})) { + $reverse_classnames{$cn} = $fn; + } + } + return $result; } @@ -936,17 +949,8 @@ foreach my $lib (@modules_to_sync) { # class =~ s,::,/,g; # } - if (defined $explicitheaders{$lib}{$class}) { - $header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$explicitheaders{$lib}{$class}", 0, $ts)); - } else { - $header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts)); - } + $header_copies++ if (syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts)); } - - if ($explicitheaders{$lib}{basename($header)}) { - $header_copies++ if(syncHeader($lib, "$out_basedir/include/$lib/$explicitheaders{$lib}{basename($header)}", "$out_basedir/include/$lib/$header", 0, $ts)); - } - } elsif ($create_private_headers && !$qpa_header) { @headers = ( "$out_basedir/include/$lib/$module_version/$lib/private/$header" ); } elsif ($create_private_headers) { @@ -975,11 +979,6 @@ foreach my $lib (@modules_to_sync) { $pri_install_classes .= $class_header unless($pri_install_classes =~ $class_header); } - if ($explicitheaders{$lib}{basename($iheader)}) { - my $compat_header = fixPaths("$out_basedir/include/$lib/$explicitheaders{$lib}{basename($iheader)}", - $dir) . " "; - $pri_install_files .= $compat_header unless($pri_install_files =~ $compat_header); - } $pri_install_files.= "$pri_install_iheader ";; } } diff --git a/sync.profile b/sync.profile index 7bd10b4865..9c759297ce 100644 --- a/sync.profile +++ b/sync.profile @@ -31,6 +31,7 @@ "qevent.h" => "QtEvents", "qnamespace.h" => "Qt", "qnumeric.h" => "QtNumeric", + "qvariant.h" => "QVariantHash,QVariantList,QVariantMap", "qsql.h" => "QSql", "qssl.h" => "QSsl", "qtest.h" => "QTest", @@ -44,13 +45,6 @@ "QGenericPluginFactory" => "QtGui/QGenericPluginFactory" } ); -%explicitheaders = ( - "QtCore" => { - "QVariantHash" => "qvariant.h", - "QVariantList" => "qvariant.h", - "QVariantMap" => "qvariant.h", - } -); @qpa_headers = ( qr/^qplatform/, qr/^qwindowsystem/ ); my @angle_headers = ('egl.h', 'eglext.h', 'eglplatform.h', 'gl2.h', 'gl2ext.h', 'gl2platform.h', 'ShaderLang.h', 'khrplatform.h'); From 40babf8b4a039bc8671696c74d8e22c719c30021 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jan 2014 20:27:00 +0100 Subject: [PATCH 116/124] un-pluralize code since ever we've thrown out the phonon hack, each header is synced to only one location (CamelCase headers notwithstanding). Change-Id: Idfef33db9410908aefe309bc7a3edeae5fc5a671 Reviewed-by: Joerg Bornemann --- bin/syncqt.pl | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 2a1523bbbd..6ae4128b81 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -937,9 +937,9 @@ foreach my $lib (@modules_to_sync) { } else { my $ts = (stat($iheader))[9]; #find out all the places it goes.. - my @headers; + my $oheader; if ($public_header) { - @headers = ( "$out_basedir/include/$lib/$header" ); + $oheader = "$out_basedir/include/$lib/$header"; foreach my $full_class (@classes) { my $header_base = basename($header); # Strip namespaces: @@ -952,14 +952,11 @@ foreach my $lib (@modules_to_sync) { $header_copies++ if (syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts)); } } elsif ($create_private_headers && !$qpa_header) { - @headers = ( "$out_basedir/include/$lib/$module_version/$lib/private/$header" ); + $oheader = "$out_basedir/include/$lib/$module_version/$lib/private/$header"; } elsif ($create_private_headers) { - @headers = ( "$out_basedir/include/$lib/$module_version/$lib/qpa/$header" ); - } - - foreach(@headers) { #sync them - $header_copies++ if (syncHeader($lib, $_, $iheader, $copy_headers, $ts)); + $oheader = "$out_basedir/include/$lib/$module_version/$lib/qpa/$header"; } + $header_copies++ if (syncHeader($lib, $oheader, $iheader, $copy_headers, $ts)); if($public_header) { #put it into the master file From e8b2ff63ec47b2f212bb0a92d59a0b5f9e8fb168 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jan 2014 21:00:49 +0100 Subject: [PATCH 117/124] remove duplicated nested condition Change-Id: I433773dbf21a7a7625d4f763b3cebe75c746aa1f Reviewed-by: Joerg Bornemann --- bin/syncqt.pl | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 6ae4128b81..a2f1b02fcc 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -963,21 +963,18 @@ foreach my $lib (@modules_to_sync) { $master_contents .= "#include \"$public_header\"\n" if (shouldMasterInclude($iheader)); #deal with the install directives - if($public_header) { - my $pri_install_iheader = fixPaths($iheader, $dir); - foreach my $class (@classes) { - # Strip namespaces: - $class =~ s/^.*:://; - # if ($class =~ m/::/) { - # $class =~ s,::,/,g; - # } - my $class_header = fixPaths("$out_basedir/include/$lib/$class", - $dir) . " "; - $pri_install_classes .= $class_header - unless($pri_install_classes =~ $class_header); - } - $pri_install_files.= "$pri_install_iheader ";; + my $pri_install_iheader = fixPaths($iheader, $dir); + foreach my $class (@classes) { + # Strip namespaces: + $class =~ s/^.*:://; +# if ($class =~ m/::/) { +# $class =~ s,::,/,g; +# } + my $class_header = fixPaths("$out_basedir/include/$lib/$class", $dir) . " "; + $pri_install_classes .= $class_header + unless($pri_install_classes =~ $class_header); } + $pri_install_files.= "$pri_install_iheader ";; } elsif ($qpa_header) { my $pri_install_iheader = fixPaths($iheader, $dir); From 46feffea1b08767ab8753843beb2d0f93e4a637f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 30 Jan 2014 21:01:23 +0100 Subject: [PATCH 118/124] de-duplicate header install source calculation Change-Id: I7c26d70fdfceac6d3c562e704cc725fad80c4f59 Reviewed-by: Joerg Bornemann --- bin/syncqt.pl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index a2f1b02fcc..bbd514e58b 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -958,12 +958,12 @@ foreach my $lib (@modules_to_sync) { } $header_copies++ if (syncHeader($lib, $oheader, $iheader, $copy_headers, $ts)); + my $pri_install_iheader = fixPaths($iheader, $dir); if($public_header) { #put it into the master file $master_contents .= "#include \"$public_header\"\n" if (shouldMasterInclude($iheader)); #deal with the install directives - my $pri_install_iheader = fixPaths($iheader, $dir); foreach my $class (@classes) { # Strip namespaces: $class =~ s/^.*:://; @@ -977,11 +977,9 @@ foreach my $lib (@modules_to_sync) { $pri_install_files.= "$pri_install_iheader ";; } elsif ($qpa_header) { - my $pri_install_iheader = fixPaths($iheader, $dir); $pri_install_qpafiles.= "$pri_install_iheader ";; } else { - my $pri_install_iheader = fixPaths($iheader, $dir); $pri_install_pfiles.= "$pri_install_iheader ";; } } From 13455344d7e55118733dfca6abba8662a334eba6 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 3 Feb 2014 21:19:48 +0100 Subject: [PATCH 119/124] move generation of qconfig.h forwarding headers to qtbase.pro less platform-specific code. the qfeatures.h generation is already here. Change-Id: Ied69fb431eed5816fbff63b33be431ee913c2bc8 Reviewed-by: Joerg Bornemann --- configure | 17 ----------------- qtbase.pro | 8 ++++++++ tools/configure/configureapp.cpp | 17 ----------------- 3 files changed, 8 insertions(+), 34 deletions(-) diff --git a/configure b/configure index 88ec0256cc..5b57f8fa55 100755 --- a/configure +++ b/configure @@ -6438,23 +6438,6 @@ else mv -f "$outpath/src/corelib/global/qconfig.h.new" "$outpath/src/corelib/global/qconfig.h" fi -# create a forwarding header -mkdir -p "$outpath/include/QtCore" || exit -echo '#include "../../src/corelib/global/qconfig.h"' > $outpath/include/QtCore/qconfig.h.new -if cmp -s "$outpath/include/QtCore/qconfig.h.new" "$outpath/include/QtCore/qconfig.h"; then - rm -f "$outpath/include/QtCore/qconfig.h.new" -else - mv "$outpath/include/QtCore/qconfig.h.new" "$outpath/include/QtCore/qconfig.h" || exit -fi - -# create a camelcase forwarding header -echo '#include "qconfig.h"' > $outpath/include/QtCore/QtConfig.new -if cmp -s "$outpath/include/QtCore/QtConfig.new" "$outpath/include/QtCore/QtConfig"; then - rm -f "$outpath/include/QtCore/QtConfig.new" -else - mv "$outpath/include/QtCore/QtConfig.new" "$outpath/include/QtCore/QtConfig" || exit -fi - #------------------------------------------------------------------------------- # save configuration into qconfig.pri #------------------------------------------------------------------------------- diff --git a/qtbase.pro b/qtbase.pro index 1cd82bbc84..ed6fc394cb 100644 --- a/qtbase.pro +++ b/qtbase.pro @@ -177,6 +177,14 @@ FEATURES_PRI = \ "QT_DISABLED_FEATURES = \$\$unique(QT_DISABLED_FEATURES)" write_file($$OUT_PWD/mkspecs/qfeatures.pri, FEATURES_PRI)|error("Aborting.") +# Create forwarding headers for qconfig.h +FWD_QCONFIG_H = \ + '$${LITERAL_HASH}include "../../src/corelib/global/qconfig.h"' +write_file($$OUT_PWD/include/QtCore/qconfig.h, FWD_QCONFIG_H)|error("Aborting.") +FWD_QTCONFIG = \ + '$${LITERAL_HASH}include "qconfig.h"' +write_file($$OUT_PWD/include/QtCore/QtConfig, FWD_QTCONFIG)|error("Aborting.") + #mkspecs mkspecs.path = $$[QT_HOST_DATA]/mkspecs mkspecs.files = \ diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index ac794d4c43..9995fb179e 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -3520,23 +3520,6 @@ void Configure::generateConfigfiles() dictionary[ "DONE" ] = "error"; } - { - FileWriter tmpStream(buildPath + "/include/QtCore/qconfig.h"); - - tmpStream << "#include \"../../src/corelib/global/qconfig.h\"" << endl; - - if (!tmpStream.flush()) - dictionary[ "DONE" ] = "error"; - } - { - FileWriter tmpStream(buildPath + "/include/QtCore/QtConfig"); - - tmpStream << "#include \"qconfig.h\"" << endl; - - if (!tmpStream.flush()) - dictionary[ "DONE" ] = "error"; - } - if (dictionary["EDITION"] == "Evaluation" || qmakeDefines.contains("QT_EVAL")) { FileWriter tmpStream(buildPath + "/src/corelib/global/qconfig_eval.cpp"); From f8c5dd9857211601e2ea4b704df92e240b2c3b4b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 3 Feb 2014 22:22:14 +0100 Subject: [PATCH 120/124] automate handling of generated headers some more let the syncqt + qt_module_header.prf pair handle generation of forwarding headers. in qtbase this is ineffective to some degree, as the need to create QtCore's forwarding headers early for QtBootstrap requires qtbase.pro already doing the real work, but at least we get the verification that nothing breaks. Other Modules (TM) will need the full functionality. Change-Id: Ifd3dfa05c4c8a91698a365160edb6dabc84e553f Reviewed-by: Joerg Bornemann --- bin/syncqt.pl | 23 +++++++++++++++++++---- mkspecs/features/qt_module_headers.prf | 14 ++++++++++++++ src/corelib/global/global.pri | 9 --------- sync.profile | 1 + 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index bbd514e58b..826d3fc6fa 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -833,6 +833,7 @@ foreach my $lib (@modules_to_sync) { my $pri_install_files = ""; my $pri_install_pfiles = ""; my $pri_install_qpafiles = ""; + my $pri_injections = ""; my $libcapitals = uc($lib); my $master_contents = @@ -905,8 +906,15 @@ foreach my $lib (@modules_to_sync) { #calc files and "copy" them foreach my $subdir (@subdirs) { my @headers = findFiles($subdir, "^[-a-z0-9_]*\\.h\$" , 0); + if (defined $inject_headers{$subdir}) { + foreach my $if (@{$inject_headers{$subdir}}) { + @headers = grep(!/^\Q$if\E$/, @headers); #in case we configure'd previously + push @headers, "*".$if; + } + } my $header_dirname = ""; foreach my $header (@headers) { + my $shadow = ($header =~ s/^\*//); $header = 0 if($header =~ /^ui_.*.h/); foreach (@ignore_headers) { $header = 0 if($header eq $_); @@ -928,6 +936,7 @@ foreach my $lib (@modules_to_sync) { } my $iheader = $subdir . "/" . $header; + $iheader =~ s/^\Q$basedir\E/$out_basedir/ if ($shadow); my @classes = $public_header && (!$minimal && $is_qt) ? classNames($iheader) : (); if($showonly) { print "$header [$lib]\n"; @@ -935,7 +944,7 @@ foreach my $lib (@modules_to_sync) { print "SYMBOL: $_\n"; } } else { - my $ts = (stat($iheader))[9]; + my $ts = $shadow ? 0 : (stat($iheader))[9]; #find out all the places it goes.. my $oheader; if ($public_header) { @@ -949,19 +958,20 @@ foreach my $lib (@modules_to_sync) { # class =~ s,::,/,g; # } - $header_copies++ if (syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts)); + $header_copies++ if (!$shadow && syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts)); } } elsif ($create_private_headers && !$qpa_header) { $oheader = "$out_basedir/include/$lib/$module_version/$lib/private/$header"; } elsif ($create_private_headers) { $oheader = "$out_basedir/include/$lib/$module_version/$lib/qpa/$header"; } - $header_copies++ if (syncHeader($lib, $oheader, $iheader, $copy_headers, $ts)); + $header_copies++ if (!$shadow && syncHeader($lib, $oheader, $iheader, $copy_headers, $ts)); my $pri_install_iheader = fixPaths($iheader, $dir); + my $injection = ""; if($public_header) { #put it into the master file - $master_contents .= "#include \"$public_header\"\n" if (shouldMasterInclude($iheader)); + $master_contents .= "#include \"$public_header\"\n" if (!$shadow && shouldMasterInclude($iheader)); #deal with the install directives foreach my $class (@classes) { @@ -973,6 +983,7 @@ foreach my $lib (@modules_to_sync) { my $class_header = fixPaths("$out_basedir/include/$lib/$class", $dir) . " "; $pri_install_classes .= $class_header unless($pri_install_classes =~ $class_header); + $injection .= ":$class"; } $pri_install_files.= "$pri_install_iheader ";; } @@ -982,6 +993,9 @@ foreach my $lib (@modules_to_sync) { else { $pri_install_pfiles.= "$pri_install_iheader ";; } + $pri_injections .= fixPaths($iheader, "$out_basedir/include/$lib") + .":".fixPaths($oheader, "$out_basedir/include/$lib") + .$injection." " if ($shadow); } if ($verbose_level && $header_copies) { @@ -1112,6 +1126,7 @@ foreach my $lib (@modules_to_sync) { $headers_pri_contents .= "SYNCQT.HEADER_CLASSES = $pri_install_classes\n"; $headers_pri_contents .= "SYNCQT.PRIVATE_HEADER_FILES = $pri_install_pfiles\n"; $headers_pri_contents .= "SYNCQT.QPA_HEADER_FILES = $pri_install_qpafiles\n"; + $headers_pri_contents .= "SYNCQT.INJECTIONS = $pri_injections\n"; my $headers_pri_file = "$out_basedir/include/$lib/headers.pri"; writeFile($headers_pri_file, $headers_pri_contents, $lib, "headers.pri file"); } diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index ca26eb674b..0baa9ec7b2 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -35,6 +35,20 @@ else: \ INC_PATH = $$MODULE_BASE_INDIR include($$INC_PATH/include/$$MODULE_INCNAME/headers.pri, "", true) +for (injection, SYNCQT.INJECTIONS) { + injects = $$split(injection, :) + fwd_hdr = $$member(injects, 1) + MAIN_FWD = $$INC_PATH/include/$$MODULE_INCNAME/$$fwd_hdr + MAIN_FWD_CONT = '$${LITERAL_HASH}include "$$member(injects, 0)"' + write_file($$MAIN_FWD, MAIN_FWD_CONT)|error("Aborting.") + injects = $$member(injects, 2, -1) + for (inject, injects) { + CLASS_FWD = $$INC_PATH/include/$$MODULE_INCNAME/$$inject + CLASS_FWD_CONT = '$${LITERAL_HASH}include "$$fwd_hdr"' + write_file($$CLASS_FWD, CLASS_FWD_CONT)|error("Aborting.") + } +} + autogen_warning = \ "/* This file was generated by qmake with the info from /$$relative_path($$_PRO_FILE_, $$MODULE_BASE_INDIR). */" diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 789f500cab..efa585ff3e 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -29,15 +29,6 @@ SOURCES += \ # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global -# configure creates these, not syncqt, so we need to manually inject them -qconfig_h_files = \ - $$OUT_PWD/global/qfeatures.h \ - $$OUT_PWD/global/qconfig.h \ - $$QT_BUILD_TREE/include/QtCore/QtConfig -targ_headers.files += $$qconfig_h_files -contains(QMAKE_BUNDLE_DATA, FRAMEWORK_HEADERS): \ - FRAMEWORK_HEADERS.files += $$qconfig_h_files - # Only used on platforms with CONFIG += precompile_header PRECOMPILED_HEADER = global/qt_pch.h diff --git a/sync.profile b/sync.profile index 9c759297ce..9823aa16bd 100644 --- a/sync.profile +++ b/sync.profile @@ -24,6 +24,7 @@ %classnames = ( "qglobal.h" => "QtGlobal", "qendian.h" => "QtEndian", + "qconfig.h" => "QtConfig", "qplugin.h" => "QtPlugin", "qalgorithms.h" => "QtAlgorithms", "qcontainerfwd.h" => "QtContainerFwd", From 1e29bf5b07ef60b8a8c14915bc3bcce4209b04ef Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 26 Feb 2014 16:48:33 +0100 Subject: [PATCH 121/124] Do not assume nice behavior in error handling SPDY is currently assuming it will only receive RST_STREAM messages on active steams. This is however not always a safe assumption. Task-number: QTBUG-37100 Change-Id: Ied89a68a209891992ad72daa513066efc1d7c421 Reviewed-by: Peter Hartmann --- src/network/access/qspdyprotocolhandler.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/access/qspdyprotocolhandler.cpp b/src/network/access/qspdyprotocolhandler.cpp index d9d861f9b4..098b3e9ab0 100644 --- a/src/network/access/qspdyprotocolhandler.cpp +++ b/src/network/access/qspdyprotocolhandler.cpp @@ -959,7 +959,6 @@ void QSpdyProtocolHandler::handleRST_STREAM(char /*flags*/, quint32 length, Q_UNUSED(length); // silence -Wunused-parameter qint32 streamID = getStreamID(frameData.constData()); QHttpNetworkReply *httpReply = m_inFlightStreams.value(streamID).second; - Q_ASSERT(httpReply); qint32 statusCodeInt = fourBytesToInt(frameData.constData() + 4); RST_STREAM_STATUS_CODE statusCode = static_cast(statusCodeInt); @@ -1016,7 +1015,8 @@ void QSpdyProtocolHandler::handleRST_STREAM(char /*flags*/, quint32 length, errorCode = QNetworkReply::ProtocolFailure; errorMessage = "got SPDY RST_STREAM message with unknown error code"; } - replyFinishedWithError(httpReply, streamID, errorCode, errorMessage.constData()); + if (httpReply) + replyFinishedWithError(httpReply, streamID, errorCode, errorMessage.constData()); } void QSpdyProtocolHandler::handleSETTINGS(char flags, quint32 /*length*/, const QByteArray &frameData) @@ -1266,6 +1266,7 @@ void QSpdyProtocolHandler::replyFinished(QHttpNetworkReply *httpReply, qint32 st void QSpdyProtocolHandler::replyFinishedWithError(QHttpNetworkReply *httpReply, qint32 streamID, QNetworkReply::NetworkError errorCode, const char *errorMessage) { + Q_ASSERT(httpReply); httpReply->d_func()->state = QHttpNetworkReplyPrivate::SPDYClosed; int streamsRemoved = m_inFlightStreams.remove(streamID); Q_ASSERT(streamsRemoved == 1); From 82e699cab0eb6a209c06607e297803fd127f5e63 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Wed, 26 Feb 2014 09:18:35 +0100 Subject: [PATCH 122/124] tst_qtjson: Mark some test as XFAIL on BlackBerry 10 These tests seem to fail because denormalized numbers are not supported on QNX yet, so marking them as expected failures. - testNumbers_2() - toJsonLargeNumericValues() - parseNumbers() Task-number: QTBUG-37066 Change-Id: Ifec95b936fb70253395dee4d1ca18e85870486a3 Reviewed-by: Fabian Bumberger --- tests/auto/corelib/json/tst_qtjson.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp index aee5875613..6736a33405 100644 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ b/tests/auto/corelib/json/tst_qtjson.cpp @@ -360,6 +360,10 @@ void tst_QtJson::testNumbers_2() QJsonDocument jDocument2(QJsonDocument::fromJson(ba)); for (int power = 0; power <= 1075; power++) { floatValues_1[power] = jDocument2.object().value(QString::number(power)).toDouble(); +#ifdef Q_OS_BLACKBERRY + if (power >= 970) + QEXPECT_FAIL("", "See QTBUG-37066", Abort); +#endif QVERIFY2(floatValues[power] == floatValues_1[power], QString("floatValues[%1] != floatValues_1[%1]").arg(power).toLatin1()); } @@ -1299,11 +1303,17 @@ void tst_QtJson::toJsonLargeNumericValues() " ]\n" "}\n"; +#ifdef Q_OS_BLACKBERRY + QEXPECT_FAIL("", "See QTBUG-37066", Continue); +#endif QCOMPARE(json, expected); QJsonDocument doc; doc.setObject(object); json = doc.toJson(); +#ifdef Q_OS_BLACKBERRY + QEXPECT_FAIL("", "See QTBUG-37066", Continue); +#endif QCOMPARE(json, expected); } @@ -1705,6 +1715,10 @@ void tst_QtJson::parseNumbers() json += numbers[i].str; json += " ]"; QJsonDocument doc = QJsonDocument::fromJson(json); +#ifdef Q_OS_BLACKBERRY + if (0 == QString::compare(numbers[i].str, "1.1e-308")) + QEXPECT_FAIL("", "See QTBUG-37066", Abort); +#endif QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); From e5870b61c6efb4b31d675fa4ea88ea6a5f9e1db4 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Wed, 26 Feb 2014 12:12:38 +0100 Subject: [PATCH 123/124] tst_qnumeric: Mark some tests as XFAIL on BlackBerry 10 These tests seem to fail because denormalized numbers are not supported on QNX yet, so marking them as expected failures. - floatDistance(denormal) - floatDistance_double(denormal) Task-number: QTBUG-37094 Change-Id: I79dbc78da6e9bef8466264fd2cab4af0ee8b868f Reviewed-by: Fabian Bumberger --- tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp index 36e01a0ccd..79df4b7055 100644 --- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp +++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp @@ -167,6 +167,9 @@ void tst_QNumeric::floatDistance() QFETCH(float, val1); QFETCH(float, val2); QFETCH(quint32, expectedDistance); +#ifdef Q_OS_BLACKBERRY + QEXPECT_FAIL("denormal", "See QTBUG-37094", Continue); +#endif QCOMPARE(qFloatDistance(val1, val2), expectedDistance); } @@ -211,6 +214,9 @@ void tst_QNumeric::floatDistance_double() QFETCH(double, val1); QFETCH(double, val2); QFETCH(quint64, expectedDistance); +#ifdef Q_OS_BLACKBERRY + QEXPECT_FAIL("denormal", "See QTBUG-37094", Continue); +#endif QCOMPARE(qFloatDistance(val1, val2), expectedDistance); } From 0d0fb04d505d105fb4b2fc71d68f729ce670b12e Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Thu, 20 Feb 2014 19:16:01 +0100 Subject: [PATCH 124/124] Make QTreeView::expand/collapse check for ineffectual invocations Added checks if item is already expanded/collapsed to QTreeView::expand/collapse since the following computations can be quite expensive. (This is useful when saving/restoring a lot of item expansion state e.g. after a model reset.) Task-number: QTBUG-35939 Change-Id: I82c4489f9fe0b8ac61994652a60312e34c46f628 Reviewed-by: Stephen Kelly --- src/widgets/itemviews/qtreeview.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index dd430435f3..781dd345bd 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -754,6 +754,8 @@ void QTreeView::expand(const QModelIndex &index) return; if (index.flags() & Qt::ItemNeverHasChildren) return; + if (d->isIndexExpanded(index)) + return; if (d->delayedPendingLayout) { //A complete relayout is going to be performed, just store the expanded index, no need to layout. if (d->storeExpanded(index)) @@ -785,6 +787,8 @@ void QTreeView::collapse(const QModelIndex &index) Q_D(QTreeView); if (!d->isIndexValid(index)) return; + if (!d->isIndexExpanded(index)) + return; //if the current item is now invisible, the autoscroll will expand the tree to see it, so disable the autoscroll d->delayedAutoScroll.stop();